Пытаюсь использовать Eclipse WindowBuilder, но ActionLister ничего не делает

Я пробовал проверить около 5 различных руководств по WindowBuilder, и хотя я могу заставить окно приложения появляться при тестировании кода, я не могу заставить кнопки работать. Это код, который я сделал на основе руководств, которые я видел.

package guiTest;

import java.awt.EventQueue;

import javax.swing.JFrame;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import java.awt.GridBagConstraints;
import javax.swing.JLabel;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class GuiTest {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    GuiTest window = new GuiTest();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public GuiTest() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
        gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0};
        gridBagLayout.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
        gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
        frame.getContentPane().setLayout(gridBagLayout);

        JButton btnLabelAdd = new JButton("Label Add");
        GridBagConstraints gbc_btnLabelAdd = new GridBagConstraints();
        gbc_btnLabelAdd.insets = new Insets(0, 0, 5, 0);
        gbc_btnLabelAdd.gridx = 6;
        gbc_btnLabelAdd.gridy = 1;
        frame.getContentPane().add(btnLabelAdd, gbc_btnLabelAdd);
        btnLabelAdd.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                makeLabel(evt);
            }
        });
    }

    private void makeLabel(ActionEvent evt) {
        JLabel lblHereLabel = new JLabel("Here Label");
        GridBagConstraints gbc_lblHereLabel = new GridBagConstraints();
        gbc_lblHereLabel.gridx = 6;
        gbc_lblHereLabel.gridy = 4;
        frame.getContentPane().add(lblHereLabel, gbc_lblHereLabel);
    }
}

Есть ли у кого-нибудь советы, как заставить это работать? Или какой-нибудь пример кода, который я мог бы использовать, чтобы убедиться, что проблема не в Eclipse? Я предполагаю, что кнопка должна создавать метку, когда кнопка щелкнута левой кнопкой мыши; это правильно?


person David Coleman    schedule 19.11.2019    source источник


Ответы (1)


Ваша кнопка работает нормально. Вы можете посмотреть, как код переходит в makeLabel() в отладчике. Вы просто не делаете новую метку видимой.

Как предложил @MadProgrammer, после того, как вы добавили новую метку, вы можете указать закрывающему Container обновить себя, вызвав revalidate(), а затем repaint(), чтобы он перерисовал себя:

private void makeLabel(ActionEvent evt) {
    JLabel lblHereLabel = new JLabel("Here Label");
    GridBagConstraints gbc_lblHereLabel = new GridBagConstraints();
    gbc_lblHereLabel.gridx = 6;
    gbc_lblHereLabel.gridy = 4;
    frame.getContentPane().add(lblHereLabel, gbc_lblHereLabel);
    frame.getContentPane().revalidate();
    frame.getContentPane().repaint();
}


Это означает, что вы избавились от необходимости прямого доступа к frame. Это означает, что вы можете переписать свой обработчик, чтобы он был «независим от фрейма», запрашивая кнопку, вызвавшую событие, для Container, которому она принадлежит, и просто добавляя к ней новую метку, например:

private void makeLabel(ActionEvent evt) {
    JLabel lblHereLabel = new JLabel("Here Label");
    GridBagConstraints gbc_lblHereLabel = new GridBagConstraints();
    gbc_lblHereLabel.gridx = 6;
    gbc_lblHereLabel.gridy = 4;

    Container displayArea = ((JButton) evt.getSource()).getParent();
    displayArea.add(lblHereLabel, gbc_lblHereLabel);
    displayArea.revalidate();
    displayArea.repaint();
}
person azurefrog    schedule 19.11.2019
comment
Вы также можете просто использовать revalidate и repaint вместо frame.setVisible для принудительного прохода макета и рисования - что я считаю лучшей практикой, поскольку вы действительно должны отделить свой код от знания чего-либо о фрейме;) - person MadProgrammer; 20.11.2019
comment
@MadProgrammer Спасибо! Обновлено. - person azurefrog; 20.11.2019
comment
Большое спасибо вам двоим! Наконец-то это заработало, теперь я могу приступить к реализации графического интерфейса для моей программы. - person David Coleman; 20.11.2019
comment
Я не согласен с @MadProgrammer и azurefrog относительно лучшего пути к решению. Я бы добавил пустую метку (без текста, видимой границы или значка) при запуске. Такая метка невидима и не может получить фокус ввода, поэтому пользователь не узнает, что она есть. При действии кнопки установите для текста или значка значение сделать его «видимым» автоматически, не беспокоясь о непосредственном родительском контейнере или верхнего уровня. - person Andrew Thompson; 31.12.2019