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

发布于 2024-11-08 01:12:11 字数 484 浏览 0 评论 0原文

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

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

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

I want to create a (simple, hopefully) custom Swing component by composing several existing components. In my case, it is an on-off switch which consists of a JLabel, and two JButtons for On and Off. I begin OnOffSwitch by extending JPanel. The constructor adds the sub-components, and sets itself up as an ActionListener for the buttons. The class has an isOn() method for querying the current state of the component.

I now want to add the ability to add ActionListeners to the OnOffSwitch class. I expected this functionality would come for free by having extended a Swing component like JPanel, but JPanel does not have this functionality. By the looks of the sources, every Swing component which does have this functionality re-implements it itself: the adding listeners to the list, the firing of ActionEvents, etc.

What is the correct way to achieve what I want? I can copy/paste that code from the various Swing components (or re-write the gist of it), or I can implement my own OnOffSwitchListener interface. To be consistent it seems that all my components should use ActionListeners.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你没皮卡萌 2024-11-15 01:12:12

我会使用 JToggelButton,如图所示 此处,或委托给包含的按钮,如 @duffymo 建议的那样。如果您确实需要自定义OnOffSwitchEvent,则标准接线概述于EventListenerList,每个 JComponent 中都包含其实例。

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

BttonGroupTest iamge

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://stackoverflow.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();
            }
        });
    }
}

I'd use a JToggelButton, as shown here, or delegate to the contained buttons, as @duffymo suggests. If you really need a custom OnOffSwitchEvent, the standard wiring is outlined in EventListenerList, an instance of which is contained in every JComponent.

Addendum: Here's an example of delegating to a ButtonGroup containing two buttons. The label is decorated with a symbol, but any implementation of Icon is even more flexible.

BttonGroupTest iamge

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://stackoverflow.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();
            }
        });
    }
}
一绘本一梦想 2024-11-15 01:12:12

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

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

public class MyUI
{
    private Button b = new Button();

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

I personally don't think you need a custom Swing component. No need for your UI class to extend any Swing class; you aren't likely to provide much custom behavior. (I might concede for a JPanel that composes others.)

I would prefer composition over inheritance. Have a UI class that has Swing data members and give it methods to add and remove Listeners as you need them. You can change the behavior that way without having to rewrite the UI class. It's nothing more than a container.

public class MyUI
{
    private Button b = new Button();

    public void addButtonListener(ActionListener listener) { this.b.addActionListener(listener); }
}
夕色琉璃 2024-11-15 01:12:12

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

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

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

By the looks of the sources, every Swing component which does have this [ActionListener] functionality re-implements it itself: the adding listeners to the list, the firing of ActionEvents, etc.

Yep. That's what you have to do when you're writing a custom Swing component.

As you say, you can copy the ActionListener code from an existing Swing component,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文