Swing

Swing

Swing is a graphical user interface (GUI) toolkit designed for Java. Swing is part of the Java API. Swing includes GUI components such as text boxes, buttons, split panes and tables.
Swing is used to provide a set of "lightweight" (all in the Java language) components that are written in pure Java, so they can also be used across platforms.
The disadvantage of lightweight components is that they are slower to execute, and the advantage is that they can use uniform behavior on all platforms.

1. Get started in 30 minutes

1.1 The relationship and difference between Swing and AWT
  • Relational
    Swing is a development kit for developing JAVA application user interfaces. Enables cross-platform applications to use any pluggable look and feel based on the Abstract Window Package (AWT).
    Much of the Swing API is a complementary extension to AWT rather than a direct replacement. The core rendering functionality that Swing uses to draw lightweight components is provided by Java 2D, which is part of AWT. However, the use of lightweight and heavyweight components in the same application can lead to Z-order incompatibility.
  • Swing
    is a form-based GUI application development and design, and provides excellent support for Java cross-platform features. It has no native code at all and is not affected by the operating system. It has achieved true cross-platform applications and can even provide a local window system. Other features not supported. Therefore, it is more practical than AWT, and has a more refined appearance than AWT programs.

AWT only provides basic components, which complicates many designs and cannot maintain the consistency of display styles under different platforms.
For example: if you create a button (Button) object, there will be a button object will request the underlying operating system to create a real button. That is, if it is executed on WindowsNT, the WindowsNT button is created; if it is executed on Linux, the Linux button is created. Therefore, the appearance of AWT components will be affected by the underlying operating system.

1.2 Swing operation steps
1.2.1 Import the Swing package
import javax.swing.*;

Most Swing programs use AWT's underlying infrastructure and event model, so two packages need to be imported:

import java.awt.*;
import java.awt.event.*;

If event handling is included in the graphical interface, you also need to import the event handling package:

import.javax.swing.event.*;
1.2.2 Select interface style

Swing allows you to choose the graphical interface style of the program. Commonly used are Java style, Windows style and so on.
The following code is used to select the graphical interface style, here is the cross-platform Java interface style.

try{
  UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
}catch(Exception e){

}
1.2.3 Setting the top-level container

A graphical interface must have at least one top-level Swing container (see: 2.1 Containers for details). The top-level Swing container provides support for other Swing components to draw and handle events on the screen.
For example: a frame (JFrame) includes borders, menu bars, toolbars, and status bars. and the main pane in the middle.
A pane can also be seen as a type of panel, but it is an integral part of the frame.
Components are not placed directly on the frame, but on panels (JPanels), which are then placed on panes.
Use the frame object's getContentPane() function to get the pane, and call the pane's add() function to place the pane.

// 声明一个名为SwingApplication的框架
JFrame frame = new JFrame("SwingApplication");
// 声明一个空的面板
JPanel panel = new JPanel();
// 将面板添加到指定的框架中,定义添加面板的布局方式
frame.getContentPane().add(panel, BorderLayout.Center);
...
// 调整此窗口的大小,以适合其子组件的首选大小和布局。
frame.pack();
// 设置声明框架可见,否则框架不显示
frame.setVisible(true);
1.2.3 Add components

The addition of components (see: 2.2 Common Components) requires the support of containers. The way of adding is similar to that of adding panels. Panels also have an add() function for adding components or sub-panels.

// 声明一个按钮组件
JButton button = new JButton("button");
// 将按钮组件添加到之前声明的面板上,定义添加组件在面板上的布局方式
panel.add(button, BorderLayout.Center);
1.2.4 Add events to components

The component realizes the interaction between the user and the system by adding events, and performs corresponding processing by listening to keyboard typing events and mouse operation events.

