简体   繁体   English

如何在 Java GUI Swing 中制作更多按钮

[英]how to make more buttons in java GUI swing

I would like to use the java swing to make two buttons, one that add +25 to 100, the initial value, and one other that adds +10 to 100, always the initial value:我想使用java swing制作两个按钮,一个将+25加到100,初始值,另一个将+10加到100,始终是初始值:

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

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GUI implements ActionListener {
    private int button1 = 100;
    private int button2 = 100;
    private JLabel label;
    private JFrame frame;
    private JPanel panel;
    
    
    public GUI() {
        
        JFrame frame = new JFrame();
        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();
        // Bottone & etichetta per il player 1
        JButton button = new JButton("add 25");
        panel1.add(button);
        button.addActionListener(this);
        label = new JLabel("initial value: 100");
        panel1.add(label);
        // Bottone & etichetta per il player 1
        JButton button1 = new JButton("add 10");
        panel2.add(button1);
        button1.addActionListener(this);
        label = new JLabel("initial value: 100");
        panel1.add(label);
        
        
        // Impostazioni della finestra
        panel1.setBorder(BorderFactory.createEmptyBorder(30, 30, 10, 30));
        panel1.setLayout(new GridLayout(0, 1));
    
        frame.add(panel1, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("GUI");
        frame.pack();
        frame.setVisible(true);
        // Impostazioni della finestra
     }  
        public static void main(String args[]) {
            new GUI();
       
        
    }
        @Override
        public void actionPerformed(ActionEvent e) {
            button1 = button1 + 25;
             label.setText("Value: " + button1);
        }
        public void actionPerformed2(ActionEvent e) {
            button2 = button2 + 10;
            label.setText("Value: " + button2);
        }
    
}

as you can see it should create two buttons, this is what I receive as output at first:正如您所看到的,它应该创建两个按钮,这是我最初收到的输出:

(button) add 25
(label) initial value: 100
(label) initial value: 100

https://i.stack.imgur.com/1MSHz.png

and after I click it, it just adds 25 to the first one:在我点击它之后,它只会在第一个增加 25:

(button) add 25
(label) initial value: 125
(label) initial value: 100

When creating a Swing GUI, it's a really good idea to separate your data model from the GUI view.创建 Swing GUI 时,最好将数据模型与 GUI 视图分开。 This separation makes it easier to code the model and easier to code the view.这种分离使得对模型进行编码和对视图进行编码变得更加容易。 The controller updates the model, which in turn updates the view.控制器更新模型,进而更新视图。

Here's a GUI I whipped up to illustrate this model / view / controller pattern.这是我为说明这个模型/视图/控制器模式而制作的 GUI。

增量图形用户界面

The first thing I did was define some fields and an array.我做的第一件事是定义一些字段和一个数组。

private int[] values;

private int startValue;
private int currentValue;

The startValue is the starting value (100), the currentValue is the current value (205 in the picture), and values is an int array that holds the values 10 and 25. startValue是起始值(100), currentValue是当前值(图中为 205), values是一个int数组,其中包含值 10 和 25。

Here's the code that sets these values.这是设置这些值的代码。 I set these values in the constructor of the class, so they're set before anything else happens.我在类的构造函数中设置了这些值,因此它们会在其他任何事情发生之前设置。

public IncrementGUI() {
    this.startValue = 100;
    this.currentValue = startValue;
    this.values = new int[] { 10, 25 };
}

Since I put the values in an int array, if I want to add another value, all I have to do is add the value to the values array.由于我将值放在一个int数组中,如果我想添加另一个值,我所要做的就是将值添加到values数组中。

Now that we have the model built, let's start on the view.现在我们已经建立了模型,让我们从视图开始。 This is my main method.这是我的主要方法。

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            IncrementGUI inc = new IncrementGUI();
            inc.createJFrame();
        }
    });
}

I call the SwingUtilities invokeLater method to ensure that the Swing components I create and execute are created and executed on the Event Dispatch Thread .我调用SwingUtilities invokeLater方法来确保我创建和执行的 Swing 组件是在Event Dispatch Thread上创建和执行的。 This keeps us from having threading problems with the GUI.这可以防止我们在 GUI 上遇到线程问题。

