【问题标题】:Writing a small app for a DnD puzzle and have trouble with a JButton array为 DnD 拼图编写一个小应用程序并遇到 JButton 数组的问题
【发布时间】:2023-12-31 16:42:01
【问题描述】:

将 Puzzle 类的对象添加到 Main 后,所有内容都按应有的方式显示。当我单击任何按钮时,一些状态索引应该交换到相反的状态,因此从真到假或从假到真。

不幸的是,按钮单击不想注册数组中的任何按钮,但它确实注册了一个由自身初始化的按钮。我该如何解决这个问题?

我的代码:


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;

public class Puzzle extends JFrame implements ActionListener
{
    int doors = 8;
    boolean [] state = new boolean[doors];
    JButton [] levers = new JButton[doors];
    JButton weird = new JButton("weird lever");
    JLabel display = new JLabel();


    Puzzle()
    {
        reset();

        this.setSize(new Dimension(1920, 1080));
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setResizable(false);
        this.setLayout(null);
        this.add(display);
        this.add(weird);

        int num = levers.length;
        int start = 50;
        int size = (1920-(num+1)*start)/num;
        char label = 'A';
        display.setBounds(size*2, 150, 2000, 300);
        display.setFont(new Font("Arial Black", Font.PLAIN, 200));
        Display();
        for(JButton i : levers)
        {
            i = new JButton(String.valueOf(label));
            label++;
            i.setBounds(start, 500, size, size);
            start+=(size+50);
            i.addActionListener(this);
            i.setFont(new Font("Arial black", Font.PLAIN, size/2));
            i.setFocusable(false);
            this.add(i);
        }
        weird.setFocusable(false);
        weird.setBounds(550, 800, 800, 200);
        weird.setFont(new Font("Arial Black", Font.PLAIN, size/2));
        weird.addActionListener(this);





    }

    @Override
    public void actionPerformed(ActionEvent e)
    {

        /*if(e.getSource() == levers[0])
        {
            state[2] = Swap(state[2]);
            Display();

        }
         if(e.getSource() == levers[1])
        {
            state[4] = Swap(state[4]);
            state[6] = Swap(state[6]);
            Display();
        }
         if(e.getSource() == levers[2])
        {
            state[2] = Swap(state[2]);
            state[3] = Swap(state[3]);
            state[6] = Swap(state[6]);
            state[7] = Swap(state[7]);
            Display();
        }
         if(e.getSource() == levers[3])
        {
            state[0] = Swap(state[0]);
            state[2] = Swap(state[2]);
            state[7] = Swap(state[7]);
            Display();
        }
        if(e.getSource() == levers[4])
        {
            state[1] = Swap(state[1]);
            state[3] = Swap(state[3]);
            state[4] = Swap(state[4]);
            state[5] = Swap(state[5]);
            Display();
        }
         if(e.getSource() == levers[5])
        {
            state[0] = Swap(state[0]);
            state[2] = Swap(state[2]);
            state[6] = Swap(state[6]);
            Display();
        }
         if(e.getSource() == levers[6])
        {
            state[1] = Swap(state[1]);
            state[5] = Swap(state[5]);
            Display();
        }
         if(e.getSource() == levers[7])
        {
            state[1] = Swap(state[1]);
            state[2] = Swap(state[2]);
            state[4] = Swap(state[4]);
            state[5] = Swap(state[5]);
            Display();
        }
        */

        if(e.getSource() == levers[0])
        {
            display.setText("A works");
        }
         if(e.getSource() == weird)
        {
            display.setText("test");
        }

    }

      boolean Swap(boolean n)
      {
          return !n;
      }

    void Display()
    {
        StringBuilder toDisplay = new StringBuilder();
        for (boolean j : state)
        {
            if (j)
            {
                toDisplay.append("| ");
            } else
                toDisplay.append("_ ");
        }
        display.setText(toDisplay.toString());
    }

