如何在Java GUI Swing中创建更多的按钮

huangapple go评论76阅读模式
英文:

how to make more buttons in java GUI swing

问题

我想使用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();
        // 按钮和标签,用于第一个按钮
        JButton button = new JButton("添加25");
        panel1.add(button);
        button.addActionListener(this);
        label = new JLabel("初始值:100");
        panel1.add(label);
        // 按钮和标签,用于第二个按钮
        JButton button1 = new JButton("添加10");
        panel2.add(button1);
        button1.addActionListener(this);
        label = new JLabel("初始值:100");
        panel2.add(label);

        // 窗口设置
        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);
        // 窗口设置
    }

    public static void main(String args[]) {
        new GUI();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        button1 = button1 + 25;
        label.setText("值: " + button1);
    }

    public void actionPerformed2(ActionEvent e) {
        button2 = button2 + 10;
        label.setText("值: " + button2);
    }
}

正如您所看到的,它应该创建两个按钮。这是我一开始收到的输出:

(button) 添加25
(label) 初始值:100
(label) 初始值:100

在我点击按钮后,它只是将25添加到第一个按钮:

(button) 添加25
(label) 初始值:125
(label) 初始值:100

英文:

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:

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

如何在Java GUI Swing中创建更多的按钮

and after I click it, it just adds 25 to the first one:

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

答案1

得分: 2

当创建一个 Swing GUI 时,将数据模型与 GUI 视图分离是一个非常好的想法。这种分离使得编写模型和视图变得更容易。控制器更新模型,进而更新视图。

这是一个我快速制作的 GUI,用来说明这种模型/视图/控制器模式。

如何在Java GUI Swing中创建更多的按钮

我首先定义了一些字段和一个数组。

private int[] values;

private int startValue;
private int currentValue;

startValue 是起始值(100),currentValue 是当前值(图片中为 205),values 是一个 int 数组,其中包含值 10 和 25。

这是设置这些值的代码。我在类的构造函数中设置这些值,所以它们在其他任何事情发生之前就被设置了。

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

由于我将这些值放在一个 int 数组中,如果我想要添加另一个值,我只需要将该值添加到 values 数组中。

现在我们已经构建了模型,让我们开始制作视图。这是我的主方法。

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

我调用 SwingUtilitiesinvokeLater 方法,以确保我创建和执行的 Swing 组件是在 事件分派线程(Event Dispatch Thread) 上创建和执行的。这可以防止 GUI 出现线程问题。

当我实例化这个类时,模型字段被设置在构造函数中,然后创建 GUI。

这是我编写的用于创建 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);
}

必须按特定顺序调用 JFrame 方法。这是我大多数 Swing 应用程序使用的顺序。

setDefaultCloseOperation 方法允许我在左上角的 X 按钮被左键单击时关闭应用程序。pack 方法将 Swing 组件“打包”到与 Swing 组件大小一致的最小可能 JFrame 中。setLocationByPlatform 方法将 JFrame 的位置设置为与平台操作系统一致。最后,setVisible 方法使 JFrame 可见。

我们创建了两个 JPanels,一个用于容纳“Value”JLabelJTextField,另一个用于容纳 JButtons。我们这样做是因为我想使用两种不同的 Swing 布局管理器 来布局 Swing 组件。

默认情况下,JFrame 使用 BorderLayout。我将值 JPanel 放在第一行之前(顶部),将按钮 JPanel 放在中心。

接下来,我在 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));
}

我使用一个 JTextField 来保存当前值。我将其设置为不可编辑,所以用户无法更改该值。

我将 setValueField 方法编写为一个独立的方法,因为我们将在 ActionListeneractionPerformed 方法中使用这个方法。

我们使用 FlowLayout,因为我希望 Swing 组件从左到右流动。

接下来,我在 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;
}

我使用 GridLayout 来容纳单列的 JButtons。我用一个空边框在 JButtons 周围添加了一些空白空间,以使 GUI 更具视觉吸引力。

因为我在循环中创建 JButtons,所以我会创建与 values 数组中的值一样多的 JButtons。这样,当你向 values 数组中添加一个值时,将会创建一个新的 JButton。

