英文:
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
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,用来说明这种模型/视图/控制器模式。
我首先定义了一些字段和一个数组。
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();
}
});
}
我调用 SwingUtilities
的 invokeLater
方法,以确保我创建和执行的 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”JLabel
和 JTextField
,另一个用于容纳 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
方法编写为一个独立的方法,因为我们将在 ActionListener
的 actionPerformed
方法中使用这个方法。
我们使用 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.
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("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. 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("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. 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 < 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
. 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("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);
}
}
答案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("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 lamda:
button25.addActionListener((e) ->
{
value25 += 25;
label.setText("Value: " + value25);
}
button10.addActionListener((e) ->
{
value10 += 10;
label.setText("Value: " + value10);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论