When I instantiate the class, the model fields are set in the constructor, then the GUI is created.当我实例化类时,模型字段在构造函数中设置,然后创建 GUI。

Here's the method I wrote to create the JFrame.这是我编写的用于创建 JFrame 的方法。

private void createJFrame() {
    JFrame frame = new JFrame("Increment Value");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    frame.add(createValuePanel(), 
            BorderLayout.BEFORE_FIRST_LINE);
    frame.add(createButtonPanel(), BorderLayout.CENTER);
    
    frame.pack();
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
}

The JFrame methods have to be called in a specific order. JFrame 方法必须按特定顺序调用。 This is the order that I use for most of my Swing applications.这是我用于大多数 Swing 应用程序的顺序。

The setDefaultCloseOperation method allows me to close the application when the X button in the upper right is left-clicked. setDefaultCloseOperation方法允许我在左键单击右上角的 X 按钮时关闭应用程序。 The pack method takes the Swing components and "packs" them into the smallest possible JFrame consistent with the size of the Swing components. pack方法将 Swing 组件“打包”到与 Swing 组件大小一致的尽可能小的JFrame The setLocationByPlatform method sets the location of the JFrame on the screen consistent with the platform operating system. setLocationByPlatform方法设置JFrame在屏幕上的位置与平台操作系统一致。 Finally, the setVisible method makes the JFrame visible.最后, setVisible方法使JFrame可见。

We created two JPanels , one to hold the "Value" JLabel and JTextField , and the other to hold the JButtons .我们创建了两个JPanels ,一个用于保存“Value” JLabelJTextField ,另一个用于保存JButtons We do this because I want to use two different Swing layout managers to layout the Swing components.我们这样做是因为我想使用两个不同的Swing 布局管理器来布局 Swing 组件。

The JFrame has a BorderLayout by default. JFrame默认有一个BorderLayout I placed the value JPanel before the first line (on top) and the button JPanel in the center.我将值JPanel放在第一行(顶部)之前,并将按钮JPanel放在中间。

Next, I coded the details of the value JPanel in the createValuePanel method.接下来,我在createValuePanel方法中对值JPanel的详细信息进行了编码。

private JPanel createValuePanel() {
    JPanel panel = new JPanel(new FlowLayout());
    
    JLabel label = new JLabel("Value: ");
    panel.add(label);
    
    valueField = new JTextField(10);
    valueField.setEditable(false);
    setValueField(currentValue);
    panel.add(valueField);
    
    return panel;
}

public void setValueField(int value) {
    valueField.setText(NF.format(value));
}

I used a JTextField to hold the current value.我使用JTextField来保存当前值。 I made it non-editable, so the user cannot change the value.我使它不可编辑,因此用户无法更改该值。

I wrote the setValueField method as a separate method because we're going to use this method in the actionPerformed method of the ActionListener .我将setValueField方法编写为一个单独的方法,因为我们将在ActionListeneractionPerformed方法中使用此方法。

We use a FlowLayout because I want the Swing components to flow from left to right.我们使用FlowLayout是因为我希望 Swing 组件从左到右流动。

Next, I coded the details of the button JPanel in the createButtonPanel method.接下来,我在createButtonPanel方法中编写了按钮JPanel的详细信息。

private JPanel createButtonPanel() {
    JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
    panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    
    for (int index = 0; index < values.length; index++) {
        JButton button = new JButton("Add " + values[index]);
        button.addActionListener(this);
        button.setActionCommand(Integer.toString(values[index]));
        panel.add(button);
    }
    
    return panel;
}

I used a GridLayout to hold a single column of the JButtons .我用了一个GridLayout保持的单个列JButtons I put some empty space around the JButtons with an empty border to make the GUI more visually appealing.我在带有空边框的JButtons周围放置了一些空白空间,以使 GUI 更具视觉吸引力。

