简体   繁体   English

Java-我的动作事件无效

[英]Java - My action event doesn't work

I'm learning Java and Swing, but my JButton doesn't work. 我正在学习Java和Swing,但是我的JButton不起作用。

import javax.swing.JFrame;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Programma {

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

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }

        catch (Exception e){
            e.printStackTrace();
        }


        JFrame frame = new JFrame("DIG");
        JPanel panel = new JPanel();
        JButton button = new JButton("Click Me");

        frame.setSize(400, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        button.setBounds(100, 100, 130, 35);

        panel.add(button);
        frame.add(panel);

        button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub

                JLabel label = new JLabel("Hello World");
                label.setVisible(true);
                panel.add(label);

            }
        });

    }
}
  1. The frame and button are visible, nut when I click it, the label doesn't appear. 框架和按钮是可见的,当我单击框架和按钮时,它不会出现标签。 How can I fix this? 我怎样才能解决这个问题?

  2. Do I write this before the other component like JPanel, JButton, etc., or do I write this at the end of code: 我应该在其他组件(例如JPanel,JButton等)之前编写此代码,还是在代码末尾编写以下代码:

    frame.setVisible(true);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

What is the difference ? 有什么区别 ?

By the way, button.setBounds(100, 100, 130, 35) doesn't work, either. 顺便说一句, button.setBounds(100, 100, 130, 35)也不起作用。

I see some issues in your code: 我在您的代码中看到了一些问题:

  1. button.setBounds(100, 100, 130, 35); that line will be ignored and you shouldn't be manually be determining the position of the components. 该行将被忽略,您不应该手动确定组件的位置。 See Null layout is evil and Why is it frowned upon to use a null layout in swing? 请参见Null布局是邪恶的为什么不赞成在swing中使用null布局? altough you're not using null layout, there is explained why you shouldn't be manually determining the positions of the components. 尽管您没有使用null布局,但解释了为什么不应该手动确定组件的位置。

  2. You're running everything in your program in the main method, that will be hard to maintain later. 您正在使用main方法运行程序中的所有内容,以后将很难维护。

  3. You're calling frame.setVisible(true) before you've added all your elements to it, that will cause you random issues. 在将所有元素添加到frame.setVisible(true)之前,您将调用它,这将导致随机问题。

  4. You're not running your program on the Event Dispatch Thread (EDT) , you can solve this by starting your program with the following code, which places it in the EDT. 您没有在事件调度线程(EDT)上运行程序,可以通过以下代码启动程序来解决此问题,并将其放在EDT中。 It's recommended as Swing is not thread safe. 推荐使用Swing并不是线程安全的。

     public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { //Your constructor here } }); } 
  5. You're setting the size of the JFrame with setSize(...) , instead call frame.pack() and override the getPreferredSize() method of the JPanel . 您可以使用setSize(...)设置JFrame的大小,而不是调用frame.pack()并重写JPanelgetPreferredSize()方法。


After all the above has been said, you need to call revalidate() and repaint() on your ActionListener so your program paints its new state. 说完上述所有内容后,您需要在ActionListener上调用revalidate()repaint() ,以便您的程序绘制其新状态。

This program follows all the above recommendations and produces the following outputs (before clicking and after clicking the button 3 times), I on purpose to not make the images so large, made the GUI shorter (200 x 200 instead of 400 x 400) 该程序遵循上述所有建议,并产生以下输出(单击之前和单击按钮3次之后),我故意使图像不变得如此大,使GUI较短(200 x 200而不是400 x 400)

在此处输入图片说明 在此处输入图片说明

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Programma {

    private JFrame frame;
    private JPanel panel;
    private JButton button;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Programma().createAndShowGui();
            }
        });
    }

    public void createAndShowGui() {
        frame = new JFrame("DIG");
        panel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
        };
        button = new JButton("Click Me");

        panel.add(button);

        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JLabel label = new JLabel("Hello World");
                panel.add(label);

                panel.revalidate();
                panel.repaint();
            }
        });

        frame.add(panel);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Do i write this before the other componente like JPanel,JButton... or do i write this at the end of code ? 我是在JPanel,JButton等其他组件之前编写此代码还是在代码末尾编写此代码?

frame.setVisible(true); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

What is the difference ? 有什么区别 ?

Altough I answered this on the recommendations, the difference is that if you call setVisible before adding all your elements to the frame, then you'll find yourself with some random issues where the components are not all visible until you pass your mouse over them (or where they should be). 尽管我在建议中回答了这个问题,但不同之处在于,如果在将所有元素添加到框架之前调用setVisible ,则会遇到一些随机问题,在这些问题上,除非您将鼠标移到组件上,否则所有组件都不可见(或应该在哪里)。 frame.pack() and setVisible should be the last ones to be called in your program, and frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack()setVisible应该是程序中要调用的最后一个,并且frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); can be at the start or the end, it doesn't affects, but I prefer to have it at the end too. 可以在开始或结束时使用,但不受影响,但我也希望在结束时使用。

button.setBounds(100, 100, 130, 35); button.setBounds(100,100,130,35); doesn't work too. 也行不通。

Well, that's because of you're using a layout manager (and that's the right way to do your GUIs) instead of a null-layout (which you shouldn't be using anyway) (See point #1). 好吧,这是因为您使用的是布局管理器 (这是执行GUI的正确方法),而不是使用null-layout (无论如何您都不应使用)(请参阅第1点)。


Edit 编辑

What is the difference between frame.setSize(); frame.setSize();有什么区别? and frame.setpack() ? 和frame.setpack()?

If you read the docs for pack() : 如果您阅读pack()文档

Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. 使此窗口的大小适合其子组件的首选大小和布局。 The resulting width and height of the window are automatically enlarged if either of dimensions is less than the minimum size as specified by the previous call to the setMinimumSize method. 如果任意一个尺寸小于上一次调用setMinimumSize方法指定的最小尺寸,则窗口的宽度和高度将自动放大。

So, it will calculate the minimum size for your JFrame where all the elements are visible and in their preferred size while setSize will only set the window size, but if you place a JScrollBar inside it for example this will reduce the window size, because of that, that's why you should override the getPreferredSize(...) method of your container, so it will calculate its preferred size including the width of the JScrollBar or some other elements that could modify its size. 因此,它将为您的JFrame计算最小尺寸,在该尺寸下所有元素都是可见的且处于其首选尺寸,而setSize仅设置窗口尺寸,但是例如,如果在其中放置JScrollBar ,则会减小窗口尺寸,因为因此,您应该重写容器的getPreferredSize(...)方法,以便它将计算其首选大小,包括JScrollBar的宽度或其他可以修改其大小的元素。 See Should I avoid the use of setPreferred|Maximum|MinimumSize in Swing? 请参阅我应该避免在Swing中使用setPreferred | Maximum | MinimumSize吗? (the general consensus says yes ) (一般共识

When you add components dynamically to panel, you need to repain it. 将组件动态添加到面板时,需要重新添加面板。

Do this 做这个

panel.revalidate(); 

after

panel.add(label);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM