英文:
This GUI is displaying nothing after setting BoxLayout
问题
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUI_Borrower extends JFrame implements ActionListener {
JPanel panel = new JPanel();
JLabel lblName = new JLabel("Name:");
JLabel lblProg = new JLabel("Program:");
JLabel lblId = new JLabel("Library ID: ");
JLabel lblTitle = new JLabel("Add Borrower");
JTextField txtName = new JTextField(10);
JTextField txtProg = new JTextField(10);
JTextField txtId = new JTextField(10);
static int counter = 19000;
JButton btnSubmit = new JButton("Submit");
public GUI_Borrower() {
super("Add Borrower");
makeFrame();
showFrame();
}
public void makeFrame() {
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
add(lblTitle);
add(lblName);
add(txtName);
JPanel progPanel = new JPanel(); // Create a panel for program components
progPanel.add(lblProg);
progPanel.add(txtProg);
panel.add(progPanel); // Add the program panel to the main panel
JPanel idPanel = new JPanel(); // Create a panel for ID components
idPanel.add(lblId);
idPanel.add(txtId);
panel.add(idPanel); // Add the ID panel to the main panel
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(btnSubmit);
btnSubmit.addActionListener(this);
}
public void showFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 200);
setLocationRelativeTo(null);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtProg.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") && txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
counter++;
txtId.setText("" + counter);
btnSubmit.setText("Confirm");
}
}
}
public static void main(String[] args) {
new GUI_Borrower();
}
}
英文:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUI_Borrower extends JFrame implements ActionListener {
JPanel panel = new JPanel();
JLabel lblName = new JLabel("Name:");
JLabel lblProg = new JLabel("Program:");
JLabel lblId = new JLabel("Library ID: ");
JLabel lblTitle = new JLabel("Add Borrower");
JTextField txtName = new JTextField(10);
JTextField txtProg = new JTextField(10);
JTextField txtId = new JTextField(10);
static int counter = 19000;
JButton btnSubmit = new JButton("Submit");
public GUI_Borrower() {
super("Add Borrower");
makeFrame();
showFrame();
}
public void makeFrame() {
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
add(lblTitle);
add(lblName);
add(txtName);
add(lblProg);
add(txtProg);
add(lblId);
add(txtId);
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(btnSubmit);
btnSubmit.addActionListener(this);
}
public void showFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 200);
setLocationRelativeTo(null);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtProg.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") && txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
counter++;
txtId.setText("" + counter);
btnSubmit.setText("Confirm");
}
}
}
public static void main(String[] args) {
new GUI_Borrower();
}
}
I tried adding BoxLayout
because all the text fields and labels are on one line. So I tried box Layout and failed.
Can anyone show me how to make it like the title one line, label Different line, button different line?
Like this:
答案1
得分: 3
正如camickr在他的评论中所说,通常使用GridBagLayout
来创建一个表单。
我重新修改了你的代码,因为我希望展示一种更好的编写GUI面板的方法。
这是GUI界面。
我所做的主要更改包括:
-
所有的Swing应用程序都必须以对
SwingUtilities
的invokeLater
方法的调用开始。这个方法确保所有的Swing组件都在事件分派线程上创建和执行。 -
我将GUI代码组织成了三个方法,这样我可以一次专注于GUI的一个部分。在
run
方法中创建了JFrame
,在createTitlePanel
方法中创建了标题JPanel
,在createFormPanel
方法中创建了表单JPanel
。JFrame
的代码在不同的Swing应用程序之间很少会改变。 -
我使用了Swing组件。我没有扩展Swing组件,或者任何Java类,除非我打算重写类的某个方法。
-
createFormPanel
类使用了GridBagLayout
来组织标签和文本字段以形成列。你可以将GridBagLayout
想象成一个灵活的网格。网格的单元格大小不必相同。Oracle的教程,如何使用GridBagLayout,有另一个示例。 -
我将
ActionListener
放在了一个单独的类中。在这个示例中,我将它设置为内部类,这样我可以将代码粘贴成一个文件。通常,你应该将不同的类放在不同的文件中。这使得每个类都更短,更容易理解。
这是可运行的示例代码。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
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;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class BorrowerGUI implements Runnable {
private static int ID_COUNTER = 19000;
public static void main(String[] args) {
SwingUtilities.invokeLater(new BorrowerGUI());
}
private JButton btnSubmit;
private JTextField txtName;
private JTextField txtProg;
private JTextField txtId;
@Override
public void run() {
JFrame frame = new JFrame("Add Borrower");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTitlePanel(), BorderLayout.BEFORE_FIRST_LINE);
frame.add(createFormPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTitlePanel() {
JPanel panel = new JPanel(new FlowLayout());
JLabel lblTitle = new JLabel("Add Borrower");
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle);
return panel;
}
private JPanel createFormPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lblName = new JLabel("Name:");
panel.add(lblName, gbc);
gbc.gridx++;
txtName = new JTextField(20);
panel.add(txtName, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblProg = new JLabel("Program:");
panel.add(lblProg, gbc);
gbc.gridx++;
txtProg = new JTextField(20);
panel.add(txtProg, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblId = new JLabel("Library ID:");
panel.add(lblId, gbc);
gbc.gridx++;
txtId = new JTextField(20);
txtId.setEditable(false);
panel.add(txtId, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = 2;
btnSubmit = new JButton("Submit");
btnSubmit.addActionListener(new SubmitListener());
panel.add(btnSubmit, gbc);
return panel;
}
public class SubmitListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtName.requestFocus();
txtProg.setText("");
txtId.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") &&
txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
ID_COUNTER++;
txtId.setText("" + ID_COUNTER);
btnSubmit.setText("Confirm");
}
}
}
}
}
编辑以补充:如果你想让标题JLabel
右对齐,你需要切换到BorderLayout
。我添加了一个空边框,这样文本就不会出现在JFrame
的右边缘。
这是修改后的方法。
private JPanel createTitlePanel(String title) {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
JLabel lblTitle = new JLabel(title);
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle, BorderLayout.AFTER_LINE_ENDS);
return panel;
}
<details>
<summary>英文:</summary>
As camickr says in his comment, you generally use a `GridBagLayout` to create a form.
I reworked your code because I hope to show a better way to code a GUI panel.
Here's the GUI.
[![Add Borrower GUI][1]][1]
The major changes I made include:
1. All Swing applications must start with a call to the `SwingUtilities` `invokeLater` method. This method ensures that all Swing components are created and executed on the [Event Dispatch Thread][2].
2. I organized the GUI code into three methods so I could focus on one part of the GUI at a time. The `JFrame` is created in the `run` method. The title `JPanel` is created in the `createTitlePanel` method. The form `JPanel` is created in the `createFormPanel` method. The code for the `JFrame` will rarely change from Swing application to Swing application.
3. I use Swing components. I don't extend Swing components, or any Java class, unless I intend to override one of the class methods.
4. The `createFormPanel` class uses the `GridBagLayout` to organize the labels and text fields in columns. You can think of the `GridBagLayout` as a flexible grid. The cells of the grid don't have to be the same size. The Oracle tutorial, [How to Use GridBagLayout][3], has another example.
5. I put the `ActionListener` in a separate class. I made it an inner class in this example so I could paste the code as one file. Generally, you should put separate classes in separate files. It makes each class shorter and easier to understand.
Here's the runnable, example code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
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;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class BorrowerGUI implements Runnable {
private static int ID_COUNTER = 19000;
public static void main(String[] args) {
SwingUtilities.invokeLater(new BorrowerGUI());
}
private JButton btnSubmit;
private JTextField txtName;
private JTextField txtProg;
private JTextField txtId;
@Override
public void run() {
JFrame frame = new JFrame("Add Borrower");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTitlePanel(), BorderLayout.BEFORE_FIRST_LINE);
frame.add(createFormPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTitlePanel() {
JPanel panel = new JPanel(new FlowLayout());
JLabel lblTitle = new JLabel("Add Borrower");
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle);
return panel;
}
private JPanel createFormPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lblName = new JLabel("Name:");
panel.add(lblName, gbc);
gbc.gridx++;
txtName = new JTextField(20);
panel.add(txtName, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblProg = new JLabel("Program:");
panel.add(lblProg, gbc);
gbc.gridx++;
txtProg = new JTextField(20);
panel.add(txtProg, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblId = new JLabel("Library ID:");
panel.add(lblId, gbc);
gbc.gridx++;
txtId = new JTextField(20);
txtId.setEditable(false);
panel.add(txtId, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = 2;
btnSubmit = new JButton("Submit");
btnSubmit.addActionListener(new SubmitListener());
panel.add(btnSubmit, gbc);
return panel;
}
public class SubmitListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtName.requestFocus();
txtProg.setText("");
txtId.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") &&
txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
ID_COUNTER++;
txtId.setText("" + ID_COUNTER);
btnSubmit.setText("Confirm");
}
}
}
}
}
Edited to add: If you want the title `JLabel` to be right-justified, you'll have to switch to a `BorderLayout`. I added an empty border so the text wouldn't be on the right edge of the `JFrame`.
Here's the changed method.
private JPanel createTitlePanel(String title) {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
JLabel lblTitle = new JLabel(title);
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle, BorderLayout.AFTER_LINE_ENDS);
return panel;
}
[1]: https://i.stack.imgur.com/gmvKr.png
[2]: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
[3]: https://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论