处理 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
,您可以使用它来设置每个 JButton
的 Action
,通过 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,相信你会喜欢的。
我正在尝试创建动态界面,该界面本质上是创建一个由越来越多的面板组成的网格,看起来类似于下图。我有一些粗略的代码来实现这一点。关于处理已添加到 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
,您可以使用它来设置每个 JButton
的 Action
,通过 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,相信你会喜欢的。