一、GUI是什么
GUI的全称为Graphical User Interface,图形化界面或图形用户接口,是指采用图形方式显示的计算机操作环境用户接口。与早期计算机使用的命令行界面相比,图形界面对于用户来说更为简便易用。GUI的广泛应用是当今计算机发展的重大成就之一,它极大地方便了非专业用户的使用人们从此不再需要死记硬背大量的命令,取而代之的是通过窗口、菜单、按键等方式来方便地进行操作。而嵌入式GUI具有下面几个方面的基本要求:轻型、占用资源少、高性能、高可靠性、便于移植、可配置等特点。
1、 不流行的主要原因
2、为什么我们要学习
- 可以写出自己心中想要的一些小工具
- 工作之时可能需要维护道swing界面
- 了解MVC架构,了解监听
二、AWT
1、AWT介绍
? AWT(Abstract Window Toolkit),中文译为抽象窗口工具包,该包提供了一套与本地图形界面进行交互的接口,是Java提供的用来建立和设置Java的图形用户界面的基本工具。其中包含了许多类和接口以及众多元素如窗口、按钮、文本框等,且包都在java.awt 包下,Container和Component是AWT中的两个核心类。
? 所有的可以显示出来的图形元素都称为Component,Component代表了所有的可见的图形元素, Component里面有一种比较特殊的图形元素叫Container,Container(容器)在图形界面里面是一种可以 容纳其它Component元素的一种容器,Container本身也是一种Component的,Container里面也可以 容纳别的Container。
? Container里面又分为Window和Panel,Window是可以独立显示出来的,平时我们看到的各种各样的 应用程序的窗口都可以称为Window,Window作为一个应用程序窗口独立显示出来,Panel也可以容 纳其它的图形元素,但一般看不见Panel,Panel不能作为应用程序的独立窗口显示出来,Panel要想 显示出来就必须得把自己装入到Window里面才能显示出来。
? Panel应用比较典型的就是Applet(JAVA的页面小应用程序),现在基本上已经不用了,AJAX和 JAVASCRIPT完全取代了它的应用。
? Window本身又可以分为Frame和Dialog,Frame就是我们平时看到的一般的窗口,而Dialog则是那 些需要用户进行了某些操作(如点击某个下拉菜单的项)才出现的对话框,这种对话框就是Dialog。
2、组件和容器(Component和Container)
Component & Container |
---|
1. Java图形用户界面最基本的组成部分是Component,Component类及其子类的对象用来描述以图形化的方式显示在屏幕上并能与用户进行交互的GUI元素,例如,一个按钮、一个标签等; 2. 一般的 Component 对象不能独立地显示出来,必须将“放在”某一Container对象中才可以显示出来 | 1. Container 是 Component 的子类,Container 子类对象可以“容纳”别的 Component 对象; 2. Container 对象可使用方法 add()向其中添加其他 Component 对象; 3. Container 是 Component 的子类,因此 Container 对象也可以被当做 Component 对象添加到其他 Container 对象中 4. 有两种常用的 Container: Window和Panel,前者表示自由停泊的顶级窗口,后者对象则可用作容纳其他的 Component 对象,但不能独立存在,必须被添加到其他 Container 中(如Window或Applet) |
2.1、 Frame
Frame 是 Window 的子类,由 Frame 或其子类创建的对象为一个窗体,其主要有以下常用方法:
Frame() :无参构造器Frame(String s) :有参构造器创建标题栏为字符串s的窗体setSize(int width, int height) :设置窗体的大小,参数分别为宽度和高度setLocation(int x, int y) :设置窗体的位置,参数为左上角坐标setBounds(int x, int y, int width, int height) :设置窗体的位置和大小,参数分别为左上角坐标、宽度和高度setBackground(Color c) :设置背景颜色,参数为Color对象setVisible(boolean b) :设置可见性, 默认为falsesetTitle(String name) / String getTile() :设置标题以及获得窗体的标题setResizable(boolean b) :设置是否可以调整大小,默认为true
public static void main(String[] args) {
Frame frame = new Frame();
frame.setTitle("First");
frame.setBackground(Color.PINK);
frame.setBounds(100, 100, 500, 500);
frame.setResizable(false);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
MyFrame frame1 = new MyFrame(300, 300, 500, 500, new Color(0xFFEBC8));
MyFrame frame2 = new MyFrame(300, 300, 500, 500, new Color(11, 43,102));
MyFrame frame3 = new MyFrame(300, 300, 500, 500, new Color(0xC8FFE7));
}
class MyFrame extends Frame {
static int id = 0;
public MyFrame(int x, int y, int w, int h, Color color) {
super("MyFrame" + id++);
setBounds(x, y, w, h);
setBackground(color);
setLayout(null);
setVisible(true);
}
}
2.2、Panel
Panel 对象可以看成可以容纳Component的空间,并且可以拥有自己的布局管理器,其常用方法有:
Panel() :使用默认FlowLayout类布局管理器初始化;Panel(LayoutManager layout) :使用指定的布局管理器进行初始化setBounds(int x, int y, int widtth, int height) setSize(int width, int height) setLocation(int x, inty) setBackgroud(Color c) setLayout(LayoutManager mgr) :设置布局管理器
public static void main(String[] args) {
Frame frame = new Frame("Java Frame with Panel");
Panel panel = new Panel(null);
frame.setBounds(300, 300, 500, 500);
frame.setBackground(new Color(227, 227, 252));
panel.setBounds(50, 50, 400, 400);
panel.setBackground(Color.PINK);
frame.add(panel);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
3、 布局管理器
Java语言中,提供了布局管理类的对象可以管理。当需要管理Component在Container中的布局时,不必直接设置Component位置和大小。每个Container都会有一个布局管理器对象,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其对应的布局管理器,调用Container的setLayout方法改变其布局管理器对象。在AWT中提供了5种布局管理器:
- FlowLayout
- BorderLayout
- GridLayour
- CardLayout
- GridBagLayout
3.1、流式布局(FlowLayout)
FlowLayout是Panel类的默认布局管理器,其对组件逐行定位,行内从左到右,一行排满后换行。流式布局不改变组件的大小,按组建原有的尺寸显示组件,可设置不同的组件间距、行距以及其对齐方式,默认的对齐方式为居中(CENTER),主要的构造方法如下:
- new FlowLayout(FlowLayout.RIGHT, 20, 40):右对齐,组件之间水平间距20px,垂直间距40个像素
- new FlowLayout(FlowLayout.LEFT):左对齐,水平和垂直间距为缺省值,默认为5
- new FlowLayout():使用缺省的居中对齐方式,水平和垂直间距为缺省值,默认为5
@Test
public void FlowLayout() {
Frame frame = new Frame("FlowLayout");
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button3");
frame.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 40));
frame.setSize(500, 500);
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.setVisible(true);
}
3.2、边框布局(BorderLayout)
BorderLayout是Frame类的默认布局管理器,它将整个容器的布局划分为东西南北中五个区域,组件只能被添加到指定的区域,如果不指定组件加入的部位,将会默认加入到CENTER区。值得注意的是每个区域只能加入一个组件,如加入多个,则先前加入的会被覆盖
BorderLayout型布局容器尺寸缩放原则如下:
- 南北两个区域在水平方向上缩放
- 东西两个区域在垂直方向上缩放
- 中部可在两个方向上缩放
@Test
public void BorderLayout() {
Frame frame = new Frame("BorderLayout");
Button buttonEast = new Button("EAST");
Button buttonWest = new Button("WEST");
Button buttonSouth = new Button("SOUTH");
Button buttonNorth = new Button("NORTH");
Button buttonCenter = new Button("CENTER");
frame.add(buttonEast, BorderLayout.EAST);
frame.add(buttonWest, BorderLayout.WEST);
frame.add(buttonSouth, BorderLayout.SOUTH);
frame.add(buttonNorth, BorderLayout.NORTH);
frame.add(buttonCenter, BorderLayout.CENTER);
frame.setSize(500, 500);
frame.setVisible(true);
}
3.3、表格布局(GridLayout)
GridLayout型布局管理器将空间划分成规则的矩形网格,每个单元格区域大小相等。组件被添加到每个单元格中,先从左到右填满一行后换行,再从上到下。
在GridLayout构造方法中指定分割的行数缓和列数
@Test
public void GridLayout() {
Frame frame = new Frame("GridLayout");
Button button1 = new Button("btn1");
Button button2 = new Button("btn2");
Button button3 = new Button("btn3");
Button button4 = new Button("btn4");
Button button5 = new Button("btn5");
Button button6 = new Button("btn6");
Button button7 = new Button("btn7");
frame.setLayout(new GridLayout(2, 4));
frame.setSize(500, 500);
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.add(button5);
frame.add(button6);
frame.add(button7);
frame.pack();
frame.setVisible(true);
}
3.4、布局练习
@Test
public void LayoutTest() {
Frame frame = new Frame("LayoutTest");
frame.setLayout(new GridLayout(2,1));
frame.setSize(400, 300);
frame.setBackground(Color.pink);
frame.setVisible(true);
Panel panel1 = new Panel(new BorderLayout());
Panel panel2 = new Panel(new BorderLayout());
Panel panel3 = new Panel(new GridLayout(2, 1));
Panel panel4 = new Panel(new GridLayout(2, 2));
panel1.add(new Button("btn-p1-west"), BorderLayout.WEST);
panel1.add(new Button("btn-p1-east"), BorderLayout.EAST);
panel3.add(new Button("btn-p3-0"));
panel3.add(new Button("btn-p3-1"));
panel1.add(panel3);
panel2.add(new Button("btn-p2-west"), BorderLayout.WEST);
panel2.add(new Button("btn-p2-east"), BorderLayout.EAST);
for (int i = 0; i < 4; i++) {
panel4.add(new Button("btn-p4-" + i));
}
panel2.add(panel4);
frame.add(panel1);
frame.add(panel2);
}
3.5、布局管理器总结
- Frame是一个顶级窗口,Frame的缺省布局管理器为BorderLayout
- Panel无法单独显示,必须添加到某个容器中,Panel的缺省布局管理器为FlowLayout
- 当把Panel作为一个组件被添加到某个容器中后,该Panel仍然可以有自己的布局管理器
- 使用布局管理器时,布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件大小和位置属性,因此用户无法在这种情况下设置组件大小和位置属性。如果试图使用Java语言提供的设置相关属性的方法,都会被布局管理器所覆盖
- 如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为
setLayout(null)
5、 事件监听
在时间监听中,事件源可以注册事件监听器对象,并可以向事件监听器对象发送事件对象,事件发生后,事件源将事件对象发给已经注册的所有事件监听器,监听器对象随后会根据事件对象内的相应方法响应这个事件。下面对涉及到的术语进行一个介绍:
- 事件对象:继承自
java.util.EventObject 对象,由开发者自行定义实现; - 事件源:就是触发事件的源头,不同的事件源会触发不同的事件类型;
- 事件监听器:事件监听器负责监听事件源发出的事件,事件监听器可以通过实现
java.util.EventListener 这个标识接口,实现事件监听。
5.1、 按钮点击事件
public class ButtonEventTest {
public static void main(String[] args) {
Frame frame = new Frame("ButtonEvent");
Button btnStart = new Button("start");
Button btnStop = new Button("stop");
MyActionListener listener = new MyActionListener();
btnStart.addActionListener(listener);
btnStop.addActionListener(listener);
frame.setLayout(new FlowLayout());
frame.add(btnStart);
frame.add(btnStop);
addWindowClosingEvent(frame);
frame.setSize(300, 300);
frame.setVisible(true);
}
private static void addWindowClosingEvent(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button " + e.getActionCommand() + " has been Pressed");
}
}
5.2、 文本框监听事件
TextField对象可能发生Action(光标在文本框内敲回车)事件。与该事件对应的事件类是java.awt.event.ActionEvent 。
- 用来处理ActionEvent事件是实现了
java.awt.event.ActionListener 接口并且实现了接口内方法public void actionPerformed(ActionEvent e) 的对象; - 实现该接口的类要在该方法中添加处理该事件(Action)的语句;
- 使用addActionListener(ActionListener I) 方法为 TextField 对象注册一个 ActionListener 对象,当TextField 对象发生Action事件时,会生成一个 ActionEvent 对象,该对象作为参数传递给 ActionListener 对象的actionPerformer 方法在方法中可以获取该对象的信息,并作相应的处理。
public class TextFieldTest {
public static void main(String[] args) {
new MyFrameTextField("Test", 300, 300);
}
}
class MyFrameTextField extends Frame {
public MyFrameTextField() {
TextField textField = new TextField();
add(textField);
textField.addActionListener(new MyMonitor());
textField.setEchoChar('*');
setVisible(true);
pack();
}
public MyFrameTextField(String title, int width, int height){
this();
setTitle(title);
setSize(width, height);
}
}
class MyMonitor implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
TextField textField = (TextField) e.getSource();
System.out.println(textField.getText());
textField.setText("");
}
}
5.3、加法计算器练习
思路:
- 定义三个文本框,用作加数、被加数以及求出的和
- 使用Label类创建一个静态文本对象
- 创建等号按钮同时加上监听事件,使得按下按钮之后可以进行求和
- 将上面三个文本框、Label对象和按钮以流式布局加到窗体中
- 监听时间加上处理文本框数据的操作
public class CalculatorTest {
public static void main(String[] args) {
new Calculator().launchFrame();
}
}
class Calculator extends Frame {
private TextField num1;
private TextField num2;
private TextField sum;
public void launchFrame() {
num1 = new TextField(10);
num2 = new TextField(10);
sum = new TextField(15);
Label labelPlus = new Label("+");
Button btnEqual = new Button("=");
btnEqual.addActionListener(new CalcMonitor());
setLayout(new FlowLayout());
add(num1);
add(labelPlus);
add(num2);
add(btnEqual);
add(sum);
pack();
setVisible(true);
addWindowClosingEvent(this);
}
public TextField getNum1() {
return num1;
}
public TextField getNum2() {
return num2;
}
public TextField getSum() {
return sum;
}
private class CalcMonitor implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int num1 = Integer.parseInt(Calculator.this.num1.getText());
int num2 = Integer.parseInt(Calculator.this.num2.getText());
sum.setText(String.valueOf(num1+num2));
System.out.println(sum.getText());
Calculator.this.num1.setText("");
Calculator.this.num2.setText("");
}
}
private void addWindowClosingEvent(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
6、Graphics类
每个Component都有一个paint(Graphic g) 用于实现绘图目的,每次重画该Component时都会自动调用paint方法。paint方法是一个特殊的方法,在创建Frame窗体时会自动隐式调用,因此在主函数里面并没有显示调用paint(Graphic g) 方法。当我们把Frame窗体最小化再打开时,又会再次调用**paint()方法重新把圆和矩形在Frame窗体上画出来,即每次需要重画Frame窗体时就会自动调用paint()**方法。
public class PaintTest {
public static void main(String[] args) {
new MyPaint().launchFrame();
}
}
class MyPaint extends Frame {
public void launchFrame() {
setBounds(200, 200, 400, 500);
setVisible(true);
pack();
}
@Override
public void paint(Graphics g) {
Color color = g.getColor();
g.setColor(Color.PINK);
g.fillOval(100, 100, 100, 50);
g.setColor(Color.yellow);
g.fillRect(150, 200, 200, 200);
g.setColor(color);
}
}
值得注意的是,在画笔这一块有一个良好的编程习惯推荐,即在使用完画笔之后,应该把画笔的初始颜色恢复过来,这就相当于画家在用完画笔之后会把画笔上的颜料清理掉一样。
7、鼠标事件适配器
抽象类java.awt.event.MouseAdapter 实现了MouseListener接口,可以使用其子类作为MouseEvent的监听器,只要重写其相应的方法即可。当然,对于其他的监听器,只要重写其相对应的方法即可。使用适配器可以有小米面监听器定义没有必要的空方法。
public class MouseAdapterTest {
public static void main(String[] args) {
new MyMouseFrame("drawing");
}
}
class MyMouseFrame extends Frame {
ArrayList points = null;
public MyMouseFrame() {
points = new ArrayList();
setLayout(null);
setBounds(200,200,300,300);
setBackground(new Color(204,204,255));
setVisible(true);
addWindowClosingEvent(this);
}
public MyMouseFrame(String title) {
this();
setTitle(title);
addMouseListener(new Monitor());
}
@Override
public void paint(Graphics g) {
Iterator iterator = points.iterator();
while (iterator.hasNext()) {
Point point = (Point)iterator.next();
g.setColor(Color.PINK);
g.fillOval(point.x, point.y, 10, 10);
}
}
private void addWindowClosingEvent(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
private class Monitor extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
MyMouseFrame frame = (MyMouseFrame) e.getSource();
points.add(new Point(e.getX(), e.getY()));
frame.repaint();
}
}
}
8、window事件
public void windowActivated(WindowEvent e);
public void windowClosed(WindowEvent e);
public void windowClosing(WindowEvent e);
public void windowDeactivated(WindowEvent e);
public void windowDeiconified(WindowEvent e);
public void windowIconified(WindowEvent e);
public void windowOpened(WindowEvent e);
public class TestWindowClose{
public static void main(String args[]){
new WindowFrame("关闭WindowFrame");
}
}
class WindowFrame extends Frame{
public WindowFrame(String s){
super(s);
setBounds(200,200,400,300);
setLayout(null);
setBackground(new Color(204,204,255));
setVisible(true);
this.addWindowListener(new WindowMonitor());
this.addWindowListener(
new WindowAdapter(){
public void windowClosing(WindowEvent e){
setVisible(false);
System.exit(-1);
}
}
);
}
class WindowMonitor extends WindowAdapter{
public void windowClosing(WindowEvent e){
setVisible(false);
System.exit(0);
}
}
}
9、键盘响应事件
键盘的处理事件是这样的:每一个键都对应着一个虚拟的码,当按下某一个键时,系统就会去找这个键对应的虚拟的码,以此来确定当前按下的是哪个键
public class TestKeyEvent{
public static void main(String args[]){
new KeyFrame("键盘响应事件");
}
}
class KeyFrame extends Frame{
public KeyFrame(String s){
super(s);
setBounds(200,200,400,300);
setLayout(null);
setVisible(true);
addKeyListener(new KeyMonitor());
}
class KeyMonitor extends KeyAdapter {
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_UP){
System.out.println("你按的是up键");
}
}
}
}
三、Swing
? Swing 是GUI(图形用户界面)开发工具包 ,内容有很多,这里会分块编写,但在进阶篇中只编写 Swing中的基本要素,包括容器、组件和布局等,更深入的内容这里就不介绍了。想深入学习的朋友们可查阅有关资料或图书,比如《Java Swing图形界面开发与案例详解》——清华大学出版社。
? 早期的AWT(抽象窗口工具包)组件开发的图形用户界面,要依赖本地系统,当把AWT组件开发的应用程序移植到其他平台的系统上运行时,不能保证其外观风格,因此AWT是依赖于本地系统平台的。 而使用Swing开发的Java应用程序,其界面是不受本地系统平台限制的,也就是说Swing开发的Java应用程序移植到其他系统平台上时,其界面外观是不会改变的。但要注意的是,虽然Swing提供的组件可以方便开发Java应用程序,但是Swing并不能取代AWT,在开发Swing程序时通常要借助与AWT的一些对象 来共同完成应用程序的设计。
1、 JFrame框架窗体
JFrame 窗体是一个容器,在Swing开发中我们经常要用到,它是Swing程序中各个组件的载体。
在JFrame对象创建完成后,需要调用getContentPane() 方法将窗体转换为容器,然后在容器中添加组件 或设置布局管理器,通常这个容器用来包含和显示组件。如果需要将组件添加至容器,可以使用来自 Container类的add()方法 进行设置。
public class JFrameDemo {
public static void main(String[] args) {
new JFrameDemo().CreateJFrame();
}
public void CreateJFrame() {
JFrame jFrame = new JFrame("这是一个JFrame窗口");
jFrame.setVisible(true);
jFrame.setBounds(100, 100, 300, 300);
jFrame.setBackground(Color.pink);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
当然,在开发中更常用的方式是通过继承``java.swing.JFrame`类创建一个窗体,可通过this关键字调用其方法。
public class JFrameDemo2 extends JFrame {
public void init() {
setVisible(true);
setBounds(100, 100, 300, 300);
setTitle("JFrame窗口");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JLabel jLabel = new JLabel("这是一个JLabel标签");
jLabel.setHorizontalAlignment(SwingConstants.CENTER);
Container container = getContentPane();
container.add(jLabel);
container.setBackground(Color.pink);
}
public static void main(String[] args) {
new JFrameDemo2().init();
}
}
2、JDialog窗体
JDialog窗体是Swing组件中的对话框,继承了AWT组件中的java.awt.Dialog 类。功能是从一个窗体中弹出另一个窗体。
public class JDialogDemo extends JDialog{
static MyJFrame jFrame;
public JDialogDemo() {
super(jFrame, "这是一个JDialog窗体", true);
Container container = getContentPane();
JLabel jLabel = new JLabel("这是一个JLabel");
jLabel.setHorizontalAlignment(SwingConstants.CENTER);
container.add(jLabel);
setBounds(350, 350, 300, 300);
}
public static void main(String[] args) {
jFrame = new MyJFrame();
}
}
class MyJFrame extends JFrame {
public MyJFrame() {
setBounds(250, 250, 500, 500);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
Container container = getContentPane();
container.setLayout(null);
JButton jButton = new JButton("点击弹出对话框");
jButton.setBounds(30, 30, 200, 50);
jButton.setHorizontalAlignment(SwingConstants.CENTER);
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new JDialogDemo().setVisible(true);
}
});
container.add(jButton);
}
}
3、 标签组件
在Swing中显示文本或提示信息的方法是使用标签,它支持文本字符串和图标。
3.1、标签
标签由JLabel类定义,可以显示一行只读文本、一个图像或带图像的文本。
JLabel类提供了许多构造方法,可查看API选择需要的使用,如显示只有文本的标签、只有图标的标签或包含文本与图标的标签等。常用的语法如下,创建的是一个不带图标和文本的Label对象
JLabel jl = new JLabel();
3.2、图标
Swing中的图标可以放置在按钮、标签等组件上,用于描述组件的用途。图标可以用Java支持的图片文件类型进行创建,也可以使用java.awt.Graphics 类提供的功能方法来创建。在Swing中通过Icon接口来创建图标,可以在创建时给定图标的大小、颜色等特性。
注意,Icon是接口,在使用Icon接口的时候,必须实现Icon接口的三个方法:
- public int getIconWidth() // 获取图片的宽度
- public int getIconHeight() // 获取图片的高度
- public void paintIcon(Component arg(), Graphics arg1, int arg2, int arg3) // 用于实现在指定坐标位置上画图
public class IconDemo extends JFrame implements Icon {
private int width;
private int height;
public IconDemo() {}
public IconDemo(int width, int height) {
this.width = width;
this.height = height;
}
public void init() {
IconDemo iconDemo = new IconDemo(15, 15);
JLabel jLabel = new JLabel("iconDemo", iconDemo, SwingConstants.CENTER);
Container container = getContentPane();
container.add(jLabel);
setBounds(300, 300, 300, 300);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.fillOval(x, y, width, height);
}
@Override
public int getIconWidth() {
return width;
}
@Override
public int getIconHeight() {
return height;
}
public static void main(String[] args) {
new IconDemo().init();
}
}
3.3、图片图标
Swing中的图标除了可以绘制之外,还可以使用某个特定的图片创建。利用javax.swing.ImageIcon 类根据现有图片创建图标。
public class ImageIconDemo extends JFrame {
public ImageIconDemo() {
URL url = ImageIconDemo.class.getResource("ImageIconTest.jpg");
System.out.println(url);
ImageIcon imageIcon = new ImageIcon(url);
imageIcon.setImage(imageIcon.getImage().getScaledInstance(150, 150, Image.SCALE_DEFAULT));
JLabel jLabel = new JLabel("JLabel标签,旁边的是照片", imageIcon, SwingConstants.CENTER);
jLabel.setOpaque(true);
Container container = getContentPane();
container.add(jLabel);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(500, 500);
setVisible(true);
}
public static void main(String[] args) {
new ImageIconDemo();
}
}
4、 布局管理器
Swing中,每个组件在容器中都有一个具体的位置和大小,在容器中摆放各自组建时很难判断其具体位置和大小,这里我们就要引入布局管理器了。它提供了基本的布局功能,可以有效的处理整个窗体的布局。常用的布局管理器包括流式布局管理器、边界布局管理器、网格布局管理器等。
4.1、绝对布局
绝对布局是硬性制定组件在容器中的位置和大小,可以使用绝对坐标的方式来指定组件的位置。具体步骤如下
- 使用
Container.setLayout(null) 方法取消布局管理器 - 使用
Container.setBounds() 方式设置每一个组件的位置和大小
public void absoluteLayoutTest() throws InterruptedException {
JFrame jFrame = new JFrame();
Container container = jFrame.getContentPane();
container.setLayout(null);
jFrame.setBounds(30, 30, 300, 300);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
Thread.sleep(10000);
}
4.2、流式布局管理器
? 流布局管理器是布局管理器中最基本的布局管理器,使用FlowLayout类,像“流”一样从左到右摆放 组件,直到占据了这一行的所有空间,再向下移动一行。组件在每一行的位置默认居中排列,要更改位置可自行设置。
? 在FlowLayout的有参构造方法中,alignment设置为0时,每一行的组件将被指定左对齐排列;当 alignment被设置为2时,每一行的组件将被指定右对齐排列;而为1时是默认的居中排列。
@Test
public void flowLayoutTest() throws InterruptedException {
JFrame jFrame = new JFrame("流式布局");
Container container = jFrame.getContentPane();
container.setLayout(new FlowLayout(2, 10, 110));
for (int i = 0; i < 10; i++) {
container.add(new JButton("按钮" + (i+1)));
}
jFrame.setSize(300, 300);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
Thread.sleep(10000);
}
4.3、边界布局管理器
在不指定窗体布局时,Swing组件默认的布局管理器是边界布局管理器,使用的是BorderLayout 类。在上面的例子中,一个JLabel标签占据了整个空间,实质上是默认使用了边界布局管理器。边界布局管理器还可以容器分为东、南、西、北、中五个区域,可以将组件加入这五个区域中。
public void BorderLayoutTest() throws InterruptedException {
String[] border = {BorderLayout.CENTER,
BorderLayout.NORTH,
BorderLayout.SOUTH,
BorderLayout.WEST,
BorderLayout.EAST};
String[] button = {"中", "北", "南", "西", "东"};
JFrame jFrame = new JFrame("边界布局");
Container container = jFrame.getContentPane();
container.setLayout(new BorderLayout());
for (int i = 0; i < button.length; i++) {
container.add(border[i], new JButton(button[i]));
}
jFrame.setSize(300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
4.4、网格布局管理器
网格布局管理器将容器划分为网格,组件按行按列排列,使用GridLayout 类。在此布局管理器中,每个 组件的大小都相同,且会填满整个网格,改变窗体大小,组件也会随之改变。
public void GridLayoutTest() throws InterruptedException {
JFrame jFrame = new JFrame("边界布局");
Container container = jFrame.getContentPane();
container.setLayout(new GridLayout(7, 3, 5, 5));
for (int i = 0; i < 20; i++) {
container.add(new JButton("按钮" + (i+1)));
}
jFrame.setSize(300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
5、 面板
面板也是一个容器,可作为容器容纳其他组件,但耶必须被添加到其他容器中。Swing中常用面板有JPanel面板和JScrollPane面板。
5.1、JPanel
JPanel面板可以聚集一些组件来布局。继承自java.awt.Container 类。
public class JPanelDemo extends JFrame {
public JPanelDemo() {
Container container = getContentPane();
container.setLayout(new GridLayout(2, 1, 10, 10));
JPanel jPanel = new JPanel(new GridLayout(1, 3));
JPanel jPane2 = new JPanel(new GridLayout(1, 2));
JPanel jPane3 = new JPanel(new GridLayout(2, 1));
JPanel jPane4 = new JPanel(new GridLayout(3, 2));
for (int i = 0; i < 3; i++) {
jPanel.add(new JButton("1"));
}
for (int i = 0; i < 2; i++) {
jPane2.add(new JButton("2"));
}
for (int i = 0; i < 2; i++) {
jPane3.add(new JButton("3"));
}
for (int i = 0; i < 6; i++) {
jPane4.add(new JButton("4"));
}
container.add(jPanel);
container.add(jPane2);
container.add(jPane3);
container.add(jPane4);
setSize(300, 300);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new JPanelDemo();
}
}
5.2、JScrollPane
? 若遇到一个较小的容器窗体中显示一个较大部分内容的情况,可用JScrollPane面板。这是一个带滚动条的面板,就像平时浏览网页,经常遇到的滚动条一样。
? 如果需要在JScrollPane面板中放置多个组件,需将这多个组件放置在JPanel面板上,然后将JPanel 面板作为一个整体组件添加在JScrollPane面板上。
public class JScrollPaneDemo extends JFrame {
public JScrollPaneDemo() {
Container container = getContentPane();
JTextArea jTextArea = new JTextArea(20, 50);
jTextArea.setText("欢迎来到陈宝子的练习");
JScrollPane jScrollPane = new JScrollPane(jTextArea);
container.add(jScrollPane);
setSize(300, 300);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new JScrollPaneDemo();
}
}
6、 按钮组件
6.1、提交按钮组件(JButton)
JButton是较为常用的组件,用于触发特定动作。可以在按钮上显示文本标签,还可以显示图标。
public class JButtonTest extends JFrame {
public JButtonTest() {
Container container = getContentPane();
ImageIcon imageIcon = new ImageIcon(JButtonTest.class.getResource("ImageIconTest.jpg"));
imageIcon.setImage(imageIcon.getImage().getScaledInstance(300, 300, Image.SCALE_DEFAULT));
JButton jButton = new JButton();
jButton.setIcon(imageIcon);
jButton.setToolTipText("照片按钮");
container.add(jButton);
setSize(300, 300);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new JButtonTest();
}
}
6.2、单选按钮组件(JRadioButton)
默认情况下,单选按钮显示一个圆形图标,通常在其旁放置一些说明性文字。当用户选中某个单选按钮后,按钮组中其它按钮将被自动取消,这时就需要按钮组(ButtonGroup)来将同组按钮放在一起,该按钮组中的按钮只能选择一个,而不在此按钮中的按钮不受影响。
public class JRadioButtonTest extends JFrame {
public JRadioButtonTest() {
Container container = getContentPane();
JRadioButton jRadioButton1 = new JRadioButton("JRadioButton1");
JRadioButton jRadioButton2 = new JRadioButton("JRadioButton2");
JRadioButton jRadioButton3 = new JRadioButton("JRadioButton3");
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(jRadioButton1);
buttonGroup.add(jRadioButton2);
buttonGroup.add(jRadioButton3);
container.add(jRadioButton1, BorderLayout.CENTER);
container.add(jRadioButton2, BorderLayout.NORTH);
container.add(jRadioButton3, BorderLayout.SOUTH);
setSize(300, 300);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new JRadioButtonTest();
}
}
6.3、复选框组件(JCheckBox)
复选框是一个方块图标,外加一段描述性文字,与单选按钮的区别就是可以多选。每一个复选框都提供“选中”与“不选中”两种状态。
public class JCheckBoxTest extends JFrame {
public JCheckBoxTest() {
Container container = getContentPane();
JCheckBox jCheckBox1 = new JCheckBox("JCheckBox1");
JCheckBox jCheckBox2 = new JCheckBox("JCheckBox2");
container.add(jCheckBox1);
container.add(jCheckBox2, BorderLayout.NORTH);
setSize(300, 300);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new JCheckBoxTest();
}
}
7、 列表组件
7.1、下拉列表(JComboBox)
@Test
public void jComboBoxTest() throws InterruptedException {
JFrame jFrame = new JFrame("JComboBoxTest");
Container container = jFrame.getContentPane();
JComboBox jComboBox = new JComboBox();
jComboBox.addItem("正在上映");
jComboBox.addItem(null);
jComboBox.addItem("即将上映");
jComboBox.addItem("已经下架");
container.add(jComboBox);
jFrame.setBounds(300, 300, 300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
7.2、列表框(JList)
列表框只是在窗体上占据固定的大小,如果要使列表框具有滚动效果,可以将列表框放入滚动面板中。
使用数组初始化列表框的参数如下:
@Test
public void jListTest() throws InterruptedException {
JFrame jFrame = new JFrame("JListTest");
Container container = jFrame.getContentPane();
String[] contents = {"1", "2", "3"};
JList jList = new JList(contents);
container.add(jList);
jFrame.setBounds(300, 300, 300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
使用集合初始化列表框的参数如下:
@Test
public void jListByVectorTest() throws InterruptedException {
JFrame jFrame = new JFrame("jListByVectorTest");
Container container = jFrame.getContentPane();
Vector vector = new Vector();
JList jList = new JList(vector);
vector.addAll(Arrays.asList("1", "2", "3"));
container.add(jList);
jFrame.setBounds(300, 300, 300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
8、 文本组件
8.1、文本框(JTextField)
文本框通常用来显示或编辑一个单行文本
@Test
public void JTextFieldTest() throws InterruptedException {
JFrame jFrame = new JFrame("JTextFieldTest");
Container container = jFrame.getContentPane();
container.setLayout(new FlowLayout());
JTextField jTextField = new JTextField("这是一个文本框", 20);
container.add(jTextField);
jFrame.setBounds(300, 300, 300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
8.2、密码框(JPasswordField)
密码框与文本框的定义与用法类似,其继承于JTextField 类,但会使用户输入的字符串以某种符号进行加密。
@Test
public void jPasswordFieldTest() throws InterruptedException {
JFrame jFrame = new JFrame("JPasswordFieldTest");
Container container = jFrame.getContentPane();
container.setLayout(new FlowLayout());
JPasswordField jPasswordField = new JPasswordField("123456", 20);
jPasswordField.setEchoChar('*');
System.out.println(jPasswordField.getPassword());
container.add(jPasswordField);
jFrame.setBounds(300, 300, 300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
8.3、文本域(JTextArea)
在文本域中可以输入多行多列的值,其和JTextField 一样继承了JTextComponent
@Test
public void jTextAreaTest() throws InterruptedException {
JFrame jFrame = new JFrame("JTextAreaTest");
Container container = jFrame.getContentPane();
container.setLayout(new FlowLayout());
JTextArea jTextArea = new JTextArea("这是一个文本域", 10, 50);
container.add(jTextArea);
jFrame.setBounds(300, 300, 300, 300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setVisible(true);
Thread.sleep(10000);
}
|