【问题标题】:Java Swing add/remove jButtons on runtimeJava Swing 在运行时添加/删除 jButtons
【发布时间】:2011-03-28 23:38:32
【问题描述】:

我的应用程序有一个模块,它允许用户在运行时在 jLayeredpane 上添加 jButtons。我想向这个动态添加的内容添加动作侦听器,并且我必须提供在运行时删除动态添加的按钮的访问权限。有没有办法做到这一点?

private Map<String, JButton> dynamicButtons;

public void addButton(String name) {
    JButton b = new JButton(name);
    b.addActionListener(new java.awt.event.ActionListener() {

        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });

    jLayeredPane2.add(b);
    dynamicButtons.put(name, b);
    jLayeredPane2.invalidate();
}

public void removeButton(String name) {
    JButton b = dynamicButtons.remove(name);
    jLayeredPane2.remove(b);
    jLayeredPane2.invalidate();
}

【问题讨论】:

  • 重新格式化的代码;如果不正确,请恢复。
  • 我最新编辑的代码会在您单击的位置添加按钮。如果在单击删除后单击它们,则删除按钮。

标签: java swing components


【解决方案1】:

原始答案 总体上很好,但在这种情况下做得不同

为了跟踪任意数量的已添加JButtons,您需要将它们保存在一个列表中。

因此,在您创建一个新按钮、为其添加侦听器并将其添加到窗格后,您需要将该新按钮保存在一个列表中。

这样您就可以跟踪您添加的所有按钮。

您还可以使用将按钮名称映射到按钮的Map&lt;String, JButton&gt;

例子:

private Map<String, JButton> dynamicButtons;

public void addButton(String name) {
    JButton b = new JButton(name);
    b.addActionListener(someAction);
    yourPanel.add(b);
    dynamicButtons.put(name, b);
    yourPanel.invalidate();
}

public void removeButton(String name) {
    Button b = dynamicButtons.remove(name);
    yourPanel.remove(b);
    yourPanel.invalidate();
}

以下是一个完整的类,可让您动态添加和删除按钮。这不完全是你想要的,但它应该让你真正接近。

您的具体案例的代码:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class ExampleFrame extends JFrame {

    private JButton add, remove;
    private JPanel dynamicButtonPane, addRemovePane;

    private boolean waitingForLocationClick;

    public ExampleFrame() {
        super("Dynamic button example");
        waitingForLocationClick = false;
        add = new JButton("Add Button");
        add.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addButton(JOptionPane
                        .showInputDialog("Name of the new button:"));
            }
        });
        remove = new JButton("Remove Button");
        remove.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                lookingToRemove = true;
            }
        });
        JPanel mainPane = new JPanel(new BorderLayout());
        dynamicButtonPane = new JPanel();
        dynamicButtonPane.setLayout(null);
        dynamicButtonPane.setPreferredSize(new Dimension(300, 300));
        addRemovePane = new JPanel();
        addRemovePane.add(add);
        addRemovePane.add(remove);
        mainPane.add(dynamicButtonPane, BorderLayout.NORTH);
        mainPane.add(addRemovePane, BorderLayout.SOUTH);
        add(mainPane);
        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        dynamicButtonPane.addMouseListener(pointSelectorListener);
    }

    private JButton buttonToPlace;

    public void addButton(String name) {
        JButton b = new JButton(name);
        b.setActionCommand(name);
        b.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (lookingToRemove) {
                    if (e.getSource() instanceof JButton) {
                        dynamicButtonPane.remove((Component) e.getSource());
                        dynamicButtonPane.validate();
                        dynamicButtonPane.repaint();
                    }
                } else
                    JOptionPane.showMessageDialog(ExampleFrame.this, "This is " + e.getActionCommand());
            }
        });
        waitingForLocationClick = true;
        lookingToRemove = false;
        buttonToPlace = b;
    }

    public void putButtonAtPoint(Point p) {
        System.out.println("Placing a button at: " + p.toString());
        dynamicButtonPane.add(buttonToPlace);
        buttonToPlace.setBounds(new Rectangle(p, buttonToPlace
                .getPreferredSize()));
        dynamicButtonPane.validate();
        buttonToPlace = null;
        waitingForLocationClick = false;
    }

    private boolean lookingToRemove = false;

    private final MouseListener pointSelectorListener = new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if (waitingForLocationClick) {
                putButtonAtPoint(e.getPoint());
            } else {
                System.out.println("Not in waiting state");
            }
        }
    };

    public static void main(String[] args) {
        new ExampleFrame();
    }
}

【讨论】:

  • 我是新手,你能详细说明一下吗?如果您用代码示例进行解释,我将不胜感激..
  • @Deepak,您的 Frame 中需要 2 个静态按钮。一个用于添加按钮,一个用于删除按钮。然后,您将为这两个按钮添加一个动作侦听器。添加按钮的操作将是addButton(string) 方法,删除按钮的操作将是removeButton(string)
  • 感谢代码解释,告诉我应该在哪里添加这段代码?它是在单独的类文件中还是与 jframe 文件一起?
  • @Deepak,这将进入您的JFrame
  • 如果我调用 removeButton(string),请告诉我,“string”是我们上下文中按钮的名称。现在我想如何设计我的应用程序是,当用户单击 jLayeredpane 时,它​​会在单击的 atea 上添加一个按钮,我正在使用 moues 坐标进行操作。现在,如果我设置删除标志并调用 removeButton(string),我希望允许用户删除按钮,就像他们创建它的方式一样(通过单击创建的按钮)
【解决方案2】:

当然。所有这些东西都可以随时以编程方式完成。以下是一些避免问题和陷阱的提示:

  • 当您将组件添加到任何面板时,请确保通过SwingUtilities.invokeLater(Runnable) 在事件调度线程上完成此操作。在 Runnable 中,您希望将组件添加到面板、连接侦听器并重新布局面板。
  • 使用SwingUtilities.isEventDispatchThread() 检查您是否已经在事件分派线程上。如果是,那么您可以立即运行 Runnable,而不是调用 invokeLater
  • 修改面板布局后,请务必在面板上调用Component.invalidate() 以确保重新布局。
  • 维护您自己的听众名单。覆盖面板上的添加和删除方法,以从您的列表以及所有现有按钮中添加或删除它们。添加新按钮时,添加列表中的所有侦听器。

这是一个非常常见的任务,Java 完全支持它。您应该可以轻松完成它。

【讨论】:

  • 我知道我们可以做到这一点,但我是摇摆概念的新手,所以我不太了解它。我还有一个问题,我需要为创建的按钮提供不同的名称。你能在代码示例中解释一下吗?或者只是给我一个链接。我也想要原始问题的代码示例。
  • 您问是否有任何方法可以做到这一点,并且有。代码示例将完全依赖于实现。由于您是实现它的人,因此将代码放在一起并弄清楚细节应该没有问题。如果您对某个特定细节感到困惑,请具体询问。
  • 基本上,发生了很多事情。你问了一个相当高级的问题,答案中有几个活动部分。只写一个问题的代码太多了。我强烈建议您自己尝试一下,如果遇到问题,请提出另一个问题。
猜你喜欢
  • 1970-01-01
  • 2022-01-08
  • 2012-02-24
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-14
相关资源
最近更新 更多