// 添加指定的操作监听器,以接收发自此组件的操作事件。
button.addActionListener(...);
// 添加指定的鼠标侦听器,以接收发自此组件的鼠标事件。
button.addMouseListener(...);
// 添加指定的鼠标移动侦听器,以接收发自此组件的鼠标移动事件。
button.addMouseMotionListener(...);
// 添加指定的鼠标滚轮侦听器,以接收发自此组件的鼠标滚轮事件。容器还接收发自子组件的鼠标滚轮事件。
button.addMouseWheelListener(...);
// 添加指定的按键侦听器,以接收发自此组件的按键事件。
button.addKeyListener(...);
1.3 Swing's thread strategy

Usually Swing is not thread safe. Unless otherwise specified, all Swing components and related classes must be accessed on the event dispatch thread.
A typical Swing application performs processing in response to events generated by user actions. For example, clicking a JButton notifies all ActionListeners added to the JButton. Since all events generated by user actions are dispatched on the dispatch thread, most developers are not affected by this restriction.

However, the impact exists in constructing and displaying Swing applications. Calls to the application's main method or methods in the applet are not called on the event dispatch thread. Therefore, when constructing and displaying an application or applet, care must be taken to transfer control to the event dispatch thread.
The preferred way to transfer control and start working with Swing is to use invokeLater. The invokeLater method schedules the Runnable to be processed on the event dispatch thread.
Both of the following examples work equally well for transferring control and launching a Swing application:

public class MyApp implements Runnable {
    public void run() {
        // Invoked on the event dispatching thread.
        // Construct and show GUI.
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MyApp(args));
    }
}
public class MyApp {
    MyApp(String[] args) {
        // Invoked on the event dispatching thread. Do any initialization
        // here.
    }

    public void show() {
        // Show the UI.
    }

    public static void main(final String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MyApp(args).show();
            }
        });
    }
}

2. Description of technical points

2.1 Container

Some components in Swing inherit the JComponent class, and the JComponent class inherits from the Container class, so any component that inherits this class can be used as a container.

Containers can be functionally divided into:
1) Top-level container:

JFrame - framework, mainly used to design the graphical interface of the application.
JApplet - small application, mainly used to design JAVA programs running in embedded web pages.
JDialog - Dialog, usually used to design windows with dependencies.
JWindow - window.

2) Ordinary container:

JPanel - A panel, usually a normal container with just a background color.
JScrollPane - scroll pane, with scroll bars.
JToolBar - Toolbar, which usually arranges multiple components in a row or column.
JSplitPane - Split pane, container for two components.
JTabbedPane - A tabbed pane that allows multiple components to share the same interface space.

3) Special container:

JInternalFrame - an internal pane that can display several frame-like windows within a single window.
JLayeredPanel - Layered panes, adding the concept of depth to panes.
JRootPane - The root pane, usually an automatically created container.

2.2 Common Components
Controls can be functionally divided into:
1) Basic controls, components that realize human-computer interaction:

JButton - button control
JComboBox - drop-down selection box
JList - list control
JMenu - menu control
JSlider - scroll bar control
JTextField - text control, is a lightweight component that allows editing a single line of text.

2) Display controls for non-editable information, controls that display non-editable information to the user:

JLabel - A label for the display area of ​​a short text string or an image or both.
JProgressBar - A component that displays the progress of certain tasks in a visual form.
JToolTip - Used to display a "tip" for a Component.

3) A display control for editable information, a control that displays editable formatted information to the user:

JColorChooser - Color picker, provides a controller pane that allows the user to manipulate and select colors.
JFileChooser - A file selector that provides a simple mechanism for users to select files.
JTable - Used to display and edit regular two-dimensional cell tables. There are many tools for customizing its rendering and editing, and default settings for these functions are provided, making it easy to set up a simple table.
JTextArea - Displays a multi-line area of ​​plain text.
JTree - A control that displays hierarchical datasets as outlines. For task-oriented documentation and examples of using trees.

2.3 Layout

2.3.1 Introduction to Swing Layout Manager

Provides layout logic (a different layout manager and UI content)

public staic void addComponentsToPane(Container pane){...}

Instantiate a container to load layout logic content through its ContentPane

