Swing组件的使用【总结】

1. Swing的特点?

答:Swing 是第二代GUI开发工具集,javax.swing包被列入Java的基础类库(JFC),Swing建立在AWT,Java2D,Accessibility等的基础上。与AWT相比,Swing具有更好的可移植性,提供了更完整的组件,增加了许多功能。

2. 几种Swing组件的介绍?

答:

1)JApplet

    javax.Swing.JApplet是java.applet.Applet的子类,与JApplet小程序配合使用的HTML文件和Applet配合使用的HTML没有差别。JApplet的默认布局是BorderLayout,而Applet的是FlowLayout。向JApplet加入swing组件不能直接用add()方法,而必须先使用JApplet的方法getContentPane()获得一个Container对象,在调用这个对象的add()方法将JComponent及其子类对象加入到JApplet中。

2)JButton

    JButton较Button增加了许多功能。例如,在Swing按钮上显示图标,在不同状态使用不同的按钮,为Swing按钮加入提示信息等。

3)JPasswordField

    其实JTextField类。用户在JPasswordField对象中输入的字符会被其他字符替代而遮住。

4)JTabbedPane

    对于局CardLayout这种布局策略的一个不便之处是,用户不能了解被第一张卡片遮住的后面卡片的内容,JTabbedPane容器可以解决这个问题。

    下例中使用JButton,ToolTipText,Border,Icon等,注意在容器JFrame及JApplet中加入组件要使用getContentPane().add()方法。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class JButtonDemo extends JApplet{
	JButton b1 = new JButton("JButton 1");
	JButton b2 = new JButton("JButton 2");
	JTextField t = new JTextField(20);
	
	public void init() {
		ActionListener a1 = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String name =
						((JButton)e.getSource()).getText();
				t.setText(name+"Pressed");
			}
		};
		b1.setToolTipText("Press Button will show msg");
		b1.setBorder(new BevelBorder(BevelBorder.RAISED));
		b1.setIcon(new ImageIcon("图像路径"));//设置图标
		
		b1.addActionListener(a1);
		b2.addActionListener(a1);
		
		getContentPane().setLayout(new FlowLayout());
		getContentPane().add(b1);
		getContentPane().add(b2);
		getContentPane().add(t);
	}
	
	public static void main(String[] args) {
		JApplet applet = new JButtonDemo();
		JFrame frame = new JFrame("Test Swing");
		frame.getContentPane().add(applet, BorderLayout.CENTER);
		frame.setSize(400, 300);
		
		applet.init();
		applet.start();
		frame.setVisible(true);
	}
}

Swing组件的使用【总结】_第1张图片


3. Swing组件与线程?

答:在Java中,Swing是线程不安全的,是单线程的设计。这样造成的结果:只能从事件派发线程(或称界面线程)访问将要在屏幕上绘制的Swing组件。事件派发线程是调用paint()和update()等回调方法的线程,它还是事件监听器接口中定义的事件处理方法。

    Swing是事件驱动的,所以在回调函数中更新可见的GUI是很自然的事情。有时需要从事件派发线程以外的线程中更新Swing组件,例如,在actionPerformance()中有很费时的操作,则在独立的线程上执行比较耗时的操作会更好,这就会立即更新用户界面和释放时间派发线程去派发其他的事件。

    在新的线程中更新Swing界面时,不能直接调用界面组件的getText()、setText()方法,这会与主界面状态不一致。解决的方法是:调用SwingUtilities类的static方法,invokeLater或invoteAndWait,它们都使事件派发线程上的可运行对象(Runnable)排队。当运行对象排在时间派发队列的队首时,就调用其run()方法,其效果是允许事件派发线程调用另一个线程中的任意一个代码块。

    总之,只能从事件派发线程更新组件,其他线程要操作界面就得将其代码放入Runnable对象的run()方法中,并用SwingUtilities.invokeLater去调用。如果一个操作在另一个操作执行之前必须从一个组件获得信息,则可以用invokeAndWait。下例使用invokeLater来更新界面,数值10减小到0:

import java.awt.*;
import javax.swing.*;

class MyFrame extends JFrame{
	JButton button = new JButton("start");
	JLabel label = new JLabel("The value will decrease!");
	public MyFrame() {
		this.setTitle("测试 InvokeLater");
		this.setSize(300, 200);
		label.setFont(new Font("", 0, 24));
		label.setHorizontalAlignment(SwingConstants.CENTER);
		getContentPane().setLayout(new BorderLayout());
		getContentPane().add(button, BorderLayout.NORTH);
		getContentPane().add(label, BorderLayout.CENTER);
		
		button.addActionListener(e->{
			new Thread(()->{
				for(int i = 10; i >= 0; i--) {
					final int j = i;
					SwingUtilities.invokeLater(()->{
						label.setText(""+j);
					});
					try {Thread.sleep(300);}catch (Exception ex) {}
				}
			}).start();
		});
	}
}

public class InvokeLaterDemo {
	public static void main(String[] args) {
		new MyFrame().setVisible(true);
	}
}
Swing组件的使用【总结】_第2张图片

你可能感兴趣的:(JAVA)