- Published in CCW-I community in May 2003
- General to CSDN in September 2006, slightly modified
- In May 2021, use Markdown to re-typesetting, make some supplements, and go to SegmentFault. All codes were reformatted in the VSCode + Java Extensions Pack and JDK11 environment and the trial run was successful. Since the bug presented by the old version of the JDK interface has been fixed, the new screenshot will not match the original content, so the original screenshot is still used, but it is explained in the relevant position.
As a Java programmer, I feel that there are more and more people using Java to develop programs from the forum, and I can't help but feel relieved. However, also from the forums, most people think that Java is mentioned as web development-not so, Java can also develop applications, and can develop beautiful graphical user interface applications, that is, Windows/ XWindow application. Therefore, I wrote this article, hoping to take you into the door of Java graphical user interface design.
Next, let's start...
Note: All codes are written and tested under Windows XP + Eclipse environment, and the sample pictures are all captured under Windows XP.
table of Contents
One, AWT and Swing
Two, the framework, listeners and events
Three, buttons, toggle buttons, check buttons and radio buttons
Four, text input box, password input box
Five, pane, scroll pane and layout management
One, AWT and Swing
AWT and Swing are the basis for the design of GUI user interfaces in Java. Unlike the heavyweight components of AWT, most of Swing are lightweight components. For this reason, Swing is almost omnipotent, not only has a variety of advanced components, but also more beautiful and easy to use. So programmers who started using AWT soon switched to Swing.
So why didn't the AWT component die? Because Swing is based on AWT, there would be no Swing without AWT. So programmers can choose to use AWT or Swing according to their own habits. However, it is best not to mix the two-apart from the different display styles, it is likely to cause confusion in the level (Z-Order), such as the following example:
/**
* @(#) AwtSwing.java
* @author [James Fan](https://segmentfault.com/blog/jamesfancy)
*/
package jamesfan.uiDemo;
import java.awt.BorderLayout;
import java.awt.Button;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
public final class AwtSwing {
public static void main(String[] args) {
AwtSwing as = new AwtSwing();
as.show();
}
JFrame frame = new JFrame("Test AWT and SWING");
JDesktopPane jdp = new JDesktopPane();
JInternalFrame jif1 = new JInternalFrame("controls");
JInternalFrame jif2 = new JInternalFrame("cover");
public AwtSwing() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(jdp);
jif1.setContentPane(new JPanel());
jif2.setContentPane(new JPanel());
jif1.getContentPane().setLayout(new BorderLayout());
jif1.getContentPane().add(new Button("AWT Button"), BorderLayout.WEST);
jif1.getContentPane().add(new JButton("Swing Button"),
BorderLayout.EAST);
jif1.setSize(200, 100);
jif2.setSize(200, 100);
jdp.add(jif1);
jdp.add(jif2);
frame.setSize(240, 140);
}
public void show() {
frame.setVisible(true);
jif1.setVisible(true);
jif2.setVisible(true);
}
}
Run this program and drag the sub-window named "cover" with the mouse, we will find a very interesting phenomenon, as shown in the figure:
Note: I don't know which version of JDK started, this UI rendering problem no longer exists!
Obviously the cover sub-window is above the controls sub-window, but it only covers the Swing Button, not the AWT Button. Look at it for a while, do you have such a feeling: Swing Button is "painted" on it, while AWT Button is "posted" on it. This is an example of layer confusion caused by the mixed use of the two.
Swing components are beautiful, easy to use, and large in number of components. They also have shortcomings-programs that use Swing components usually run slower than programs that use AWT components. But everyone still prefers to use Swing components, why? Because with the upgrading of computer hardware, a little bit of speed is no longer a problem. On the contrary, users need more beautiful user interfaces, and developers need easy-to-use development components.
Two, the framework, listeners and events
The framework ( Frame
, JFrame
) is the basis of the Java graphical user interface. It is what we usually call a window and is a typical feature of Windows/XWindow applications. When it comes to Windows/XWindow, it is easy to think of "Event Driver". The graphical user interface of Java is event-driven, and various listeners are responsible for capturing various events.
If we need to capture and process a certain event of a certain component, we need to add a listener for it. For example, if we want to JFrame
) when it is activated, we need to JFrame
object) that can listen to the event of "activating window"—— WindowListener
.
How to add a listener? This is usually done by a addXxxxxListener
method provided by the component class. For example, JFrame
provides the addWindowListener
method to add a window listener ( WindowListener
).
A listener often not only listens to one event, but can listen to multiple related events. For example, WindowListener
can monitor the window close event ( windowClosing
) in addition to the window activation event ( windowActivate
So how can these events be distinguished? It depends on overloading multiple methods of the listener class (Method). After the listener listens to an event, it will automatically call the relevant method. Therefore, as long as we overload this method, we can handle the corresponding event.
Let’s look at an example first:
/**
* @(#) TestFrame.java
* @author [James Fan](https://segmentfault.com/blog/jamesfancy)
*/
package jamesfan.uiDemo;
import javax.swing.*;
import java.awt.event.*;
public class TestFrame extends JFrame {
private int counter = 0;
public TestFrame() {
// 使用匿名类添加一个窗口监听器
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println(
"Exit when Closed event");
// 退出应用程序
System.exit(0);
}
public void windowActivated(WindowEvent e) {
// 改变窗口标题
setTitle("Test Frame " + counter++);
}
});
// 设置窗口为固定大小
setResizable(false);
setSize(200, 150);
}
public static void main(String[] args) {
TestFrame tf = new TestFrame();
tf.setVisible(true);
}
}
In this example, we designed a window class ( public class TestFrame extends JFrame { ... }
), and added a window listener ( addWindowListener(new WindowAdapter() ...
) for this window. The window listener we added mainly monitors two events: window closing ( public void windowClosing(WindowEvent e) ...
) and window activation ( public void windowActivated(WindowEvent e) ...
). In the window close event we exited the entire application ( System.exit(0);
), and in the window activation event, we changed the window title ( setTitle("Test Frame " + counter++);
). Finally, we main
method, and run it to get the result shown in the following figure:
The result of running this program is a frame with nothing added, that is, an empty window. So, do you know the most important lines of code to display a window? I don’t know. It’s okay. Let me tell you that you only need to do three things to display a window: generate instance (object)→set size→display, correspondingly, the following three lines of code:
JFrame frame = new JFrame("Frame's Title");
frame.setSize(400, 300);
frame.setVisible(true);
Maybe you will say: I know the meaning of the first sentence, and I also understand the meaning of the third sentence. Why is the second sentence necessary? In fact, thinking about it, you will understand. Can you draw a rectangle that has no size? Can't. Similarly, how to display a window with no size? So we need to use the setSize(int width, int height)
method to set the size for it. We also have another way: with JFrame
of pack()
let it fit a size method. pack()
is satisfactory most of the time, but sometimes, it will make you dumbfounded-try it more.
In JFrame
, we use the addWindowListener
method to add a listener WindowListener
( addWindowListener(new WindowAdapter() ...
) to monitor window events JFrame
WindowListener
is an interface, in java.awt.event
this package, but the case did not seem to use WindowListener
, but the use of WindowsAdapter
it, how is this going?
WindowAdapter
is the simplest implementation of the WindowsListener
interface, and it is also in the java.awt.event
package. If we directly use WindowListener
generate a class, we need to implement each of its methods (a total of 7). But WindowAdapter
as WindowListener
, has realized that each of its methods is empty (that is, only contains empty sentences, or methods without sentences). With WindowAdapter
you only need to overload the methods that may be used (there are only 2 in the above example), and you don't need to implement each method. The advantage is obvious-reduce the amount of coding.
In JFrame
window events occurring on the ( WindowEvent
) include:
event | Description |
---|---|
windowActivated(WindowEvent e) | Triggered when the window gets focus |
windowClosed(WindowEvent e) | Triggered after the window is closed |
windowClosing(WindowEvent e) | Triggered when the window is closed |
windowDeactivated(WindowEvent e) | Triggered when the window loses focus |
windowDeiconified(WindowEvent e) | |
windowIconified(WindowEvent e) | |
windowOpened(WindowEvent e) | Triggered after the window is opened |
The above example overloads two of these methods. If you switch back and forth between the window generated by running the above example and another application window (in the Windows operating system, you can use Alt+Tab to switch)... Give it a try, what do you find? Have you setTitle("Test Frame " + counter++)
that the number on the title of our sample window keeps increasing? This is the credit windowActivated
The other event processing function windowClosing
in System.exit(0)
ensures that the current Java application is exited when the window is closed. What will happen if we don't do this? After the experiment, you will find that although the window is closed, the program does not end, but at this time, there is no other way except forcibly ending Ctrl+C So, this is very important: you want to exit the application when you close the window, then you need to handle the windowClosing
event. ......Not all, there is actually another simpler way, let JFrame
handle this by yourself-you just need to call JFrame
of setDefaultCloseOperation
as follows:frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
。
Execute the above statement after the JFrame
object is generated, and you can exit the program windowsClosing
We can add AWT or Swing components to the JFrame
However, although it has the add
method, it cannot be used directly to add components, otherwise an exception will be thrown-try it if you don't believe it. There is only one explanation for the cause of this problem: JFrame
is not a container, it is just a frame. So, how should components be added?
JFrame
has a Content Pane, and all the components displayed in the window are added to this Content Pane. JFrame
provides two methods: getContentPane
and setContentPane
are used to obtain and set its Content Pane. Usually we don't need to JFrame
the Content Pane of 0609b51beb9bc8, just get the default Content Pane directly to add components and so on. Such as:
(new JFrame()).getContentPane().add(new Button("test button"))
Three, buttons, toggle buttons, check buttons and radio buttons
The button... is the button, you don't even know the button, right?
- Toggle button, there are two states of button, namely pressed state and up state, if it is called selected state or unselected state.
- The check button, also called the check box, uses a small box to indicate two states.
- The radio button, also called the radio button, is marked with a small circle to indicate that it is selected. Often appear in groups, and only one of a group of radio buttons can be selected.
Did you find anything? ——By the way, this part is talking about various buttons, and the last three buttons have two states. Let's take a look at what these buttons look like:
In the above figure, from top to bottom, there are buttons, toggle buttons, check buttons, and radio buttons in order. The window shown is the result of the following example:
/**
* @(#) TestButtons.java
* @author [James Fan](https://segmentfault.com/blog/jamesfancy)
*/
package jamesfan.uiDemo;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JToggleButton;
public final class TestButtons {
public static void main(String[] args) {
TestButtons tb = new TestButtons();
tb.show();
}
JFrame frame = new JFrame("Test Buttons");
JButton jButton = new JButton("JButton"); // 按钮
JToggleButton toggle = new JToggleButton("Toggle Button"); // 切换按钮
JCheckBox checkBox = new JCheckBox("Check Box"); // 复选按钮
JRadioButton radio1 = new JRadioButton("Radio Button 1"); // 单选按钮
JRadioButton radio2 = new JRadioButton("Radio Button 2");
JRadioButton radio3 = new JRadioButton("Radio Button 3");
JLabel label = new JLabel("Here is Status, look here."); // 不是按钮,是静态文本
public TestButtons() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new java.awt.FlowLayout());
// 为一般按钮添加动作监听器
jButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
label.setText("You clicked jButton");
}
});
// 为切换按钮添加动作监听器
toggle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JToggleButton toggle = (JToggleButton) ae.getSource();
if (toggle.isSelected()) {
label.setText("You selected Toggle Button");
} else {
label.setText("You deselected Toggle Button");
}
}
});
// 为复选按钮添加条目监听器
checkBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
JCheckBox cb = (JCheckBox) e.getSource();
label.setText("Selected Check Box is " + cb.isSelected());
}
});
// 用一个按钮组对象包容一组单选按钮
ButtonGroup group = new ButtonGroup();
// 生成一个新的动作监听器对象,备用
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JRadioButton radio = (JRadioButton) ae.getSource();
if (radio == radio1) {
label.setText("You selected Radio Button 1");
} else if (radio == radio2) {
label.setText("You selected Radio Button 2");
} else {
label.setText("You selected Radio Button 3");
}
}
};
// 为各单选按钮添加动作监听器
radio1.addActionListener(al);
radio2.addActionListener(al);
radio3.addActionListener(al);
// 将单选按钮添加到按钮组中
group.add(radio1);
group.add(radio2);
group.add(radio3);
frame.getContentPane().add(jButton);
frame.getContentPane().add(toggle);
frame.getContentPane().add(checkBox);
frame.getContentPane().add(radio1);
frame.getContentPane().add(radio2);
frame.getContentPane().add(radio3);
frame.getContentPane().add(label);
frame.setSize(200, 250);
}
public void show() {
frame.setVisible(true);
}
}
Except for the general buttons, the other three buttons have two states, namely selected (pressed) state and unselected (up) state. So how do we judge? The switch button ( JToggleButton
) provides a isSelected()
method to determine the current state. When the return value is true ( true
), it means it is in the selected state, and when the return value is false ( false
), it means it is in the unselected state. The check button ( JCheckBox
) and the radio button ( JRadioButton
) are JToggleButton
, so they also have the isSelected()
method. As in the above example, if (toggle.isSelected()) { ... }
and so on.
Radio buttons are determined by their own characteristics that they must appear in groups, and only one of a group can be selected. So we need to use a special class, ButtonGroup
to manage. ButtonGroup
the multiple radio buttons added to 0609b51beb9e44, if one is selected, other radio buttons in the same group will automatically change its state to unselected. In ButtonGroup
Add button, using its add
method, in the example above group.add(radio1)
.
Now that we have added multiple radio buttons to a ButtonGroup
, can we add a ButtonGroup
object JFrame
to achieve the purpose of adding all the radio buttons in it What? No way! ButtonGroup
is not a displayable component, it is only used for management. So, to JFrame
add a group JRadioButton
time, a need to add a JRadioButton
, rather than the general add a ButtonGroup
.
In the above example, JLabel
is also used. This is not a button, but a static text component, which is mainly used to display prompt text. To obtain a JLabel
objects currently displayed text, it may be used getText()
method; conversely, to change a JLabel
text object is displayed, to use it setText(String text)
method, in the above example label.setText("You selected Toggle Button")
.
In fact, these two methods can also be used for JButton
and other classes. For example, in the above example, we use new JButton("JButton")
construct a button jButton
. If we use jButton.getText()
we can get the string "JButton"
. And jButton.setText("A Button")
, you can change the text displayed on the button to "A Button"
. These two lines of code are not written in the example, you can try it yourself.
In the above example, the action listener ( ActionListener
) is used extensively. ActionListener
only listens to one event, which is triggered when an action is generated on its related component, so it is called an action event ( ActionEvent
). ActionListener
has only one method that needs to be implemented, which is actionPerformed(ActionEvent event)
. Buttons, toggle buttons, and radio buttons all trigger action events when they are clicked, causing the action listener to call the actionPerformed
method. So, if you want to do something after clicking the button, of course, we should override ActionListener
of actionPerformed
way to go. Various buttons provide addActionListener
methods to add action listeners.
2021-05-11 Supplement
Java 8 introduced Lambda syntax, adding ActionListener can use a more concise syntax, such as
jButton.addActionListener( e -> ((JRadioButton) e.getSource()) .setText("add action listener by Lambda since java 8") );
The check box should be special. Although it also has the addActionListener
method, which means that the action listener can be used, but after using it, you will find that the action listener does not play the expected role. why? It turned out that a click on the check button to trigger action is not an event, but an event entry ( ItemEvent
status changes () in itemStateChanged
), entry by the listener ( ItemListener
monitor), the corresponding need to override the method is ItemListener
of itemStateChanged
method .
The example we named al
of ActionListener
added to every radio buttons, how to determine which radio button triggered the event and al
listen to it? We can see from ActionEvent
of getSource()
get a triggering event radio button method. Since getSource()
returns a Object
reference, although this reference points to an instance of a radio button, we still need to convert the type of this reference to JRadioButton
, as in the above example: JRadioButton radio = (JRadioButton) ae.getSource()
, only in this way can we call JRadioButton
. Object
does not have a method.
At the same time, it should be noted that each radio button can add a separate ActionListener
instance, not the same one. In the same way, for some irrelevant ActionListener
, you can also add the same ActionListener
instance. The key lies in the programmer's overload actionPerformed
For example, the following code adds the same action listener instance JButton
object and a JRadioButton
/**
* @(#) TestActionForDifferenctButtons.java
* @author [James Fan](https://segmentfault.com/blog/jamesfancy)
*/
package jamesfan.uiDemo;
import javax.swing.*;
import java.awt.event.*;
public class TestActionForDifferenctButtons {
JButton b;
JRadioButton rb;
public TestActionForDifferenctButtons() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new java.awt.FlowLayout());
b = new JButton("JButton");
rb = new JRadioButton("RadioButton");
ActionListener a = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == b) {
System.out.println("You clicked the JButton");
} else {
System.out.println("You clicked the RadioButton");
}
}
};
b.addActionListener(a);
rb.addActionListener(a);
f.getContentPane().add(b);
f.getContentPane().add(rb);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new TestActionForDifferenctButtons();
}
}
After running the program, click the two buttons respectively. Correspondingly, you can get the following output in the console:
You clicked the JButton
You clicked the RadioButton
This shows that it is possible to add the same listener to multiple different components-but only if these components can add the listener.
Four, text input box, password input box
There are two types of text input boxes, a single-line text input box ( JTextField
) and a multi-line text input box ( JTextArea
). There is only one type of password input box ( JPasswordField
). JPasswordField
is JTextField
. The main difference is that JPasswordField
will not display what the user inputs, but only a fixed character set by the programmer, such as'*' or'#'.
The following example pictures and codes are JTextField
, JPasswordField
and JTextArea
:
/**
* @(#) TestTexts.java
* @author [James Fan](https://segmentfault.com/blog/jamesfancy)
*/
package jamesfan.uiDemo;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public final class TestTexts extends JFrame {
public static void main(String[] args) {
TestTexts tt = new TestTexts();
tt.setVisible(true);
}
private JLabel label = new JLabel("Status");
private JTextField textField;
private JPasswordField pwdField;
private JTextArea textArea;
public TestTexts() {
super("Test Texts");
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().setLayout(new java.awt.FlowLayout());
textField = new JTextField(15);
// 监听文本光标移动事件
textField.addCaretListener(new CaretListener() {
public void caretUpdate(CaretEvent e) {
// 如果改变了内容,就可以即时更新 label 显示的内容
label.setText(textField.getText());
}
});
pwdField = new JPasswordField(15);
pwdField.setEchoChar('#');
textArea = new JTextArea(5, 15);
textArea.setLineWrap(true);
getContentPane().add(textField);
getContentPane().add(pwdField);
getContentPane().add(textArea);
getContentPane().add(label);
setSize(200, 200);
}
}
In the above example, we constructed a single-line text box ( textField = new JTextField(15)
15
characters, and added a CaretListener
( textField.addCaretListener ...
) addCaretListener
CaretListener
monitors the movement event of the text cursor. This event is triggered JTextField
using the keyboard, mouse, etc. We need to overload caretUpdate(CaretEvent e)
to handle the event ( public void caretUpdate(CaretEvent e) ...
). In this way, we can do something similar to what we did in the OnChange event of the TextBox in VB.
JTextField
has 5 construction methods, 4 of which are commonly used:
JTextField()
JTextField(int columns)
, as in the above exampletextField = new JTextField(15)
JTextField(String text)
JTextField(String text, int columns)
In these construction methods, the parameter text
is the initial content of columns
specifies the width of the single-line text box in characters. JTextField
text content can be used getText
get method. You can also use the setText
method to specify the text content in JTextField
JPasswordField
is JTextField
, and its construction method is similar. JPasswordField
provides the setEchoChar(char ch)
method to set the characters displayed in order to hide the password. The default is '*'
characters. In the above example, it is set to '#'
characters ( pwdField.setEchoChar('#')
). Like JTextField
, JPasswordField
also uses getText
and setText
obtain or set text content (of course, it is hidden on the user interface).
JTextField
is a single-line text box and cannot display multiple lines of text. If you want to display multiple lines of text, you have to use the multi-line text box JTextArea
. JTextArea
has 6 construction methods, and 4 of them are commonly used:
JTextArea()
JTextArea(int rows, int columns)
JTextArea(String text)
JTextArea(String text, int rows, int columns)
text
is JTextArea
initialization text content; rows
to JTextArea
height in units; columns
to JTextArea
width, in characters. As in the above example, a multi-line text box ( textArea = new JTextArea(5, 15)
) with a height of 5 lines and a width of 15 characters is constructed.
The default text area is not automatically fold line (but may enter a carriage return linefeed), we can use JTextArea
the setLineWrap
method of setting whether to allow automatic folding line. setLineWrap(true)
allows automatic line wrapping, and setLineWrap(false)
does not allow automatic line wrapping. The multi-line text box will automatically expand in size according to the content entered by the user. If you don’t believe it, do your own experiment-if it does not automatically wrap, the width of the multi-line text box is determined by the longest line of text; if the line data exceeds the preset Set the number of lines, the multi-line text box will expand its height to adapt. In other words, multi-line text boxes will not automatically generate scroll bars. How to do? You will know when we talk about the scroll pane ( JScrollPane
Obtaining and setting the text content in the multi-line text box can also be done using two methods, getText
and setText
Five, pane, scroll pane and layout management
The pane ( JPanel
) and the scroll pane ( JScrollPane
) are widely used in the layout and arrangement of various components on the window in the graphical user interface design. The so-called layout and arrangement here are Layout, so I have to talk about layout first.
The components added to the container (usually windows, etc.) are placed in a certain order and rules to make them look more beautiful. This is the layout. The layout is managed by the Layout Manager. So, when should we use the layout manager? Which layout manager does the application choose? How to use the layout manager?
Often, we design a window in which several components are to be added. In order to manage these managed layouts, we have to use the layout manager. For example, to design a simple editor, only two buttons and a multi-line text box need to be placed in the editor. Do these components let Java arrange arbitrarily? Or is it a more standardized arrangement in accordance with a certain positional relationship? Of course you should choose the latter. Then, in order to arrange these components according to a certain positional relationship, we need to use the layout manager.
Then we encountered a multiple choice question-which layout manager to use. To this end, we must first know what layout managers are and what are their layout features. Commonly used layout managers are: FlowLayout
, BorderLayout
, GridLayout
, BoxLayout
etc. Among them, FlowLayout
and BorderLayout
most commonly used. This article mainly only talks about these two layout managers. The following list explains their layout characteristics:
Layout manager layout features
Layout class | brief introduction |
---|---|
FlowLayout | Arrange the components in order from left to right and top to bottom, fold to the next row to continue placing if one row cannot be completed |
BorderLayout | Place the components in five areas: east (right), south (down), west (left), north (up), and middle. Only one component (or container) can be placed in each direction. |
GridLayout | It looks like an unframed table with a component in each cell |
BoxLayout | Just like a row or column of boxes neatly placed, one component in each box |
Take the above editor as an example, if you choose FlowLayout
, then two buttons and a multi-line text box will be arranged in one line-of course this is the case when the window is wide enough; if the window is slightly narrower, it may be arranged in two lines , The first row has two buttons, and the second row is a multi-line text box-this is the ideal situation; if the window is narrower, it may be arranged in three rows, one for the first row and one for the second row Button, place a multi-line text box on the third line. Therefore, if the window size can be changed, the positional relationship of the three components may also change with the change of the window size. In fact, most of the routines mentioned above use FlowLayout
, because we did not require the layout of the components.
What if BorderLayout
is used? We can try to add a pane ( JPanel
, explained later), and place two buttons in it, and then add this pane to BorderLayout
(that is, the upper part); then add a multi-line text box to the middle of BorderLayout
. The result is similar to FlowLayout
, which is the most ideal situation. Moreover, if the size of the window is changed, their positional relationship is still the North-Central relationship and will not change accordingly.
The remaining two layout managers, JPanel
with the panes (0609b51beba8e3 ), can also arrange the three components required by the above-mentioned editor. But since their use is a little more complicated, I won't talk about it. Now let's talk about how to use FlowLayout
and BorderLayout
.
Any layout manager, you need to use on a container, such as JFrame
Content Pane and the following to say JPanel
are container ( JFrame
default Content Pane is actually a JPanel
). The container component provides a setLayout
method, which is used to change its layout manager. By default, JFrame
the Content Pane using BorderLayout
, and a newly generated JPanel
objects using FlowLayout
. But no matter what, we can call their setLayout
method to change the layout manager. For example, in the above editor, if we want the window ( JFrame
object, assuming frame
) to use BorderLayout
, we can use frame.getContentPane().setLayout(new BorderLayout())
to change its layout manager to a new BorderLayout
object.
Then, our direct operation of the layout manager is over, and the rest only needs to add components to the container. If you use FlowLayout
, we only need to add(Component c)
method of the container. However, it BorderLayout
, because you have to specify which area to add the component to. Then we use the add(Component c, Object o)
method of the container to add components. The second parameter of this method is to specify the area to be added to. For example, if you want to add a multi-line text box to BorderLayout
in the above editor, you can use frame.getContentPane().add(new JTextArea(5, 15), BorderLayout.CENTER)
to achieve.
BorderLayout
are described by the following five constants:
Constant name | meaning |
---|---|
BorderLayout.EAST | East (right) |
BorderLayout.SOUTH | South (down) |
BorderLayout.WEST | West (left) |
BorderLayout.NORTH | North (up) |
BorderLayout.CENTER | in |
JPanel
has already been mentioned. JPanel
as a container can contain some components, and then add this JPanel
object as a component to another container (called the parent container). What are the benefits of this feature?
BorderLayout
n’t it mention that only one component can be added to an area of 0609b51bebaafa? But our editor needs to add two buttons to its north, what should we do? In the following example, we will use a JPanel
contain these two buttons, and then add this JPanel
object as a component to the Content Pane that BorderLayout
When talking about the layout features of each layout manager above, almost every type is that only one component can be added to an area, so when we want to add multiple components to an area, we need to use JPanel
. If you haven't understood it yet, it may be easier to understand a section of the program later.
And the scroll pane ( JScrollPane
)? It is a container that can generate scroll bars by itself, usually contains only one component, and automatically generates scroll bars according to the size of this component. For example, when talking about JTextArea above, it was mentioned: JTextAera will automatically expand in size with the content entered by the user, which can easily break the layout of each component. However, if we include it in a scroll pane, its expansion will not be directly reflected in the size change, but will be reflected in the scroll bar of the scroll pane, and it will not break the layout of the components. . Later examples will make you clear.
Are you waiting to see examples? Okay, here comes the example:
/**
* @(#) TestPanels.java
* @author [James Fan](https://segmentfault.com/blog/jamesfancy)
*/
package jamesfan.uiDemo;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public final class TestPanels extends JFrame {
public static void main(String[] args) {
TestPanels tp = new TestPanels();
tp.setVisible(true);
}
public TestPanels() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel panel = new JPanel();
for (int i = 0; i < 2; i++) {
panel.add(new JButton("Button 00" + i));
}
JTextArea textArea = new JTextArea(5, 15);
textArea.setLineWrap(true);
JScrollPane scrollPane = new JScrollPane(textArea);
getContentPane().add(panel, BorderLayout.NORTH);
getContentPane().add(scrollPane, BorderLayout.CENTER);
pack();
}
}
The running result of this example is shown in the figure below, which is exactly what we want-the two buttons above, and the bottom is a scrollable multi-line text box:
In the above example, a JPanel
object ( JPanel panel = new JPanel()
) is first generated, and then two buttons are placed in it ( panel.add ...
); then a multi-line text box ( JTextArea textArea = new JTextArea(5, 15)
) is generated, and a scroll pane is used to wrap it ( JScrollPane scrollPane = new JScrollPane(textArea)
) To make it a scrollable multi-line text box. Finally, two containers ( JPanel
object and JScrollPane
object) were added to the north ( getContentPane().add(panel, BorderLayout.NORTH)
) and middle (that is, the remaining part, getContentPane().add(scrollPane, BorderLayout.CENTER)
) of the window, respectively.
It seems something is wrong, what is it? By the way, we did not set the Content Pane layout manager is BorderLayout
ah, why ...... just do not say, JFrame
the Content Pane's default layout manager is BorderLayout
, so no need to set up.
Well, "A Brief Introduction to Java Graphical User Interface Design" is over. Due to the limited space, I'm talking about elementary knowledge here. With this foundation, it is not difficult to design a more complex graphical user interface!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。