Because I create the JButtons in a for loop, I create as many JButtons as there are values in the values array.因为我在 for 循环中创建JButtons ,所以我创建了与values数组中的values一样多的JButtons This way, when you add a value to the values array, a new JButton will be created.这样,当您向values数组添加一个值时,将创建一个新的 JButton。

A JButton can hold an action command String as well as display text. JButton可以保存操作命令String以及显示文本。 We use this action command String to pass the increment value to the actionPerformed method.我们使用此操作命令String actionPerformed量值传递给actionPerformed方法。

Finally, I coded the actionPerformed method.最后,我编写了actionPerformed方法。 It's pretty simple.这很简单。 I get the increment value from the JButton , increment the current value, and display the current value in the JTextField .我从JButton获取增量值,增加当前值,并在JTextField显示当前值。

@Override
public void actionPerformed(ActionEvent event) {
    int value = Integer.valueOf(event.getActionCommand());
    currentValue += value;
    setValueField(currentValue);
}

Here's the entire runnable example.这是整个可运行示例。 I hope this explanation helps you to create more complex Swing GUIs.我希望这个解释可以帮助您创建更复杂的 Swing GUI。

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class IncrementGUI implements ActionListener {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                IncrementGUI inc = new IncrementGUI();
                inc.createJFrame();
            }
        });
    }
    
    private static NumberFormat NF = 
            NumberFormat.getIntegerInstance();
    
    private int[] values;
    
    private int startValue;
    private int currentValue;
    
    private JTextField valueField;
    
    public IncrementGUI() {
        this.startValue = 100;
        this.currentValue = startValue;
        this.values = new int[] { 10, 25 };
    }
    
    private void createJFrame() {
        JFrame frame = new JFrame("Increment Value");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createValuePanel(), 
                BorderLayout.BEFORE_FIRST_LINE);
        frame.add(createButtonPanel(), BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createValuePanel() {
        JPanel panel = new JPanel(new FlowLayout());
        
        JLabel label = new JLabel("Value: ");
        panel.add(label);
        
        valueField = new JTextField(10);
        valueField.setEditable(false);
        setValueField(currentValue);
        panel.add(valueField);
        
        return panel;
    }
    
    public void setValueField(int value) {
        valueField.setText(NF.format(value));
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        for (int index = 0; index < values.length; index++) {
            JButton button = new JButton("Add " + values[index]);
            button.addActionListener(this);
            button.setActionCommand(Integer.toString(values[index]));
            panel.add(button);
        }
        
        return panel;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        int value = Integer.valueOf(event.getActionCommand());
        currentValue += value;
        setValueField(currentValue);
    }

}

您没有将 panel2 添加到 JFrame 中,尽管我建议将两个按钮都放在一个 JPanel 上。

private int button1 = 100;
...

public GUI() 
{
    ...
    JButton button1 = new JButton("add 10");

Don't use the same variable name in your class.不要在类中使用相同的变量名。 It is extremely confusing to have a local variable and instance variable with the same name.具有相同名称的局部变量和实例变量非常令人困惑。 A variable name should be descriptive.变量名应该是描述性的。 So maybe you have variables like:所以也许你有这样的变量:

private int value10 = 100;
...

public GUI() 
{
    ...
    JButton button10 = new JButton("add 10");

to indicate that the button10 button is used to increment the value of value10.表示 button10 按钮用于增加 value10 的值。

but it should add 10 to the second one但它应该在第二个上加 10

public void actionPerformed2(ActionEvent e) {

You can't just make up a method by adding a "2" to the end of the method name.您不能仅仅通过在方法名称的末尾添加“2”来组成方法。 That code will never be invoked.该代码永远不会被调用。 If you have two buttons, then you need two ActionListeners.如果您有两个按钮,那么您需要两个 ActionListener。

The easiest way to do this is to use a lamda:最简单的方法是使用 lamda:

button25.addActionListener((e) ->
{
    value25 += 25;
    label.setText("Value: " + value25);
}

button10.addActionListener((e) ->
{
    value10 += 10;
    label.setText("Value: " + value10);
}

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

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