Java Swing добавляет / удаляет jButtons во время выполнения - PullRequest
5 голосов
/ 12 августа 2010

Мое приложение имеет модуль, который позволяет пользователю добавлять jButtons на jLayeredpane во время выполнения. Я хочу добавить слушателей действия к этому динамически добавляемому содержимому, а также я должен предоставить доступ для удаления динамически добавленных кнопок во время выполнения. Есть ли способ сделать это?

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

Ответы [ 2 ]

10 голосов
/ 12 августа 2010

Оригинальный ответ В общем, хорошо, но в этом случае сделано иначе

Чтобы отслеживать произвольное количество добавленных JButtons, вам необходимо сохранить их в списке.

Итак, после того, как вы создали новую кнопку, добавили к ней слушателей и добавили ее на панель, вам нужно сохранить эту новую кнопку в списке.

Таким образом, вы можете отслеживать все добавленные вами кнопки.

Вы также можете использовать Map<String, JButton>, который отображает имя кнопки на кнопку.

Пример:

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();
    }
}
6 голосов
/ 12 августа 2010

Абсолютно.Все это может быть сделано программно в любое время.Вот несколько советов, чтобы избежать проблем и ловушек:

  • Когда вы добавляете компоненты на любую панель, убедитесь, что это сделано в потоке диспетчеризации событий через SwingUtilities.invokeLater(Runnable).Внутри Runnable вы хотите добавить компонент на панель, подключить прослушиватели и изменить расположение панели.
  • Используйте SwingUtilities.isEventDispatchThread(), чтобы проверить, находитесь ли вы уже в потоке диспетчеризации событий.Если да, то вы можете просто запустить Runnable немедленно вместо вызова invokeLater.
  • После того, как вы изменили макет панели, обязательно вызовите Component.invalidate() на панели, чтобы убедиться, чтовыкладывается снова.
  • Вести собственный список слушателей.Замените методы добавления и удаления на панели, чтобы добавить или удалить их из списка, а также из всех существующих кнопок.Когда вы добавляете новые кнопки, добавляйте всех слушателей в список.

Это очень распространенная задача, и она полностью поддерживается Java.Вы должны быть в состоянии сделать это без особых проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...