文章目录
第十一章 GUI
GUI: 全称是Graphical User Interface,即图形用户界面。顾名思义,就是应用程序提供给用户操作的图形界面,包括窗口、菜单、按钮、工具栏和其他各种图形界面元素。目前,图形用户界面已经成为一种趋势,几乎所有的程序设计语言都提供了GUI设计功能。Java中针对GUI设计提供了丰富的类库,这些类分别位于java.awt和javax.swing包中,简称为AWT和Swing。
AWT是用于创建图形用户界面的一个工具包,它提供了一系列用于实现图形界面的组件,如窗口、按钮、文本框、对话框等。其中,Component类通常被称为组件,根据Component的不同作用,可将其分为基本组件类和容器类。而容器类则是通过Component的子类Container实例化的对象。Container类表示容器,它是一种特殊的组件,可以用来容纳其他组件。
常用容器
框架(JFrame) 内部包含一个名叫Container(内容面板)的面板容器,如果要给框架中添加图形控件,通常将它们加入到这个内容面板中。
通过JFrame类中的getContentPane()方法即可获得此框架的内容面板。
也可以自己创建Jpanel面板对象,把JPanel作为一个组件添加到某个容器中.
常用方法:
void setBackground(Color bg)设置面板的背景色,由参数bg指定颜色
void setLayout(LayoutManager mgr)设置面板的布局,参数是布局管理器
Component add(Component comp)往面板中添加一个组件
1,JFrame
Frame相当于一个大的框架,再它里面可以放多个组件、多个面版。它是相对于了window界面来说的。
//创建一个Frame实例对象:
JFrame jframe = new JFrame("This is my first FrameTest");
//设置窗口名字
jframe.setTitle("窗口名字");
//设置界面可见:
jframe.setVisible(true);
//设置窗口大小:
jframe.setSize(500,500);
//设置背景颜色:
jframe.setBackground(Color.orange);
//设置弹出初始位置:
jframe.setLocation(500,500);
//设置界面大小固定:
jframe.setResizable(false);
//设置窗口出现的位置
jframe.setLocation(int x,int y);
//默认出现的位置为中间
jframe.setLocationRelativeTo(null);
//设置窗口不能关闭
jframe.setDefaultCloseOperation(int operation);
//关闭窗口
jframe.dispose();
JPanel提供面板,它是轻量级的容器;
面板中可以添加其它组件,也可以设置布局,我们一般使用面板来实现布局嵌套;
JPanel() | 创建一个空面板 |
---|---|
JPanel(LayoutManaer layout) | 创建带有指定布局的面板 |
2,Panel
Panel也是一个容器,但是它不能单独存在,只能存在其他容器(Window或其子类)中,一个Panel对象代表了一个长方形的区域,在这个区域中可以容纳其他组件。在程序中通常会使用Panel来实现一些特殊的布局。
//Panel类似于一个空间,但是不能单独使用(可再Frame里面使用Panel)
public static void main(String[] args) {
Frame frame = new Frame();
//在Frame里面的布局:
Panel panel = new Panel();
//设置布局:
frame.setLayout(null); //默认将Panel属性置顶
//设置Frame的坐标:
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(82, 142, 146)) ;
//设置Panel的坐标,在Frame里面的左边:
panel.setBounds(50,50,100,100);
panel.setBackground(new Color(47, 15, 45));
//将Panel的布局加入到Frame里面去:
frame.add(panel);
frame.setVisible(true);
3,布局管理器
当一个容器被创建后,它们都会有一个默认的布局管理器。Window、Frame和Dialog的默认布局管理器是BorderLayout,Panel的默认布局管理器是FlowLayout。如果不希望通过布局管理器来对容器进行布局,也可以调用容器的setLayout(null)方法,将布局管理器取消。
组件不能单独存在,必须放置于容器当中,而组件在容器中的位置和尺寸是由布局管理器来决定的。接下来,我们就介绍三种比较常用的布局管理器:
1)流式布局管理器FlowLayout
在流式布局下,容器会将组件按照添加顺序从左向右放置。当到达容器的边界时,会自动将组件放到下一行的开始位置。这些组件可以左对齐、居中对齐(默认方式)或右对齐的方式排列。
this.setLayout(new FlowLayout());
this.add(new Button(“确定”));
this.add(new Button(“取消”));
FlowLayout布局管理器对组件逐行定位,行内从左到右,一行排满后换行。
不改变组件的大小,按组件原有尺寸显示组件,可设置不 同的组件间距,行距以及对齐方式。
构造方法
new FlowLayout(FlowLayout.RIGHT,20,40);右对齐,组件之间水平间距20个像素,垂直间距40个像素。
new FlowLayout(FlowLayout.LEFT);左对齐,水平和垂直间距为缺省值(5)。
new FlowLayout();使用缺省的居中对齐方式,水平和垂直间距为缺省值(5)。
JFrame jframe = new JFrame();
jframe.setVisible(true);
//组件-button
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button3");
//设置流式布局:
jframe.setLayout(new FlowLayout());
// frame.setLayout(new FlowLayout(FlowLayout.LEFT)); //布局偏左
// frame.setLayout(new FlowLayout(FlowLayout.RIGHT)); //布局偏右
jframe.setSize(200,200);
//把button填加到frame:
jframe.add(button1);
jframe.add(button2);
jframe.add(button3);
2)边界布局管理器BorderLayout
BorderLayout布局管理器只允许在容器内放置5个组件,这5个组件的位置是由BorderLayout类中的North、South、East、West和Center5个常量来确定的,他们对应着容器中的上下左右中,用法如下:
this.add(new Button(“按钮”) ,BorderLayout.NORTH);
this.add(new Button(“按钮”) ,BorderLayout.CENTER);
组件在BorderLayout中的大小都是可以改变的。一般情况下可以让中间区域大一些,而且可以只用其中几个区域。
BorderLayout将整个容器的布局划分成东(EAST)西(WEST)南(SOUTH)北(NORTH)中(CENTER)五个区域,组件只能被添加到指定的区域。
如不指定组件的加入部位,则默认加入到CENTER区。
每个区域只能加入一个组件,如加入多个,则先前加入的会被覆盖。
BorderLayout型布局容器尺寸缩放原则:
北、南两个区域在水平方向缩放。
东、西两个区域在垂直方向缩放。
中部可在两个方向上缩放。
JFrame jframe = new JFrame("TestBorderLayout:");
jframe.setVisible(true);
jframe.setSize(500,500);
Button button1 = new Button("East");
Button button2 = new Button("West");
Button button3 = new Button("South");
Button button4 = new Button("North");
Button button5 = new Button("Center");
//BorderLayout的使用:
jframe.add(button1,BorderLayout.EAST); //add(添加的组件,边界布局设置)
jframe.add(button2,BorderLayout.WEST);
jframe.add(button3,BorderLayout.SOUTH);
jframe.add(button4,BorderLayout.NORTH);
jframe.add(button5,BorderLayout.CENTER);
3)网格布局管理器GriLayout
GridLayout布局管理器是矩形网格,在网格中放置组件,每个网格的高度和宽度都相等,组件随着网格的大小而在水平和垂直方向上拉伸,网格的大小是由容器的大小和创建网格的多少来确定的。其用法如下:
this.setLayout(new GridLayout(2 , 3)); //创建一个2行3列的网格
this.add(new Button(“按钮”));
当组件数目大于网格数时,GridLayout保持行数不变而自动增加列数。
GridLayout型布局管理器将空间划分成规则的矩形网格,每个单元格区域大小相等。 组件被添加到每个单元格中,先从左到右添满一行后换行,再从上到下。
在 GridLayout 构造方法中指定分割的行数和列数.
JFrame jframe = new JFrame("TestGridLayout:");
jframe.setSize(500,500);
jframe.setVisible(true);
//设置布局格式:3行2列
jframe.setLayout(new GridLayout(3,2));
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button3");
Button button4 = new Button("button4");
Button button5 = new Button("button5");
Button button6 = new Button("button6");
jframe.add(button1);
jframe.add(button2);
jframe.add(button3);
jframe.add(button4);
jframe.add(button5);
jframe.add(button6);
4,事件监听
对于采用了图形用户界面的程序来说,事件控制是非常重要的;到目前为止,我们编写的图形用户界面程序都仅仅只是完成了界面,而没有任何实际的功能,要实现相应的功能,必须进行事件处理;
用户与GUI组件进行交互就会发生事件,如:按下一个按钮、用键盘输入一个字符、点击鼠标等等;
当前我们要关注的并不是“事件是如何产生的”,而是讨论当发生事件后,我们应当“如何处理之”。
Java中,事件处理的基本思路如下:
一个源(事件源)产生一个事件(事件对象)并把它送到监听器那里,监听器只是简单地等待,直到它收到一个事件,一旦事件被接受,监听器将处理这些事件;
一个事件源必须注册监听器以便监听器可以接受关于一个特定事件的通知。
1)事件处理
添加事件监听器(此处即为匿名类)
按钮对象.addActionListener(new ActionListener() {
// 事件处理
@Override
public void actionPerformed(ActionEvent e) {
执行操作
}
});
2)对话框
JOptionPane对话框
showMessageDialog():消息对话框
主要有五种消息类型,类型不同,图标不同:
ERROR_MESSAGE 错误消息提示
INFORMATION_MESSAGE 信息提示
WARNING_MESSAGE 警告提示
QUESTION_MESSAGE 问题提示
PLAIN_MESSAGE 简洁提示
showConfirmDialog():确认对话框
主要有四种消息类型,类型不同,图标不同:
DEFAULT_OPTION 默认选项
YES_NO_OPTION 是/否选项
YES_NO_CANCEL_OPTION 是/否/取消选项
OK_CANCEL_OPTION 确定/取消
3)窗口监听事件
Window类型的窗口需要实现WindowListener。接着通过addWindowListener()方法为事件源注册事件监听器对象,当事件源上发生事件时,便会触发事件监听器对象,由事件监听器调用相应的方法来处理相应的事件。MyWindowListener类实现WindowListener接口后,需要实现接口中定义的7个方法,然而在程序中需要用到的只有windowClosing()
一个方法,其他六个方法都是空实现,没有发挥任何作用,所以可以使用事件适配器。
当对窗体事件进行处理时,首先需要定义一个实现了WindowListener接口的类作为窗体监听器,然后通过addWindowListener()方法将窗体对象与窗体监听器绑定。
public class WindowListeners {
public static void main(String[] args) {
new WindowFrame();
}
}
class WindowFrame extends Frame{
public WindowFrame(){
setBounds(100,100,400,300);
//添加button组件到界面中:
Button button = new Button("setVisible!");
add(button);
setVisible(true);
//设置窗口监听,使用适配器模式:
addWindowListener(new WindowAdapter() {
//监听窗口关闭:
@Override
public void windowClosing(WindowEvent e) {
System.out.println("windowClosing");
}
//监听窗口动态:
@Override
public void windowActivated(WindowEvent e) {
System.out.println("windowActivated");
}
});
}
}
4)鼠标监听事件
在图形用户界面中,用户会经常使用鼠标来进行选择、切换界面等操作,这些操作被定义为鼠标事件,JDK中提供了一个MouseEvent类用于表示鼠标事件,几乎所有的组件都可以产生鼠标事件。
首先需要通过实现MouseListener接口定义监听器(也可以通过继承适配器MouseAdapter
类来实现),然后调用addMouseListener()方法将监听器绑定到事件源对象。
public class mouse extends Frame {
public mouse(){
setBounds(100,100,400,350);
setVisible(true);
Button b1 = new Button("btn1");
Button b2 = new Button("btn2");
//添加鼠标事件:
b1.addMouseListener(new MouseListen());
add(b1,BorderLayout.SOUTH);
add(b2,BorderLayout.NORTH);
}
class MouseListen extends MouseAdapter {
//定义鼠标按压触发监听效果:
@Override
public void mousePressed(MouseEvent e) {
Object source = e.getSource();
System.out.println("鼠标点击了!");
}
}
public static void main(String[] args) {
new mouse();
}
5)键盘监听事件
键盘操作也是最常用的用户交互方式,例如键盘按下、释放等,这些操作被定义为键盘事件。JDK中提供了一个KeyEvent类表示键盘事件,处理KeyEvent事件的监听器对象需要实现KeyListener接口或者继承KeyAdapter
类。
public class KeyListenP {
public static void main(String[] args) {
new KeyFrame();
}
}
class KeyFrame extends Frame{
public KeyFrame(){
setBounds(100,100,400,300);
setVisible(true);
//键盘监听事件:
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//当键盘按压下去时,输入按下的键值:
int keyCode = e.getKeyCode();
if (keyCode ==e.VK_ENTER){ //可以使用KeyEvent.VK_ENTER代表的键盘的值
System.out.println("按下回车键");
}
}
});
ListenClose(this);
}
}
6)动作监听事件
动作事件与前面三种事件有所不同,它不代表某个具体的动作,只是表示一个动作发生了。动作事件用ActionEvent类表示,处理ActionEvent事件的监听器对象需要实现ActionListener接口。可适用于窗口、鼠标、键盘等事件的监听处理。
public class TestActionListen {
public static void main(String[] args) {
//按下按钮,触发一些事件:
Frame frame = new Frame();
frame.setSize(400,300);
frame.setVisible(true);
Button button = new Button("点击一下!");
frame.add(button,BorderLayout.CENTER);
//构造一个ActionListener:
MyAction myAction = new MyAction();
button.addActionListener(myAction);
ListenCLose(frame);
}
//关闭窗口事件:
private static void ListenCLose(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
//事件监听:
class MyAction implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
Button button = new Button();
System.out.println(e.getSource());
System.out.println("button点击了");
}
}
5,Swing
swing中,提供了布局管理器类的对象可以管理。
每个Jpanel都有一个布局管理器对象,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其对应的布局管理器,调用Jpanel的setLayout方法改变其布局管理器对象或通过构造方法设置。
6,标签
标签(JLabel)
标签是容纳文本和图标的控件,通常用来在界面中标识别的控件。
构造函数:
JLabel() 创建一个空的标签
JLabel(String text) 创建一个带文本的标签
JLabel(Icon image) 创建一个带图像的标签
方法:
void setText(String text) 设置标签上的文本
String getText() 获得标签上的文本
setFont(new Font(“宋体”,Font.BOLD, 18)); 设置字体
7,按钮
按钮(JButton)
构造方法:
JButton(String text) 创建一个带文本的标签
JButton(Icon image) 创建一个带图像的标签
方法:
void setBackground(Color bg) 设置按钮的背景色
void setEnabled(boolean b) 设置启用(或禁用)按钮,由参数b决定
void setToolTipText(String text) 设置按钮的悬停提示信息
8,文本域&密码框&文本框
1)密码框
密码框(JPasswordField)
构造函数:
JPasswordField()
JPasswordField(String text)
JPasswordField(String text, int columns)
方法:
char[] getPassword()
2)JTextField
单行文本(JTextField)
JTextField的构造函数:
JTextField()
JTextField(String text )
JTextField(int columns)
JTextField(String text, int columns)
方法:
void setText(String text) 设置文本框中的文本
String getText() 获得文本框中的文本
void setEditable(boolean b) 设置文本框是否可以编辑
setColumns(20); 设置列数
3)JTextArea
多行文本框(JTextArea)
构造函数:
JTextArea() 创建一个空的文本域
JTextArea(String text) 用指定文本初始化文本域
JTextArea(int rows, int columns) 创建一个指定行数和列数的空文本域
JTextArea(String text,int rows, int columns) 创建一个带文本,并指行数和列数的
方法:
void setText(String text) 设置文本域中的文本
String getText() 获得文本域中的文本
void setFont(Font font) 设置文本域中文本的字体
void setLineWrap(boolean wrap) //是否自动换行,默认false
如果需要文本区自动出现滚动条,可将文本区对象放入滚动窗(JScrollPane)中:
JScrollPane scrollPane = new JScrollPane(txtArea);
add(scrollPane );
9,菜单栏
菜单栏组件:
构造方法:JMenuBar();
方法:add(menu); 向菜单栏添加菜单
菜单组件:
构造方法:JMenu(“菜单名称");
方法:add(menuItem); 向菜单添加菜单选项
菜单项组件:
构造方法:JMenuItem(“菜单项名称");
将菜单栏添加到窗口
setJMenuBar(menuBar);
//设置一个登录界面
package com.ffyc.gui.hm2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Login1Frame extends JFrame {
public void createFrame() {
//设置登录窗口
this.setSize(380, 180);
this.setTitle("欢迎登录");
this.setLocationRelativeTo(null);//默认居中显示
this.setResizable(false);//禁止设置窗口大小
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口选项
//设置账号面板
JPanel jp = new JPanel(new GridLayout(3, 1));
JPanel accountPanel = new JPanel();
JLabel accountLabel = new JLabel("账号");
JTextField accountText = new JTextField(15);
//给账号输入框添加监听
accountText.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
//从输入框获取账号
if (!accountText.getText().matches("^[A-z|0-9_-]{0,15}$")) {
JOptionPane.showMessageDialog(null, "只能有数字和字母组成~", "登录提示", JOptionPane.WARNING_MESSAGE);
}
}
});
accountPanel.add(accountLabel);
accountPanel.add(accountText);
//设置密码面板
JPanel passwordPanel = new JPanel();
JLabel passwordLabel = new JLabel("密码");
JPasswordField passwordField = new JPasswordField(15);
//密码监听
passwordField.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if (!new String(passwordField.getPassword()).matches("^[A-z|0-9_-]{0,15}$")) {
JOptionPane.showMessageDialog(null, "只能有数字和字母组成~", "登录提示", JOptionPane.WARNING_MESSAGE);
}
}
});
passwordPanel.add(passwordLabel);
passwordPanel.add(passwordField);
//设置登录取消面板
JPanel btnPanel = new JPanel();
JButton loginBtn = new JButton("登录");
//登录监听
loginBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (accountText.getText().length() == 0||new String(passwordField.getPassword()).length()==0) {
JOptionPane.showMessageDialog(null, "账号不能为空~", "登录提示", JOptionPane.WARNING_MESSAGE);
}
else if((accountText.getText().equals("admin"))&(new String(passwordField.getPassword()).equals("111"))){
dispose();//关闭当前窗口
//弹出登录成功后的窗口
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setSize(500, 500);
frame.setTitle("登录成功");
frame.setLocationRelativeTo(null);
frame.setResizable(false);//禁止设置窗口大小
//创建单行文本框
JPanel jPanel1=new JPanel();
JTextField jf=new JTextField(34);
JButton jbt=new JButton("发送");
//创建多行文本框
JPanel jPanel=new JPanel();
JTextArea jt=new JTextArea(25,40);
jt.setEnabled(false);//设置不能输入
jt.setLineWrap(true);
JScrollPane jsp=new JScrollPane(jt);//滚动框
//发送监听
jbt.addActionListener(new ActionListener() {
String s="";
@Override
public void actionPerformed(ActionEvent e) {
if(jf.getText().length()==0){
JOptionPane.showMessageDialog(null, "输入信息不能为空~","提示信息",JOptionPane.WARNING_MESSAGE);
}else{
String s1="";
s+=(jf.getText()+"\n");
jt.setText(s);
jf.setText(s1);
}
}
});
jPanel.add(jsp);
jPanel1.add(jf);
jPanel1.add(jbt);
frame.add(jPanel,BorderLayout.CENTER);
frame.add(jPanel1,BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}else{
JOptionPane.showMessageDialog(null, "账号或密码错误~", "错误提示", JOptionPane.WARNING_MESSAGE);
}
}
});
//取消监听
JButton cancelBtn = new JButton("取消");
cancelBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
accountText.setText("");
passwordField.setText("");
}
});
btnPanel.add(loginBtn);
btnPanel.add(cancelBtn);
jp.add(accountPanel);
jp.add(passwordPanel);
jp.add(btnPanel);
this.add(jp);
this.setVisible(true);//显示窗口
}
}
//运行入口
package com.ffyc.gui.hm2;
public class Run {
public static void main(String[] args) {
new Login1Frame().createFrame();
}
}