Как мне создать GUI, используя Swing, который выбирает два элемента из списка и предоставляет пользователю две кнопки, чтобы он мог выбрать победителя? - PullRequest
0 голосов
/ 10 июля 2020

Я работаю со списком элементов, которые хочу ранжировать. В идеале программа могла бы случайным образом выбрать 2 элемента для сравнения и представить их, отсортировать список с новым рейтингом, а затем выбрать еще 2, чтобы пользователь мог выбирать победителя снова и снова, пока пользователь не остановился. Части, с которыми у меня возникают проблемы:

  1. получение кнопки для взаимодействия с объектом для изменения его ранга и
  2. закрытие и повторное открытие JFrame с новыми элементами для сравнения

Я создал класс под названием action, который должен обрабатывать клики:

public class action extends JFrame implements ActionListener{
  private JButton b1;
  private JButton b2;
  private JButton b3;
  private JPanel jp;


  public action(Bond one, Bond two){
    //JFrame mf = new JFrame("My Frame");
    //JPanel jp = new JPanel();
    jp = new JPanel();
    setSize(500,500);
    setVisible(true);
    setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
    b1 = new JButton(one.name+"\nRating: "+one.rating);
    b1.addActionListener(this);
    b2 = new JButton(two.name);
    b2.addActionListener(this);
    b3 = new JButton("Tie");
    b3.addActionListener(this);
    jp.add(b1);
    jp.add(b2);
    jp.add(b3);
    add(jp);
  }
  public void actionPerformed(ActionEvent e){
    int clickCount = 0;
    if (clickCount > 3) {
      System.exit(0);
    }
    JOptionPane jo = new JOptionPane();
    if(e.getSource() == b1){
      //  jo.showMessageDialog(null, "button 1");
      clickCount++;
      //System.exit(0);
    }
    if(e.getSource() == b2){
      jo.showMessageDialog(null, "button 2");
      clickCount++;
      //System.exit(0);
    }
    if(e.getSource() == b3){
      jo.showMessageDialog(null, "button 3");
      clickCount++;
      //System.exit(0);
    }
  }
}

И вот как я вызываю класс action из основного:

    while(compCount < 3){
      //these generate random numbers that correspond with the index of the elements to be compared
      //comp is the name of the list of objects
      int r1 = r.nextInt(comp.size());
      int r2 = r.nextInt(comp.size());
      int t;
      if(r1 == r2){
        continue;
      }
      else{
        action a = new action(comp.get(r1), comp.get(r2));
        compCount++;
      }
    }

В настоящее время это просто создает 3 всплывающих окна windows, которые ничего не делают, когда я нажимаю кнопки. Любая помощь или понимание будут оценены!

1 Ответ

1 голос
/ 13 июля 2020

ОП хочет сделать сложный Swing GUI. Он не предоставил минимального, работоспособного примера, поэтому я создал свой собственный.

Лучший способ создать сложный Swing GUI - это построить его по одной маленькой части за раз. Тестируя каждый маленький кусок по отдельности, вы тоже можете построить сложный GUI.

Вот созданный мной GUI.

Favorite Character GUI

The object of this game is to choose your favorite characters from the lower case characters of the English alphabet. You can left-click on the Pass button if neither character is among your favorites.

I'd already written the JPanel to display a character for a previous Ответ на переполнение стека .

Первое, что я сделал, это создал главный класс. Я назвал этот класс FavoriteCharacter.

Я вызвал метод SwingUtilities invokeLater, чтобы гарантировать, что компоненты Swing были созданы и выполнены в потоке отправки событий .

Затем я написал код JFrame. Код JFrame почти идентичен для всех созданных мной Swing GUI. Код JFrame находится в методе run класса FavoriteCharacter.

Затем я написал класс модели, класс LetterMap. Каждый раз, когда я создаю сложный Swing GUI, я использую шаблон модель / представление / контроллер . Эта модель довольно проста. У меня есть карта, которая содержит символы нижнего регистра английского sh алфавита, а также подсчет голосов.

После того, как модель заработала, я вернулся к созданию представления. Каждая небольшая часть GUI содержится в методе класса FavoriteCharacter. Таким образом, я мог тестировать каждую маленькую часть представления индивидуально. Не надо бросать спагетти-код об стену и смотреть, что мне нравится.

Фактическое рисование персонажей происходит в классе LetterPanel. Все пользовательские раскраски Swing должны выполняться методом paintComponent из JPanel.

После того, как я закончил GUI, я работал над двумя классами контроллеров, PassListener и VoteListener. PassListener вызывает метод в классе FavoriteCharacters для выбора другой пары символов. VoteListener обновляет модельный класс LetterMap, отображает общее количество голосов для выбранного символа в JOptionPane и выбирает другую пару букв.

