【问题标题】:Java Swing (issue with ActionListener)Java Swing(ActionListener 问题)
【发布时间】:2014-02-16 05:45:44
【问题描述】:

我有一个带回家的任务,我需要制作一个数独板,它显示板上文件中的整数,并允许某人单击 JButton 并输入缺失值。

我已经使用 JPanel 显示板并将文本文件打印到各个按钮,但我不知道如何让 addActionListener 拾取任何缺少值的按钮。它仅适用于最后一个空白按钮。 (空白按钮的值为 0)。

我的问题是为什么最后一个空白按钮只作为目标。一共6个,点击后只有最后一个弹出对话框?

public class MyCustomeFrame extends JFrame {
    private int[][] numbers;
    private String[] nums;
    JButton b1;
    JButton b2;
    JButton b3;
    JButton b4;

    private JPanel p2;

    public MyCustomeFrame() {
        // Create the border layout
        setLayout(new BorderLayout(5, 5));

        // Create a new panel for the buttons to be placed on
        JPanel p1 = new JPanel();

        // Create 3 buttons

        b1 = new JButton("Load");
        b2 = new JButton("Save");
        b3 = new JButton("Check");

        // Adds the 3 buttons to the panel
        p1.add(b1);
        p1.add(b2);
        p1.add(b3);

        // Create the event handlers for when the button is pressed
        b1.addActionListener(new MyButtonHandler());
        b2.addActionListener(new MyButtonHandler());
        b3.addActionListener(new MyButtonHandler());


        // Place the panel south in the window
        add(p1, BorderLayout.SOUTH);

        p2 = new JPanel();

        // Define the grid parameters
        p2.setLayout(new GridLayout(9, 9, 5, 5));

        // Show the grid
        add(p2, BorderLayout.CENTER);
        int[][] numbers = new int[9][9];
        int rowIdx = 0;



        //This is where i read the input file located on my computer and place the numbers on the Sudoku board
        try {
            BufferedReader bReader = new BufferedReader(new FileReader(
                "C:\\Users\\Derek\\Desktop\\input.txt"));

            String line = bReader.readLine();

            while (line != null) {
                nums = line.split(",");

                for (int i = 0; i < numbers[0].length; i++) {
                    numbers[rowIdx][i] = Integer.parseInt(nums[i]);

                    // This creates the individual buttons that are then placed on the board
                    if (numbers[rowIdx][i] >= 1) {
                        p2.add(new JButton(nums[i]));
                    } else {

                        //this is where I'm having the issue
                        b4 = new JButton(" ");
                        p2.add(b4);
                        b4.addActionListener(new MyButtonHandler());
                    }
                }

                rowIdx++;
                line = bReader.readLine();
            }
            bReader.close();
        } catch (FileNotFoundException g) {
            System.out.println("File Not Found!");
        } catch (IOException g) {
            System.out.println("Something went wrong...Try Again");
            g.printStackTrace();
        }
    }

    class MyButtonHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == b1) {
                System.out.println("Loading File...");

            } else if (e.getSource() == b2) {
                System.out.println("Saving File...");

                try {
                    BufferedWriter bWriter = new BufferedWriter(new FileWriter(
                        new File("C:\\SudokuSave.txt"), true));

                    bWriter.close();

                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            } else if (e.getSource() == b3) {
                System.out.println("Checking Solution...");

            } else if (e.getSource() == b4) {
                System.out.println("clicked");
                JOptionPane.showInputDialog("Input a number between 1 - 9");
            }
        }
    }
}

【问题讨论】:

    标签: java swing


    【解决方案1】:

    Vyacheslav 在https://stackoverflow.com/a/21803753 中已经指出了问题的原因

    一些提示:

    您应该使用正确的变量名称。调用 JButton b2 太可怕了。当它是“加载”按钮时,将其命名为loadButton。当它是“保存”按钮时,将其命名为saveButton。代码(最多)编写一次,但可能读取数百次。在最好的情况下,Java 代码应该读起来像散文一样。

    在构造函数中读取具有硬编码名称的文件以构建 GUI 组件是一种非常糟糕的做法。您应该考虑创建一些“数据模型”,其中包含您可以从中创建 GUI 的信息,并拆分

    的过程
    1. 读取文件并将数据存储在数据模型中,以及
    2. 从数据模型创建 GUI。

    这也将允许您比打印更好地处理异常

    System.out.println("Something went wrong...Try Again");
    

    为了解决您的问题,您可以考虑使用匿名侦听器。创建一个负责所有按钮的ActionListener不是很灵活。通常,您只想将单击按钮与对(私有)方法的单个调用相关联。例如,你可以写

    JButton saveButton = new JButton("Save");
    saveButton.addActionListener(new ActionListener() {
    {
        @Override
        public void actionPerformed(ActionEvent) {
            saveButtonWasPressed();
        }
    });
    

    特别是在您有 几个 按钮具有类似功能的情况下,这种方法提供了一个优势:您可以为每个按钮创建匿名侦听器,每个侦听器都包含有关 按钮被点击 - 大致应用于您的代码:

    if (numbers[rowIdx][i] == 0) {
        JButton b = new JButton(" ");
        panel.add(b);
        b.addActionListener(createActionListener(rowIdx, i));
    }
    
    ...
    
    private ActionListener createActionListener(
        final int row, final int column) {
        ActionListener actionListener = new ActionListener() {
        {
            @Override
            public void actionPerformed(ActionEvent) {
                System.out.println("Pressed button in row "+row+", column "+column);
            }
        };
        return actionListener;
    }
    

    【讨论】:

    • 还可以考虑Action“将功能和状态从组件中分离出来。”
    • @trashgod 绝对!对于数独板的按钮网格,这可能不是那么有益,但对于标准动作(加载,保存..)动作绝对是要走的路,特别是当相同的功能应该在一个按钮和一个MenuItem,或者当 I18N 之类的东西发挥作用时......
    • JDigit 是一个使用AbstractAction 的示例。
    【解决方案2】:

    你的错误很简单——for 的每次迭代你都在为b4 变量分配一个新的JButton 对象引用,所以最后b4 指的是你创建的最后一个JButton

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-03
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多