组合 Swing 组件:如何添加添加 ActionListener 的功能?

Posted

技术标签:

【中文标题】组合 Swing 组件:如何添加添加 ActionListener 的功能?【英文标题】:Composing Swing Components: How do I add the ability to add ActionListeners? 【发布时间】:2011-08-27 12:12:41 【问题描述】:

我想通过组合几个现有组件来创建一个(希望是简单的)自定义 Swing 组件。在我的例子中,它是一个开关,由一个 JLabel 和两个用于打开和关闭的 JButton 组成。我从扩展 JPanel 开始 OnOffSwitch。构造函数添加子组件,并将自己设置为按钮的 ActionListener。该类有一个 isOn() 方法用于查询组件的当前状态。

我现在想添加将 ActionListeners 添加到 OnOffSwitch 类的功能。我希望通过扩展 JPanel 之类的 Swing 组件来免费提供此功能,但 JPanel 没有此功能。从源代码来看,每个具有此功能的 Swing 组件都会重新实现它自己:将侦听器添加到列表、触发 ActionEvents 等。

实现我想要的正确方法是什么?我可以从各种 Swing 组件复制/粘贴该代码(或重写它的要点),或者我可以实现我自己的 OnOffSwitchListener 接口。为了保持一致,我的所有组件似乎都应该使用 ActionListeners。

【问题讨论】:

【参考方案1】:

从源代码来看,每个确实具有此 [ActionListener] 功能的 Swing 组件都会重新实现它自己:将侦听器添加到列表中,触发 ActionEvents 等。

是的。这就是您在编写自定义 Swing 组件时必须做的事情。

如您所说,您可以从现有的 Swing 组件中复制 ActionListener 代码,

【讨论】:

【参考方案2】:

我个人认为您不需要自定义 Swing 组件。您的 UI 类无需扩展任何 Swing 类;您不太可能提供太多自定义行为。 (我可能会承认 JPanel 可以组合其他人。)

我更喜欢组合而不是继承。拥有一个具有 Swing 数据成员的 UI 类,并为其提供根据需要添加和删除侦听器的方法。您可以通过这种方式更改行为,而无需重写 UI 类。它只不过是一个容器。

public class MyUI

    private Button b = new Button();

    public void addButtonListener(ActionListener listener)  this.b.addActionListener(listener); 

【讨论】:

+1 我同意使用现有组件进行组合;抱歉我之前的误读。【参考方案3】:

我会使用JToggelButton,如here 所示,或委托给包含的按钮,如@duffymo 建议的那样。如果您真的需要自定义OnOffSwitchEvent,标准接线在EventListenerList 中列出,每个JComponent 中都包含一个实例。

附录:这是一个委托给包含两个按钮的 ButtonGroup 的示例。标签用符号装饰,但Icon 的任何实现都更加灵活。

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JToggleButton;

/** @see https://***.com/questions/6035834 */
public class ButtonGroupTest extends JComponent 

    private static final String ON = "On";
    private static final String OFF = "Off";
    private final JToggleButton bOn = new JToggleButton(ON);
    private final JToggleButton bOff = new JToggleButton(OFF);
    private final JLabel label = new JLabel(" \u2301 ");
    private final ButtonHandler handler = new ButtonHandler();

    public ButtonGroupTest() 
        this.setLayout(new FlowLayout());
        label.setOpaque(true);
        label.setBackground(Color.red);
        label.setFont(label.getFont().deriveFont(36f));
        ButtonGroup bg = new ButtonGroup();
        this.add(bOn);
        bg.add(bOn);
        bOn.setSelected(true);
        bOn.addActionListener(handler);
        this.add(label);
        this.add(bOff);
        bg.add(bOff);
        bOff.addActionListener(handler);
    

    public void addActionListener(ActionListener listener) 
        bOn.addActionListener(listener);
        bOff.addActionListener(listener);
    

    private class ButtonHandler implements ActionListener 

        @Override
        public void actionPerformed(ActionEvent e) 
            String cmd = e.getActionCommand();
            if (ON.equals(cmd)) 
                label.setBackground(Color.red);
             else 
                label.setBackground(Color.black);
            
        
    

    private void display() 
        JFrame f = new JFrame("ButtonGroupTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    

    public static void main(String[] args) 
        EventQueue.invokeLater(new Runnable() 

            @Override
            public void run() 
                new ButtonGroupTest().display();
            
        );
    

【讨论】:

以上是关于组合 Swing 组件:如何添加添加 ActionListener 的功能?的主要内容,如果未能解决你的问题,请参考以下文章

Java swing 添加来自另一个类的组件

如何使用 Swing 在 JFrame 中添加面板

将 Swing 组件添加到容器的标准方法?

一个 Swing 组件不能添加到多个容器中吗?

用java编写的swing程序。如何在主界面中实现刷新的功能,就是让主界面的组件刷新

java Swing第2集:向JFrame添加组件