首页 > 解决方案 > 如何使用 Swing 制作一个 GUI,从列表中选择两个元素并向用户显示两个按钮,以便他们选择获胜者?

问题描述

我正在处理我想要排名的元素列表。理想情况下,程序会随机选择 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);
    }
  }
}

以下是我从我的主要调用动作类的方式:

    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 个弹出窗口,当我单击按钮时它们什么都不做。任何帮助或见解将不胜感激!

标签: javaswinguser-interface

解决方案


OP 想要制作一个复杂的 Swing GUI。他没有提供最小的、可运行的示例,所以我创建了自己的示例。

制作复杂的 Swing GUI 的最佳方式是一次构建一小块。通过单独测试每个小块,您也可以构建一个复杂的 GUI。

这是我创建的 GUI。

最喜欢的角色 GUI

这个游戏的目的是从英文字母的小写字符中选择你最喜欢的字符。如果两个角色都不是您的最爱,您可以左键单击“通过”按钮。

我已经编写了JPanel以显示先前Stack Overflow 答案的字符。

我做的第一件事是创建主类。我命名了这个类FavoriteCharacter

我调用了该SwingUtilities invokeLater方法以确保在Event Dispatch Thread上创建和执行 Swing 组件。

接下来,我编写了JFrame代码。对于JFrame我创建的每个 Swing GUI,代码几乎相同。JFrame代码位于类的方法runFavoriteCharacter

接下来,我写了模型类,LetterMap类。每当我创建一个复杂的 Swing GUI 时,我都会使用模型/视图/控制器模式。这个模型非常简单。我有一张地图,其中包含英文字母的小写字符以及投票计数。

一旦我让模型工作,我就回去创建视图。GUI 的每一小部分都包含在FavoriteCharacter类的一个方法中。这样,我可以单独测试视图的每一小块。没有把意大利面条代码扔在墙上,看看什么对我有用。

角色的实际绘制发生在LetterPanel课堂上。所有 Swing 自定义绘画都必须paintComponentJPanel.

完成 GUI 后,我处理了两个控制器类PassListenerVoteListener. PassListener调用FavoriteCharacters类中的方法来选择另一对字符。 VoteListener更新LetterMap模型类,显示 a 中所选字符的投票总数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);
        }

    }

}

推荐阅读