private static void createAndShowGUI(){
  JFrame frame = new JFrame("...");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  addComponentsToPane(frame.getContentPane());

  frame.pack();
  frame.setVisible(true);
}

The main() program entry, a separate thread is started, and the UI is instantiated.

public static void main(String[] args){
  javax.swing.SwingUtilities,invokeLater(new Runnable(){
    public void run(){
      createAndShowGUI();
    }
  });
}
2.3.2 Common layout managers

Commonly used layout managers are: FlowLayout, BorderLayout, BoxLayout, CardLayout, GridLayout and GridBagLayout.

1) FlowLayout

The FlowLayout class is the simplest layout manager. Follow: from left to right until there is no more space, then, go to the next line.

public static void addComponentsToPane(Container pane){
  pane.setLayout(new FlowLayout());
  pane.add(new JButton("button1"));
  pane.add(new JButton("button2"));
  ...
}
2) BorderLayout

BorderLayout divides the interface into five areas: PAGE_START, PAGE_END, LINE_START, LINE_END, CENTER.

public static void addComponentsToPane(Container pane) {
  JButton button = new JButton("button1");
  pane.add(button, BorderLayout.PAGE_START);

  button = new JButton("button2");
  button.setPreferredSize(new Dimension(200, 100));
  pane.add(button, BorderLayout.CENTER)
}
3) BoxLayout

BoxLayout can add components to the current panel from top to bottom or from left to right.

public static void addComponentsToPane(Container pane) {
  JPanel xPanel = new JPanel();
  xPanel.setLayout(new BoxLayout(xPanel, BoxLayout.X_AXIS));
  xPanel.add(new JButton("button1"));
  xPanel.add(new JButton("button2"));

  pane.add(xPanel, BorderLayout.PAGE_START);
}
4) CardLayout

Unlike other layouts, the card layout hides some components. A card layout is a group of containers or components that display only one at a time, each container in the group is called a card.

public static void addComponentsToPane(Container pane){
  final JPanel contentPanel = new JPanel();
  JPanel controlPanel = new JPanel();
  final CardLayout CardLayout  cardLayout=new CardLayout();
  pane.add(contentPanel, BorderLayout.CENTER);
  pane.add(controlPanel, BorderLayout.PAGE_END);
  controlPanel.setLayout(new FlowLayout());

  JButton[] b = new JButton[10];
  for (int i = 0; i < 10; i++) {
    b[i] = new JButton("No" + i);
    contentPanel.add(b[i]);
  }

  contentPanel.setLayout(cardLayout);
  JButton nextButton = new JButton("next");
  nextButton.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e){
      cardLayout.next(contentPanel);
    }
  });
}
5) GridLayout

GridLayout creates a component table, and when components are added, each grid will be filled from left to right and top to bottom at a time, and it is not possible to specify a grid to be filled.

public static void addComponentsToPane(Container pane){
  JButton[] b = new JButton[10];
  pane.setLayout(new GridLayout(3, 3));
  for (int i = 0; i < b.length; i++) {
    b[i] = new JButton("No" + i);
    pane.add(b[i]);
  }
}
6) GridBagLayout

GridBagLayout is the most complex of all AWT layouts, but also the most powerful. GridBagLayout, like GridLayout, manages components in a grid in a container. But GridBagLayout is much more powerful.
1. All rows and columns managed by GridBagLayout can be of different sizes.
2. GridLayout restricts each component to one cell. The components in GridBagLayout can occupy a rectangular area of ​​any size.

public static void addComponentsToPane(Container pane){
  JButton button;
  pane.setLayout(new GridBagLayout());
  GridBagConstraints c = new GridBagConstraints();

  button = new JButton("button1");
  c.fill = GridBagConstraints.HORIZONTAL;
  c.gridx = 0;
  c.gridy = 0;
  pane.add(button, c);

  button = new JButton("button2");
  c.fill = GridBagConstraints.HORIZONTAL;
  c.weightx = 0.5;
  c.gridx = 1;
  c.gridy = 0;
  pane.add(button, c);

  ...
}

