java - 如何让 GUI 按钮正确响应?

标签 java swing jpanel awt jbutton

我编写了以下代码,除了信息框中的“退出信息”按钮和信息框中的文本之外,它似乎运行顺利。首先,信息框中的文本(位于标签上)拒绝显示。其次,“退出信息”按钮没有出现在我为其设置的位置。关于我可以做些什么来使其正常运行有什么建议吗? 谢谢

注意:我对 Java 非常缺乏经验,因此可能无法完全理解答案,除非它们是为幼儿园学生编写的:)

    import java.awt.*;
    import javax.swing.*;

    public class CombineInputWindow {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    // Create the frame
    JFrame frame = new JFrame("New GUI");// Title the frame
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// add close function

    // Create the label:
    JLabel textLabel = new JLabel("");// No text is added
    textLabel.setPreferredSize(new Dimension(320,240));// Set the size of the label
    frame.getContentPane().add(textLabel, BorderLayout.CENTER);// Add the label to the frame

    // The following three lines set the frame up further
    frame.setLocationRelativeTo(null);
    frame.pack();
    frame.setVisible(true);

    // Create the panel
    JPanel panel = new JPanel();
    frame.add(panel);// Add panel to frame

    // Create lbutton (size, text, etc.)
    JButton lbutton = new JButton("Move Left");
    panel.add(lbutton);
    lbutton.setSize(128,32);
    lbutton.setVisible(true);
    lbutton.setLocation(0,208);

    // Create rbutton (size, text, etc.)
    JButton rbutton = new JButton("Move right");
    panel.add(rbutton);
    rbutton.setSize(128,32);
    rbutton.setVisible(true);
    rbutton.setLocation(192,208);

    // Create dodge button (size, text, etc.)
    JButton btndodge = new JButton("Duck");
    panel.add(btndodge);
    btndodge.setSize(64,32);
    btndodge.setVisible(true);
    btndodge.setLocation(128,208);

    // Create exit button (size, text, etc.)
    JButton btnexit = new JButton("Exit");
    panel.add(btnexit);
    btnexit.setSize(64,32);
    btnexit.setVisible(true);
    btnexit.setLocation(256,0);

    // Create info button (size, text, etc.)
    JButton btninfo = new JButton("Info");
    panel.add(btninfo);
    btninfo.setSize(64,32);
    btninfo.setVisible(true);
    btninfo.setLocation(192,0);

    // Add function to the lbutton for mouse event
    lbutton.addMouseListener(new java.awt.event.MouseAdapter() {
        int vbtnclicks = 0; 
        public void mouseClicked(java.awt.event.MouseEvent evt) {
            vbtnclicks = vbtnclicks + 1;

            //The following code prints out the number of times the user has clicked the button
            if (vbtnclicks > 2) { 
                System.out.println("You moved left " + vbtnclicks + " times!");
                }

            else if (vbtnclicks == 1) {
                System.out.println("You moved left once!");
                }

            else if (vbtnclicks == 2){
                System.out.println("You moved left twice!");
            }

            else {
                // The following code should not have to show up
                System.out.println("I get the sense this code has been meddled with...");
            }

        }
    });

    // Add mouse event for rbutton
    rbutton.addMouseListener(new java.awt.event.MouseAdapter() {
        int cbtnclicks = 0; 
        public void mouseClicked(java.awt.event.MouseEvent evt) {
            cbtnclicks = cbtnclicks + 1;

            //The following code prints out the number of times the user has clicked the button
            if (cbtnclicks > 2) { 
                System.out.println("You moved right " + cbtnclicks + " times!");
                }

            else if (cbtnclicks == 1) {
                System.out.println("You moved right once!");
                }

            else if (cbtnclicks == 2){
                System.out.println("You moved right twice!");
            }

            else {
                // The following code should not have to show up
                System.out.println("I get the sense this code has been meddled with...");
            }

        }
    });

    // Add mouse event for btndodge
            btndodge.addMouseListener(new java.awt.event.MouseAdapter() {
                int dbtnclicks = 0; 
                public void mouseClicked(java.awt.event.MouseEvent evt) {
                    dbtnclicks = dbtnclicks + 1;

                    //The following code prints out the number of times the user has clicked the button
                    if (dbtnclicks > 2) { 
                        System.out.println("You ducked " + dbtnclicks + " times!");
                        }

                    else if (dbtnclicks == 1) {
                        System.out.println("You ducked once!");
                        }

                    else if (dbtnclicks == 2){
                        System.out.println("You ducked twice!");
                    }

                    else {
                        // The following code should not have to show up
                        System.out.println("I get the sense this code has been meddled with...");
                    }

                }
            });

    // Add mouse event and exit command to the exit button
    btnexit.addMouseListener(new java.awt.event.MouseAdapter() {
        public void mouseClicked(java.awt.event.MouseEvent evt) {


            System.exit(0);
    }
    });

    // Add function to the "Info" button
    btninfo.addMouseListener(new java.awt.event.MouseAdapter() {
        public void mouseClicked(java.awt.event.MouseEvent evt) {

            // Open an Info Window with specific settings
            JFrame inframe = new JFrame("Info");

            JLabel inlabel = new JLabel("This is the info text.");
            inlabel.setPreferredSize(new Dimension(300,100));
            inframe.getContentPane().add(inlabel, BorderLayout.CENTER);

            inframe.setLocationRelativeTo(null);
            inframe.pack();
            inframe.setVisible(true);

            JPanel inpanel = new JPanel();
            inframe.add(inpanel);

            JButton inextbtn = new JButton("Exit Info");
            inpanel.add(inextbtn);

            inextbtn.setSize(96,24);
            inextbtn.setVisible(true);
            inextbtn.setLocation(0,0);

            inextbtn.addMouseListener(new java.awt.event.MouseAdapter() {
                public void mouseClicked(java.awt.event.MouseEvent evt) {

                    inframe.dispose();
                    }
            });
        }
    });
    }

}