Вот пример кода для запуска.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class FavoriteCharacter implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new FavoriteCharacter());
    }

    private char[] letterPair;

    private JFrame frame;

    private LetterMap letterMap;

    private LetterPanel letterPanel1;
    private LetterPanel letterPanel2;

    public FavoriteCharacter() {
        this.letterMap = new LetterMap();
        this.letterPair = letterMap.pickTwo();
    }

    @Override
    public void run() {
        frame = new JFrame("Favorite Character");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createTitlePanel(),
                BorderLayout.BEFORE_FIRST_LINE);
        frame.add(createMainPanel(letterPair),
                BorderLayout.CENTER);
        frame.add(createSkipPanel(),
                BorderLayout.AFTER_LAST_LINE);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createTitlePanel() {
        JPanel panel = new JPanel();

        JLabel label = new JLabel("Vote for your favorite character");
        label.setHorizontalAlignment(JLabel.CENTER);
        panel.add(label);

        return panel;
    }

    private JPanel createMainPanel(char[] letterPair) {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));

        panel.add(Box.createHorizontalStrut(10));
        letterPanel1 = new LetterPanel(Color.WHITE, letterPair[0]);
        panel.add(createLetterPanel(letterPanel1, "0"));

        panel.add(Box.createHorizontalStrut(10));

        letterPanel2 = new LetterPanel(Color.WHITE, letterPair[1]);
        panel.add(createLetterPanel(letterPanel2, "1"));

        panel.add(Box.createHorizontalStrut(10));

        return panel;
    }

    private void updateLetterPanels() {
        letterPanel1.setLetter(letterPair[0]);
        letterPanel2.setLetter(letterPair[1]);

        letterPanel1.repaint();
        letterPanel2.repaint();
    }

    private void updateLetterPair() {
        letterPair = letterMap.pickTwo();
        System.out.println(Arrays.toString(letterPair));
        updateLetterPanels();
    }

    private JPanel createLetterPanel(LetterPanel letterPanel,
            String actionCommand) {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(0, 10, 10, 10);
        gbc.weightx = 0d;
        panel.add(letterPanel, gbc);

        gbc.gridy++;
        gbc.weightx = 1d;
        JButton button = new JButton("Vote");
        button.setActionCommand(actionCommand);
        button.setHorizontalAlignment(JButton.CENTER);
        button.addActionListener(new VoteListener());
        panel.add(button, gbc);

        return panel;
    }

    private JPanel createSkipPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(0, 18, 10, 18);
        gbc.weightx = 1d;

        JButton button = new JButton("Pass");
        button.setHorizontalAlignment(JButton.CENTER);
        button.addActionListener(new PassListener());
        panel.add(button, gbc);

        return panel;
    }

    public class LetterPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private char letter;

        private Color backgroundColor;

        private Font font;

        public LetterPanel(Color backgroundColor, char letter) {
            this.backgroundColor = backgroundColor;
            this.letter = letter;
            this.font = getFont().deriveFont(96f)
                    .deriveFont(Font.BOLD);
            this.setBorder(BorderFactory.createLineBorder(
                    Color.GREEN, 6));
            this.setPreferredSize(new Dimension(120, 200));
        }

        public void setLetter(char letter) {
            this.letter = letter;
        }

        public char getLetter() {
            return letter;
        }

        public LetterPanel getLetterPanel() {
            return this;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(backgroundColor);
            g2d.fillRect(0, 0, getWidth(), getHeight());

            g2d.setColor(Color.BLACK);
            drawCenteredString(g2d, Character.toString(letter),
                    font);
        }

        /**
         * Draw a String centered in the middle of the panel.
         *
         * @param g2d The Graphics2D instance.
         * @param text The String to draw.
         * @param font The Font to draw with.
         */
        public void drawCenteredString(Graphics2D g2d,
                String text, Font font) {
            FontMetrics metrics = g2d.getFontMetrics(font);
            int x = (getWidth() - metrics.stringWidth(text)) / 2;
            int y = ((getHeight() - metrics.getHeight()) / 2) +
                    metrics.getAscent();
            g2d.setFont(font);
            g2d.drawString(text, x, y);
        }

    }

    public class PassListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            updateLetterPair();
        }

    }

    public class VoteListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            int index = Integer.valueOf(event.getActionCommand());
            char c = letterPair[index];
            letterMap.addVote(c);
            int votes = letterMap.getVotes(c);

            showMessageDialog(c, votes);
        }

        private void showMessageDialog(char c, int votes) {
            String text = "The character '" + c + "' has ";
            text += Integer.toString(votes);
            if (votes == 1) {
                text += " vote.";
            } else {
                text += " votes.";
            }

            JOptionPane.showMessageDialog(frame, text);
            updateLetterPair();
        }

    }

    public class LetterMap {

        private Map<Character, Integer> letterMap;

        private Random random;

        public LetterMap() {
            this.letterMap = createLetterMap();
            this.random = new Random();
        }

        private Map<Character, Integer> createLetterMap() {
            Map<Character, Integer> letterMap = new TreeMap<>();

            for (int i = 0; i < 26; i++) {
                Character c = (char) (i + 'a');
                letterMap.put(c, 0);
            }
            return letterMap;
        }

        public char[] pickTwo() {
            int index1 = random.nextInt(letterMap.size());
            int index2 = random.nextInt(letterMap.size());
            while (index2 == index1) {
                index2 = random.nextInt(letterMap.size());
            }

            char[] output = new char[2];
            Set<Character> letterSet = letterMap.keySet();
            Iterator<Character> iter = letterSet.iterator();

            int count = 0;
            int index3 = 0;
            while (iter.hasNext() && index3 < 2) {
                Character key = iter.next();
                if (count == index1 || count == index2) {
                    if (index3 < 2) {
                        output[index3++] = key;
                    }
                }
                count++;
            }

            return output;
        }

        public void addVote(char c) {
            Integer vote = getVotes(c);
            letterMap.put(c, ++vote);
        }

        public int getVotes(char c) {
            return letterMap.get(c);
        }

    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...