    void reset ()
    {
        Arrays.fill(state, true);
    }

}```

【问题讨论】:

    标签: java arrays swing jframe jbutton


    【解决方案1】:

    按钮点击不想注册数组中的任何按钮,但它确实注册了单个按钮

    System.out.println( levers[0] );
    
    if(e.getSource() == levers[0])
    {
        display.setText("A works");
    }
    

    将一些调试代码添加到您的 ActionListener 中,您将看到 levers[0] 的值为“null”。

        for(JButton i : levers)
        {
            i = new JButton(String.valueOf(label));
            label++;
            i.setBounds(start, 500, size, size);
            start+=(size+50);
            i.addActionListener(this);
            i.setFont(new Font("Arial black", Font.PLAIN, size/2));
            i.setFocusable(false);
            this.add(i);
        }
    

    您创建了按钮,但从不将每个按钮的实例添加到数组中。

    for(JButton i : levers)
    

    为什么要使用“i”作为变量名。通常,“i”用作索引。使用适当的变量名称,例如“按钮”。但是,在这种情况下,您不想使用“for each”循环。

    相反,您需要一个普通的 for 循环,这样您就可以索引数组以在创建时添加每个按钮:

    //for(JButton i : levers)
    for (int i = 0; i < doors; i++)
    {
        JButton button = new JButton(String.valueOf(label));
        levers[i] = button;
        ...
    

    其他问题:

    1. 方法名称不应以大写字符开头。
    2. 应在框架可见之前将组件添加到框架中。
    3. 应在Event Dispatch Thread (EDT) 上创建组件。
    4. 不要使用空布局和 setBounds()。 Swing 旨在与布局管理器一起使用。
    5. 不要对屏幕尺寸进行硬编码。相反,您可以使用 frame.setExtendedState(JFrame.MAXIMIZED_BOTH);,因此它适用于所有屏幕尺寸。

    【讨论】:

    • 谢谢,我会做一个普通的 for 循环,但 Intellij 建议我使用 for each。
    【解决方案2】:

    简介

    您的代码太复杂,我无法理解。我喜欢简单的代码。简短的方法和简单的类。

    这是我想出的 GUI。

    这是我点击几个字母JButtons后的图形用户界面

    说明

    Oracle 有一个很棒的教程Creating a GUI With JFC/Swing,它将向您展示如何创建一个 Swing GUI。跳过 Netbeans 部分。

    您的代码缺少一个主要方法,所以我添加了一个。我通过调用 SwingUtilities invokeLater 方法启动了 Swing 应用程序。此方法确保在Event Dispatch Thread 上创建和执行 Swing 组件。

    我做的第一件事是创建一个PuzzleModel 类来保存布尔数组。将模型与视图和控制器类分开是个好主意。这种模式就是model / view / controller (MVC) 模式。

    一个 Swing JFrame 可以包含许多 JPanels。我创建了一个段 JPanel 来容纳一个 JLabel 和一个 JButton 垂直对齐。我使用GridBagLayout 来对齐JLabelJButtonSwing layout managers帮助您避免绝对定位和绝对定位带来的问题。

    我创建了一个主 JPanel 来保存 8 个段 JPanels。这些JPanelsFlowLayout 对齐。

    如您所见,我的JFrame 比您的小。您创建尽可能小的JFrame。如果用户想让它变大,那就是右上角的矩形。

    Swing 旨在从内到外进行设计。您没有指定 JFrame 大小并尝试使组件适合。您创建组件并让 Swing 确定JFrame 的大小。如果您希望我创建的JFrame 更大,请增加字体大小。提示:72 的分数或倍数在大多数显示器上看起来更好。

    我创建了两个ActionListener 类,一个用于字母表JButtons,一个用于杠杆JButton。这使得更容易专注于字母表JButtons。在ActionListener 中您所要做的就是在左键单击每个JButton 时交换适当的isVertical 布尔值。我只是翻转了相应的布尔值作为演示。

    代码

    这是完整的可运行代码。

    import java.awt.BorderLayout;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Arrays;
    
    import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class PuzzleGUI implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new PuzzleGUI());
        }
        
        private JLabel[] leverLabel;
        
        private final PuzzleModel model;
    
        public PuzzleGUI() {
            this.model = new PuzzleModel();
        }
        
        @Override
        public void run() {
            JFrame frame = new JFrame("Weird Lever");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            frame.add(createMainPanel(), BorderLayout.CENTER);
            frame.add(createButtonPanel(), BorderLayout.AFTER_LAST_LINE);
            
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
            
            System.out.println(frame.getSize());
        }
        
        private JPanel createMainPanel() {
            JPanel panel = new JPanel(new FlowLayout());
            panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            
            char c = 'A';
            boolean[] isVertical = model.getIsVertical();
            leverLabel = new JLabel[isVertical.length];
            for (int i = 0; i < isVertical.length; i++) {
                String labelText = (isVertical[i]) ? "|" : "-";
                panel.add(createLeverButtonPanel(labelText, Character.toString(c), i));
                c = (char) (((int) c) + 1);
            }
            
            return panel;
        }
        
        public void updateMainPanel() {
            boolean[] isVertical = model.getIsVertical();
            for (int i = 0; i < isVertical.length; i++) {
                String labelText = (isVertical[i]) ? "|" : "-";
                leverLabel[i].setText(labelText);
            }
        }
        
        private JPanel createLeverButtonPanel(String labelText, String buttonText, int index) {
            JPanel panel = new JPanel(new GridBagLayout());
            panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            
            Font font1 = new Font("Arial Black", Font.PLAIN, 144);
            Font font2 = new Font("Arial Black", Font.PLAIN, 72);
            
            GridBagConstraints gbc = new GridBagConstraints();
            
            gbc.gridx = 0;
            gbc.gridy = 0;
            leverLabel[index] = new JLabel(labelText);
            leverLabel[index].setFont(font1);
            panel.add(leverLabel[index], gbc);
            
            gbc.gridy++;
            JButton button = new JButton(buttonText);
            button.addActionListener(new AlphabetButtonListener());
            button.setFont(font2);
            panel.add(button, gbc);
            
            return panel;
        }
        
        private JPanel createButtonPanel() {
            JPanel panel = new JPanel(new FlowLayout());
            panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            
            Font font2 = new Font("Arial Black", Font.PLAIN, 48);
            
            JButton button = new JButton("Weird Lever");
            button.addActionListener(new LeverButtonListener());
            button.setFont(font2);
            panel.add(button);
            
            return panel;
        }
    
        public class AlphabetButtonListener implements ActionListener {
    
            @Override
            public void actionPerformed(ActionEvent event) {
                JButton button = (JButton) event.getSource();
                String text = button.getText();
                char c = text.charAt(0);
                int index = ((int) c - 'A');
                model.swap(index);
                updateMainPanel();
            }
            
        }
        
        public class LeverButtonListener implements ActionListener {
    
            @Override
            public void actionPerformed(ActionEvent event) {
                // TODO Auto-generated method stub
                
            }
            
        }
    
        public class PuzzleModel {
            
            private boolean[] isVertical;
            
            public PuzzleModel() {
                int doors = 8;
                this.isVertical = new boolean[doors];
                reset();
            }
            
            private void reset() {
                Arrays.fill(isVertical, true);
            }
            
            public void swap(int index) {
                isVertical[index] = !isVertical[index];
            }
    
            public boolean[] getIsVertical() {
                return isVertical;
            }
            
        }
        
    }
    

    【讨论】:

      最近更新 更多