最佳答案

您的主要问题(infoLabel 未显示)是由于您在将 JPanel 添加到其 contentPane 之前在其 JFrame 上调用了 setVisible(true) 。将所有组件添加到 JFrame 之后始终调用 setVisible(true)。由于 inFrame 使用 BorderLayout,您还可以通过将 JPanel 添加到 JFrame 来覆盖 JLabel。

其他问题:

  • 是的,对 JButton 使用 ActionListener,而不是 MouseListener。如果按钮获得焦点并且按下空格键,ActionListener 将做出响应——这是预期的且正确的行为。 MouseListener 不会。另外,如果禁用 JButton,ActionListener 将无法工作,这也是预期的且正确的,而 MouseListener 在这里又会出现错误。
  • 不要设置 GUI 组件的绝对大小或位置,而是让组件默认首选大小,然后容器布局管理器为您完成这项繁重的工作。
  • 信息窗口应该是 JDialog 而不是 JFrame,因为可见应用程序应该只有一个主框架窗口,即一个 JFrame。

例如:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class CombineInput2 {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            MainPanel mainPanel = new MainPanel();
            JFrame frame = new JFrame("Main GUI");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }

}

class MainPanel extends JPanel {
    public MainPanel() {
        setPreferredSize(new Dimension(400, 400));
        add(new JButton(new InfoAction("Info", this)));
        add(new JButton(new ExitAction()));
    }
}

class InfoAction extends AbstractAction {
    private MainPanel mainPanel;
    private JDialog dialog;

    public InfoAction(String name, MainPanel mainPanel) {
        super(name);
        this.mainPanel = mainPanel;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (dialog == null) {
            Window win = SwingUtilities.getWindowAncestor(mainPanel);
            dialog = new JDialog(win, "Info", ModalityType.APPLICATION_MODAL);
            dialog.add(new DialogPanel());
            dialog.pack();
            dialog.setLocationRelativeTo(win);
        }
        dialog.setVisible(true);
    }
}

class DialogPanel extends JPanel {
    private static final int DP_WIDTH = 250;
    private static final int DP_HEIGHT = 100;
    private String text = "This is the info text.";
    private JLabel infoLabel = new JLabel(text, SwingConstants.CENTER);

    public DialogPanel() {
        JPanel btnPanel = new JPanel();
        Action exitAction = new ExitAction();
        exitAction.putValue(Action.NAME, "Exit Info");
        btnPanel.add(new JButton(exitAction));

        setLayout(new BorderLayout());
        add(infoLabel, BorderLayout.CENTER);
        add(btnPanel, BorderLayout.PAGE_START);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension prefSz = super.getPreferredSize();

        if (isPreferredSizeSet()) {
            return prefSz;
        }
        int width = Math.max(prefSz.width, DP_WIDTH);
        int height = Math.max(prefSz.height, DP_HEIGHT);
        return new Dimension(width, height);
    }
}

class ExitAction extends AbstractAction {
    public ExitAction() {
        super("Exit");
        putValue(MNEMONIC_KEY, KeyEvent.VK_X);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Component c = (Component) e.getSource();
        if (c == null) {
            return;
        }
        Window win = SwingUtilities.getWindowAncestor(c);
        if (win != null) {
            win.dispose();
        }
    }
}

关于java - 如何让 GUI 按钮正确响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40812831/

相关文章:

java - 使用 Mockito,如何在 void 方法上拦截回调对象?

java - 如何在 Oracle "Fix versions"和 Oracle JDK 版本之间进行转换?

java - 如何使字体列表在 JComboBox 中工作

java - 引用 JPanel Action 监听器内部的类

Java Swing - 按钮不改变宽度大小

java - 图像未显示在 JPanel 中

java - JFrame 重绘后不刷新

java - 未捕获自定义 RuntimeException

java - JTabbedPane 首先显示错误的选项卡组件

java - 需要从 JFrame 获取输入并在不同的类中使用它(Pro-Engineer 的 J-link 应用程序)