JButton 可以包含一个操作命令 String,以及显示文本。我们使用这个操作命令 String 将递增值传递给 actionPerformed 方法。

最后,我编写了 actionPerformed 方法。这非常简单。我从 JButton 获取递增值,增加当前值,并在 JTextField 中显示当前值。

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

这是完整的可运行示例。希望这个解释能够帮助您创建更复杂的 Swing GUI。

英文:

When creating a Swing GUI, it's a really good idea to separate your data model from the GUI view. 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.

如何在Java GUI Swing中创建更多的按钮

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.

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.

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. This keeps us from having threading problems with the GUI.

When I instantiate the class, the model fields are set in the constructor, then the GUI is created.

Here's the method I wrote to create the JFrame.

private void createJFrame() {
JFrame frame = new JFrame(&quot;Increment Value&quot;);
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. This is the order that I use for most of my Swing applications.

The setDefaultCloseOperation method allows me to close the application when the X button in the upper right is left-clicked. The pack method takes the Swing components and "packs" them into the smallest possible JFrame consistent with the size of the Swing components. The setLocationByPlatform method sets the location of the JFrame on the screen consistent with the platform operating system. Finally, the setVisible method makes the JFrame visible.

We created two JPanels, one to hold the "Value" JLabel and JTextField, and the other to hold the JButtons. We do this because I want to use two different Swing layout managers to layout the Swing components.

The JFrame has a BorderLayout by default. I placed the value JPanel before the first line (on top) and the button JPanel in the center.

Next, I coded the details of the value JPanel in the createValuePanel method.

private JPanel createValuePanel() {
JPanel panel = new JPanel(new FlowLayout());
JLabel label = new JLabel(&quot;Value: &quot;);
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. 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.

We use a FlowLayout because I want the Swing components to flow from left to right.

Next, I coded the details of the button JPanel in the createButtonPanel method.

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 &lt; values.length; index++) {
JButton button = new JButton(&quot;Add &quot; + 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. I put some empty space around the JButtons with an empty border to make the GUI more visually appealing.

Because I create the JButtons in a for loop, I create as many JButtons as there are values in the values array. This way, when you add a value to the values array, a new JButton will be created.

A JButton can hold an action command String as well as display text. We use this action command String to pass the increment value to the actionPerformed method.

Finally, I coded the actionPerformed method. It's pretty simple. I get the increment value from the JButton, increment the current value, and display the current value in the 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.

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(&quot;Increment Value&quot;);
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(&quot;Value: &quot;);
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 &lt; values.length; index++) {
JButton button = new JButton(&quot;Add &quot; + 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);
}
}

答案2

得分: 0

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

英文:

You didn't add panel2 to your JFrame, altough I would suggest just putting both buttons on one JPanel.

答案3

得分: 0

private int value10 = 100;
...

public GUI() 
{
    ...
    JButton button10 = 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.

> but it should add 10 to the second one

public void actionPerformed2(ActionEvent e) {

You can't just make up a method by adding a "2" to the end of the method name. That code will never be invoked. If you have two buttons, then you need two ActionListeners.

The easiest way to do this is to use a lambda:

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

button10.addActionListener((e) ->
{
    value10 += 10;
    label.setText("Value: " + value10);
}
英文:
private int button1 = 100;
...
public GUI() 
{
...
JButton button1 = new JButton(&quot;add 10&quot;);

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(&quot;add 10&quot;);

to indicate that the button10 button is used to increment the value of value10.

> but it should add 10 to the second one

public void actionPerformed2(ActionEvent e) {

You can't just make up a method by adding a "2" to the end of the method name. That code will never be invoked. If you have two buttons, then you need two ActionListeners.

The easiest way to do this is to use a lamda:

button25.addActionListener((e) -&gt;
{
value25 += 25;
label.setText(&quot;Value: &quot; + value25);
}
button10.addActionListener((e) -&gt;
{
value10 += 10;
label.setText(&quot;Value: &quot; + value10);
}

huangapple
  • 本文由 发表于 2020年10月11日 21:25:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/64304509.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定