Java Swing add/remove jButtons on runtime

后端 未结 2 668
广开言路
广开言路 2020-12-09 23:11

My application has a module which allows the user to add jButtons on the jLayeredpane during runtime. I want to add action listeners to this dynamically added contents and a

相关标签:
2条回答
  • 2020-12-09 23:47

    Original Answer Good in general, but done differently in this case

    In order to keep track of an arbitrary number of added JButtons, you will need to keep them in a list.

    So, after you create a new button, add the listeners to it, and add it to the pane, you then need to save that new button in a list.

    That way you can keep track of all of the buttons you have added.

    You could also use a Map<String, JButton> that maps a button name to the button.

    Example:

    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();
    }
    

    The following is a full class that lets you add and remove buttons dynamically. It's not exactly what you want, but it should get you really close.

    Code for your specific case:

    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();
        }
    }
    
    0 讨论(0)
  • 2020-12-10 00:00

    Absolutely. All of this stuff can be done programatically at any time. Here are a couple of hints to avoid problems and pitfalls:

    • When you add components to any panel, make sure this is done on the Event Dispatch Thread through SwingUtilities.invokeLater(Runnable). Inside the Runnable, you want to add the component to the panel, hook up the listeners, and re-layout the panel.
    • Use SwingUtilities.isEventDispatchThread() to check to see if you are already on the event dispatch thread. If you are, then you can just run the Runnable immediately instead of calling invokeLater.
    • Once you've modified the layout of a panel, be sure to call Component.invalidate() on the panel to make sure it gets laid out again.
    • Maintain your own list of listeners. Overwrite the add and remove methods on the panel to add or remove them from your list and also from all existing buttons. When you add new buttons, add all listeners on the list.

    This is a very common task, and it is fully supported by Java. You should be able to get it done without too much trouble.

    0 讨论(0)
提交回复
热议问题