处理 JButton 集合的事件

Handling events for a collection of JButtons

我正在尝试创建动态界面,该界面本质上是创建一个由越来越多的面板组成的网格,看起来类似于下图。我有一些粗略的代码来实现这一点。关于处理已添加到 ArrayList 的 JButton 的事件,我有一个问题。我知道创建内部 class 事件处理程序是最佳实践,我将如何处理存储在 ArrayList 中的按比例缩放的按钮数量的事件?

目前我已经通过获取对象源来实现这一点。

全局变量:

ArrayList<JButton> buttons = new ArrayList<JButton>();

向面板添加按钮:

    for (int i = 0; i < 2; i ++) {
        int xTotal = 150;
        if (i == 0) {
            xTotal = 132;
        }
        else {
            xTotal = 308;
        }
        xTotal = xTotal + xTotal;

        JButton currentButton = new JButton("+");
        currentButton.setBounds(xTotal , 375, 45, 25); 
        currentButton.setFont(currentButton.getFont().deriveFont(14f));
        currentButton.addActionListener(new AddHandler());

        buttons.add(currentButton);
        panel.add(currentButton);
    }

事件处理程序:

class AddHandler implements ActionListener {

    public void actionPerformed(ActionEvent event) {


        Object source = event.getSource();

        if (source == buttons.get(0)) {
            System.out.println("hello");

        }
        else {

            System.out.println("it worked");
        }

    }
}

在我看来,您创建的不仅仅是 JButtons 的集合。相反,您似乎想要创建(如果我错了请纠正我)images/text 和 JButton 的集合。这表明您想要创建一个 class 来封装 one (?) 菜单项,它包含一个用于图像的 JLabel,一个可能用于文本的 JLabel ,也许还有其他组件,以及一个 JButton,用户可以按该 select 菜单项。该组件将是一个 JPanel,它(此处很重要)使用布局管理器智能地排列其所有组成组件。我建议不要使用 ActionListeners,而是沿着 class 创建一个单独的支架,扩展 AbstractAction,您可以使用它来设置每个 JButtonAction,通过 JButton 的构造函数或通过其 setAction(...) 方法。然后,您可以将这些 JPanel 的集合放在可能使用 GridLayout 的主 JPanel 中,并将其保存在 JScrollPane 中。

我的建议和代码的详细信息当然取决于您的 GUI 和当前代码的详细信息。

其他"side"推荐:

  • 不要使用 null 布局和 setBounds(...)。新手 Swing 程序员常常认为这是创建复杂 GUI 的最简单方法,短期内可能如此,但从长远来看,当需要维护、升级和增强 GUI 时,情况并非如此。此外,如此创建的 GUI 在一个平台和屏幕分辨率上可能看起来不错,但在所有其他平台上看起来很糟糕。了解和使用布局管理器。
  • 也许您想要一组 Action 或 JButton,但我不确定您是否需要它。如果按钮的 Action 知道要做什么,则不需要集合。 Action 可以有一个构造函数,用于传递对菜单项的名称和价格的引用。

虽然你已经接受了另一个答案,但我还是想分享一下我的想法。

我的想法是通过创建JButton的子类在按钮上存储一个数字(可能是一个ID)。 (ID 可能是此按钮当前链接到的食品的 ID)

class FoodButton extends JButton{
    long id;

    public FoodButton(String text, long id){
        super(text);
        this.id = id;
    }
    //Perhaps more constructors

    public long getId(){
        return id;
    }
}

然后编写一个获取事件源的 actionListener(尽管您似乎认为这是不好的做法,但我认为在这个例子中它是有意义的),观察:

ActionListener al = new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e){
        FoodButton btn = (FoodButton) e.getSource();
        long id = btn.getId();

        //Do something now that you know what button was clicked (id)
    }
}

让我再次注意,这个 actionListener 是在之前你的循环创建的,所以你只需要一个,你会为你的所有按钮分配相同的一个。

然后在循环中创建一个 FoodButton,而不是创建普通的 JButton:

ActionListener al = new ActionListener(){...};
for (int i = 0; i < 2; i ++) {
    //...

    //Assigning id 'i' here, but you could pick something else
    JButton currentButton = new FoodButton("+", i);
    //...
    currentButton.addActionListener(al);

    buttons.add(currentButton);
    panel.add(currentButton);
}

我希望这对你有所帮助。

另外,作为一个也用过null layouts的人,一旦你习惯了layoutmanagers,相信你会喜欢的。