2.4 Event monitoring

Java Swing components automatically generate various events in response to user actions. Java encapsulates events into event classes, and defines an event listener for each event class.
A component registers event listener methods to indicate that the component should respond to specified events. That is to say, we can register the listener and listen to the events generated by the event source, so as to handle the user behavior we need to handle in the event handler.

2.4.1 Three ways to register events
1) Use one to monitor multiple if statements to achieve

Inherit the ActionListener interface and implement the actionPerformed method. Get the
event .
Disadvantage: When the program is more complex, a large series of if statements are required to implement. Program code is difficult to read and maintain.

public class Test_01 extends JFrame implement ActionListener {
  Test_01(){
    JPanel panel = new JPanel();
    JButton button1 = new JButton("按钮一");
    JButton button2 = new JButton("按钮二");

    panel.add(button1);
    panel.add(button2);
    this.getContentPane().add(panel);
    this.setVisible(true);

    button1.addActionListener(this);
    button2.addActionListener(this);
  }

  public void actionPerformed(ActionEvent e){
    String source = e.getActionCommend();
    if(source.equals("按钮一")){
      System.out.println("你按了按钮一");
    }
    if(source.equals("按钮二")){
      System.out.println("你按了按钮二");
    }
  }

  public static void main(String args[]){
    new Test_01();
  }
}
2) Implemented using anonymous inner class

Disadvantage: Because the anonymous inner class and the event group are together. Depending on the location of the event group in the code, the definition of the class and the handling of events are not easy to read. If the event handler is complex, the code in the inner class can become very long.

public class Test_02 extends JFrame implement ActionListener {
  Test_02(){
    JPanel panel = new JPanel();
    JButton button1 = new JButton("按钮一");
    JButton button2 = new JButton("按钮二");

    panel.add(button1);
    panel.add(button2);
    this.getContentPane().add(panel);
    this.setVisible(true);

    button1.addActionListener(
      new ActionListener(){
        public void actionPerformed(ActionEvent e){
          System.out.println("你按了按钮一");
        }
    });

    button2.addActionListener(
      new ActionListener(){
        public void actionPerformed(ActionEvent e){
          System.out.println("你按了按钮二");
        }
    });
  }

  public static void main(String args[]){
    new Test_02();
  }
}
3) Use general inner class implementation

Advantages: Single event handling, can be reused by toolbars, menu bars, etc.

public class Test_03 extends JFrame implement ActionListener {
  Test_03(){
    JPanel panel = new JPanel();
    JButton button1 = new JButton("按钮一");
    JButton button2 = new JButton("按钮二");

    panel.add(button1);
    panel.add(button2);
    this.getContentPane().add(panel);
    this.setVisible(true);

    button1.addActionListener(new Button1ActionListener());
    button2.addActionListener(new Button2ActionListener());
  }

  private class Button1ActionListener implement ActionListener{
    public void actionPerformed(ActionEvent e){
      System.out.println("你按了按钮一");
    }
  }

  private class Button2ActionListener implement ActionListener{
    public void actionPerformed(ActionEvent e){
      System.out.println("你按了按钮二");
    }
  }

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

2.5 Focus System

2.5.1 Window events and focus events
1) FocusEvent
  • Application of FocusEvent:

Low-level event that indicates that a Component has gained or lost input focus. This low-level event is generated by a Component such as a TextField. Events are passed to each FocusListener or FocusAdapter object, which is registered using the Component's addFocusListener method to receive such events. (FocusAdapter objects implement the FocusListener interface.) When the event occurs, all such listener objects will get this FocusEvent.

  • Event type of FocusEvent:
event type Summary
FocusEvent.FOCUS_GAINED control gets focus
FocusEvent.FOCUS_LOST Control loses focus
2) WindowEvent
  • Application of WindowEvent:

Low-level events that indicate window state changes. This low-level event is generated by the Window object when the Window object is opened, closed, activated, deactivated, iconified, or de-iconified, or when the focus is transferred into or out of the Window. The event is passed to every WindowListener or WindowAdapter object registered to receive such events using the window's addWindowListener method. (WindowAdapter objects implement the WindowListener interface.) All such listener objects get this WindowEvent when an event occurs.

  • WindowEvent focus-related event types:
event type Summary
WindowEvent.WINDOW_ACTIVATED window activation
WindowEvent.WINDOW_GAINED_FOCUS window gets focus
WindowEvent.WINDOW_LOST_FOCUS window loses focus
WindowEvent.WINDOW_DEACTIVATED window inactive
3) Through FocusEvent.getOppositeComponent and WindowEvent.getOppositeWindow, the opposite controls in the focus jump process can be obtained.
2.5.2 Global Handling of Keyboard Events
  • KeyEventDispatcher: Pre-process keyboard messages before they are passed to the focus control, need to
    register with KeyboardFocusManager
  • KeyEventPostProcessor: To process the keyboard message after the keyboard message is passed to the focus control and processed by the focus space, it needs to be
    registered with the KeyboardFocusManager.
  • KeyboardFocusManager handles KeyEventDispatcher and KeyEventPostProcessor in the event chain mode,
    and uses itself as the last handler of the event chain.
2.5.3 Keyboard control focus jump
  • Component provides two methods for controlling the focus jump of the keyboard.

  • Whether setFocusTraversalKeysEnabled(boolean) supports keyboard control focus jump

parameter value Summary
true (default) Support keyboard control focus, ordinary KeyListener will not receive focus control keys.
speak The keyboard control focus is not supported, and the focus control key is the same as other keys.

* setFocusTraversalKeys(int, Set) uses the specified key to control the focus jump.
* The int parameter specifies the jump direction
* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS jumps to the previous focus control.
* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS jumps to the next focus control.
* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS Jump to the next focus loop body.
* KeyEventPostProcessor.UP_CYCLE_TRAVERSAL_KEYS Jump to the previous focus loop body.
* Set parameter is a collection of keyboard (AWTKeyStroke) events.
* Multiple keyboard events can correspond to one focus jump operation, but one event cannot correspond to multiple focus jump operations.
* You cannot use KEY_TYPED type keyboard events to correspond to the focus jump operation, you can use KEY_PRESSED or KEY_RELEASED.

  • The default case for Swing control:
    • Switch to the next component:
      text field: CTRL+TAB controls focus switching
      Other components: TAB and CTRL+TAB can control focus switching
    • Switch to the previous component:
      Text field: CTRL+SHIFT+TAB controls focus switching
      Other components: SHIFT+TAB/CTRL+SHIFT+TAB can control focus switching
2.5.4 Focus jump strategy
  • The focus jump policy (FocusTraversalPolicy) defines the order of focus jumps.

  • Swing implements two focus jump strategies

    • SortingFocusTraversalPolicy: Determine the focus jump through a Comparator
    • LayoutFocusTraversalPolicy: Inherited from SortingFocusTraversalPolicy, the
      focus jump is determined by the size, position and direction of the control.
  • Containers in Swing use LayoutFocusTraversalPolicy by default

2.5.5 Program control focus jump
  • Interfaces provided by KeyboardFocusManager:

    • KeyboardFocusManager.focusNextComponent(Component)
    • KeyboardFocusManager.focusPreviousComponent(Component)
    • KeyboardFocusManager.upFocusCycle(Component)
    • KeyboardFocusManager.downFocusCycle(Component)
  • Component provides an interface:

    • Component.transferFocus()
    • Component.transferFocusBackward()
    • Component.transferFocusUpCycly()
    • Component.transferFocusDownCycle()
  • Component itself gets focus:

    • Component.requestFocus(): Supports getting focus across windows, limited by the system platform
    • Component.requestFocusWindow: Does not support getting focus across windows, not limited by the system platform

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325794692&siteId=291194637