目录
1.GUI的概念
1.1GUI的概念
GUI(Graphical User Interface)即图形用户界面,是指采用图形方 式显示的用户界面,与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受。
1.2容器
容器是Component的子类,一个容器可以容纳多个组件,并使他们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面,所有的组件都可以通过add()方法加入容器中。
有三种类型的容器:Window、Panel、ScrollPane
1.2.1窗口(Frame)
package Frame;
import javax.swing.*;
import java.awt.*;
public class LoginFrame extends JFrame {
public LoginFrame() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new LoginFrame();//创建一个窗口对象
}
}
下图为运行结果
1.2.2面板(Panel)
Panel是一种透明的容器,既没有标题,也没有边框。它不能作为最外层的容器单独存在,首先必须先作为一个组件放置在其他容器中,然后在把它当做容器。
package Panel;
import javax.swing.*;
import java.awt.*;
public class Demo1 extends JFrame {
public Demo1() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
JPanel jPanel=new JPanel();
jPanel.setBackground(Color.CYAN);//设置面板的背景颜色
//创建一个按钮
JButton jButton=new JButton("按钮1");
jPanel.add(jButton);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new Demo1();
}
}
2.布局管理器
为了实现跨平台并获得动态的布局效果,java将容器内的所有组件安排给一个“布局管理器”负责管理,如:排列顺序、组件大小、位置、当窗口移动或调整大小后组件变化等功能授权给对应的容器布局管理器来管理。
2.1 流式布局(FlowLayout)
FlowLayout 组件从左到右、从上到下,一个挨一个的放在容器中。(Panel和Applet的默认容器布局)如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。
package Panel;
import javax.swing.*;
import java.awt.*;
public class Demo2 extends JFrame {
public Demo2() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
//JPanel jPanel=new JPanel();
/*
面板组件可以设置布局管理方式:布局管理器
FlowLayout 流式布局 也是面板默认的布局方式
把组件放在一排,从左到右开始排放,一行占满后,重新开启一行
面板默认流式布局是水平居中的
*/
//JPanel jPanel=new JPanel(new FlowLayout(FlowLayout.LEFT));//设置内容水平对齐方式
JPanel jPanel=new JPanel(new FlowLayout(FlowLayout.LEFT,10,30));//设置组件之间水平,垂直之间的距离
//创建一个按钮
JButton jButton=new JButton("按钮1");
JButton jButton1=new JButton("按钮2");
jPanel.add(jButton);
jPanel.add(jButton1);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new Demo2();
}
}
案例效果:
2.2边界布局(BorderLayout)
按照东、西、南、北、中放组件。(Window/Frame/Dialog的默认容器布局)BorderLayout布局管理器把容器分成5个区域:North,South,East,West和Center,每个区域只能放置一个组件。
package Panel;
import javax.swing.*;
import java.awt.*;
public class Demo3 extends JFrame {
public Demo3() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
//JPanel jPanel=new JPanel();
/*
边界布局:
BorderLayout
一共有五个区域,每个区域可以放置一个组件,并占满整个区域。
中间的区域是必须的。
添加组件时,可以指定组件的位置,如果没有指定位置,那么默认位置为中间。
*/
JPanel jPanel=new JPanel(new BorderLayout());
//创建一个按钮
JButton jButton=new JButton("按钮1");
JButton jButton1=new JButton("按钮2");
JButton jButton2=new JButton("按钮3");
JButton jButton3=new JButton("按钮4");
JButton jButton4=new JButton("按钮5");
jPanel.add(jButton,BorderLayout.NORTH);
jPanel.add(jButton1,BorderLayout.SOUTH);
jPanel.add(jButton2,BorderLayout.EAST);
jPanel.add(jButton3,BorderLayout.WEST);
jPanel.add(jButton4,BorderLayout.CENTER);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new Demo3();
}
}
案例效果:
2.3 网格布局(GridLayout)
使容器中各个组件呈网格状布局,平均占据容器的空间。
package Panel;
import javax.swing.*;
import java.awt.*;
public class Demo4 extends JFrame {
public Demo4() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
//JPanel jPanel=new JPanel();
/*
网格布局
GridLayout
网格就类似一个表格,可以设置行数和列数。
每个网格中只能放一个组件,占满整个区域。
从第一行开始摆放,第一行占满后,开始第二行
*/
JPanel jPanel=new JPanel(new GridLayout(2,2));
//添加按钮
JButton jButton=new JButton("按钮1");
JButton jButton1=new JButton("按钮2");
JButton jButton2=new JButton("按钮3");
JButton jButton3=new JButton("按钮4");
jPanel.add(jButton);
jPanel.add(jButton1);
jPanel.add(jButton2);
jPanel.add(jButton3);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new Demo4();
}
}
案例效果:
3.常用组件
标签(JLabel)
标签是容纳文本和图标的控件,通常用来在界面中标识别的控件。
构造函数:
JLabel()
创建一个空的标签
JLabel(String text)
创建一个带文本的标签
单行文本(JTextField)
JTextField的构造函数:
JTextField(int columns)
方法:
void setText(String text)
设置文本框中的文本
String getText()
获得文本框中的文本
package component;
import javax.swing.*;
import java.awt.*;
public class ComponentDemo1 extends JFrame {
public ComponentDemo1() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
JPanel jPanel=new JPanel();
jPanel.setBackground(Color.CYAN);//设置面板的背景颜色
JLabel jLabel=new JLabel("账号");
jLabel.setFont(new Font("楷体", Font.BOLD, 20));//设置字体
jLabel.setForeground(Color.BLACK);//设置字体颜色
JTextField jTextField=new JTextField(15);
jTextField.getText();//获得文本框中输入的内容
jPanel.add(jLabel);
jPanel.add(jTextField);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new ComponentDemo1();
}
}
案例效果:
多行文本框(JTextArea)
构造函数:
JTextArea(int rows, int columns) 创建一个指定行数和列数的空文本域
package component;
import javax.swing.*;
import java.awt.*;
public class ComponentDemo2 extends JFrame {
public ComponentDemo2() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
JPanel jPanel=new JPanel();
jPanel.setBackground(Color.CYAN);//设置面板的背景颜色
//创建一个多行文本框组件(文本域)
JTextArea jTextArea=new JTextArea(5,20);
jTextArea.setLineWrap(true);//强制换行
//带滚动条面板
JScrollPane jScrollPane=new JScrollPane(jTextArea);
jPanel.add(jScrollPane);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new ComponentDemo2();
}
}
案例效果:
密码框:JPasswordField
构造函数:
JPasswordField(String text)
JPasswordField(String text, int columns)
按钮(JButton)
构造方法:
JButton(String text)
创建一个带文本的标签
package component;
import javax.swing.*;
import java.awt.*;
public class ComponentDemo3 extends JFrame {
public ComponentDemo3() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
JPanel jPanel=new JPanel();
jPanel.setBackground(Color.CYAN);//设置面板的背景颜色
JLabel jLabel=new JLabel("密码");
JPasswordField jPasswordField=new JPasswordField(15);
char[] password=jPasswordField.getPassword();
JButton jButton=new JButton("登录");
jButton.setToolTipText("点击登录");
jPanel.add(jLabel);
jPanel.add(jPasswordField);
jPanel.add(jButton);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new ComponentDemo3();
}
}
案例效果:
Menu组件
package component;
import javax.swing.*;
import java.awt.*;
public class ComponentDemo4 extends JFrame {
public ComponentDemo4() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
JPanel jPanel=new JPanel();
jPanel.setBackground(Color.CYAN);//设置面板的背景颜色
//创建菜单栏组件
//菜单栏 菜单 菜单项
JMenuBar jMenuBar=new JMenuBar();//创建菜单栏
//创建菜单
JMenu jMenu1=new JMenu("文件");
JMenu jMenu2=new JMenu("编辑");
JMenu jMenu3=new JMenu("帮助");
//创建菜单项
JMenuItem jMenuItem1=new JMenuItem("新建");
JMenuItem jMenuItem2=new JMenuItem("保存");
JMenuItem jMenuItem3=new JMenuItem("剪切");
JMenuItem jMenuItem4=new JMenuItem("复制");
JMenuItem jMenuItem5=new JMenuItem("关于我们");
//把菜单项添加到菜单中
jMenu1.add(jMenuItem1);
jMenu1.add(jMenuItem2);
jMenu2.add(jMenuItem3);
jMenu2.add(jMenuItem4);
jMenu3.add(jMenuItem5);
//把菜单添加到菜单栏中
jMenuBar.add(jMenu1);
jMenuBar.add(jMenu2);
jMenuBar.add(jMenu3);
//把菜单栏添加到窗口中
this.setJMenuBar(jMenuBar);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
}
public static void main(String[] args) {
new ComponentDemo4();
}
}
案例效果:
4.时间处理
添加事件监听器
(
此处即为匿名类
)
按钮对象
.addActionListener(new ActionListener() {
//
事件处理
@Override
public void actionPerformed(ActionEvent e) {
执行操作
}
})
例如我们在常用组件中设计的登录界面,我们可以通过为按钮添加时间监听来检测其是否被点击,如果点击则会输出"按钮被点击了"。
package listener;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Demo1 extends JFrame {
public Demo1() throws HeadlessException {
this.setTitle("欢迎登录");//设置窗口标题
this.setSize(400, 400);//设置窗口大小
this.setResizable(false);//设置窗口大小是否可以调整
this.setLocationRelativeTo(null);//设置窗口居中
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时结束程序
//创建一个面板
JPanel jPanel=new JPanel();
jPanel.setBackground(Color.CYAN);//设置面板的背景颜色
JLabel jLabel=new JLabel("账号");
jLabel.setFont(new Font("楷体", Font.BOLD, 20));//设置字体
jLabel.setForeground(Color.BLACK);//设置字体颜色
JTextField jTextField=new JTextField(15);
jTextField.getText();//获得文本框中输入的内容
JButton jButton=new JButton("登录");
jPanel.add(jLabel);
jPanel.add(jTextField);
jPanel.add(jButton);
this.add(jPanel);//将面板添加到窗口上
this.setVisible(true);//启动窗口
//添加时间监听器
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被点击了");
}
});
jTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(jTextField.getText());
}
});
}
public static void main(String[] args) {
new Demo1();
}
}
案例效果:
案例分析:
通过输出我们可以得知按钮被点击了两次。
5.对话框
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 确定/取消
6.实际应用
通过图形界面的学习,我们可以利用提供的这些常用组件,时间处理,对话框来创建一个网络聊天室。
通过前面的网络编程我们可以得知想要通过网络进行消息的传递我们首先要创建一个客户端和一个服务器端。
具体代码如下:
服务器端
package chatroomserver;
import javax.swing.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ChatroomServer extends JFrame {
//创建集合来储存接收到的客户端
ArrayList<Socket> list=new ArrayList<>();
public ChatroomServer()
{
//创建服务器端
try {
ServerSocket serverSocket=new ServerSocket(9999);
System.out.println("服务器启动成功");
//设置循环,监听是否有客户端连接
while (true)
{
Socket socket=serverSocket.accept();
list.add(socket);
System.out.println("有客户端连接到服务器,连接的数量为:"+list.size());
//为每个连接服务器的客户端提供线程
new SocketThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器端启动失败");
}
}
//创建一个内部类,继承Thread,用来监听自己的客户端有没有发送消息
class SocketThread extends Thread
{
DataInputStream dataInputStream;
public SocketThread(Socket socket) throws IOException {
dataInputStream=new DataInputStream(socket.getInputStream());
}
@Override
public void run() {
while(true) {
try {
String msg = dataInputStream.readUTF();
System.out.println(msg);
//向不同的客户端发消息
//遍历Socket集合
for(Socket sockets:list)
{
DataOutputStream dataOutputStream=new DataOutputStream(sockets.getOutputStream());
dataOutputStream.writeUTF(msg);
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("客户端下线了");
}
}
}
}
}
接下来是客户端:
就想我们日常使用的QQ,微信一样,我们设计的网络聊天室需要一个登录界面和一个聊天界面
首先是登录界面
package ChatroomFrame;
import com.sun.org.apache.xerces.internal.impl.xpath.regex.Match;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.Socket;
public class Login extends JFrame {
public Login() throws HeadlessException {
this.setTitle("欢迎登录");
this.setSize(400,400);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jPanel=new JPanel(new GridLayout(4,1));
JPanel welcomejPanel=new JPanel(new FlowLayout(FlowLayout.CENTER));
JLabel welcomejLabel=new JLabel("欢迎登录");
welcomejPanel.add(welcomejLabel);
JPanel accountjPanel=new JPanel(new FlowLayout(FlowLayout.CENTER));
JLabel accountjLabel=new JLabel("账号");
accountjLabel.setFont(new Font("楷体", Font.BOLD, 20));
accountjLabel.setForeground(Color.BLACK);
JTextField jTextField=new JTextField(15);
accountjPanel.add(accountjLabel);
accountjPanel.add(jTextField);
JPanel passwordjPanel=new JPanel(new FlowLayout(FlowLayout.CENTER));
JLabel passwordjLabel=new JLabel("密码");
passwordjLabel.setFont(new Font("楷体", Font.BOLD, 20));
passwordjLabel.setForeground(Color.BLACK);
JPasswordField jPasswordField=new JPasswordField(15);
char[] password=jPasswordField.getPassword();
passwordjPanel.add(passwordjLabel);
passwordjPanel.add(jPasswordField);
JPanel loginjPanel1=new JPanel(new FlowLayout(FlowLayout.CENTER));
JPanel loginjPanel2=new JPanel(new GridLayout(1,2));
JButton loginjButton=new JButton("登录");
loginjPanel1.add(loginjButton);
JButton enrolljButton=new JButton("注册");
loginjPanel1.add(enrolljButton);
loginjPanel1.add(loginjPanel2);
jPanel.add(welcomejPanel);
jPanel.add(accountjPanel);
jPanel.add(passwordjPanel);
jPanel.add(loginjPanel1);
this.add(jPanel);
this.setVisible(true);
loginjButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String account=jTextField.getText();
String password=new String(jPasswordField.getPassword());
if(jTextField.getText().length()==0||password.length()==0){
JOptionPane.showMessageDialog(null, "账号或者密码不能为空", "警告", JOptionPane.WARNING_MESSAGE);
}
else if(!password.matches("[a-zA-Z0-9]{1,15}")){
JOptionPane.showMessageDialog(null, "账号密码只能由数字,字母组成", "警告", JOptionPane.WARNING_MESSAGE);
}
else
{
JOptionPane.showMessageDialog(null, "登录成功", "提示", JOptionPane.INFORMATION_MESSAGE);
try {
Socket socket=new Socket("127.0.0.1", 9999);
new Chat(account,socket);
dispose();//释放当前的窗口
} catch (IOException ioException) {
JOptionPane.showMessageDialog(null, "与服务器端连接失败","警告",JOptionPane.WARNING_MESSAGE);
}
}
}
});
}
}
其次是聊天界面
package ChatroomFrame;
import javax.swing.*;
import javax.xml.crypto.Data;
import java.awt.*;
import java.awt.event.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Chat extends JFrame {
JTextArea jTextArea;
public Chat(String account, Socket socket) throws HeadlessException, IOException {
DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream());
this.setTitle("欢迎"+account+"来到聊天室");
this.setSize(400,400);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//点击关闭按钮时什么都不做
JPanel jPanel=new JPanel(new BorderLayout());
jTextArea=new JTextArea();
jTextArea.setEditable(false);
jTextArea.setLineWrap(true);
JScrollPane jScrollPane=new JScrollPane(jTextArea);
jPanel.add(jScrollPane);
JPanel sendjPanel=new JPanel(new FlowLayout());
jPanel.add(sendjPanel,BorderLayout.SOUTH);
JTextArea jTextArea1=new JTextArea(5,25);
jTextArea1.setLineWrap(true);
JScrollPane jScrollPane1=new JScrollPane(jTextArea1);
sendjPanel.add(jScrollPane1);
JButton sendjButton=new JButton("发送");
sendjPanel.add(sendjButton);
//创建线程用来接受服务器端的消息
new ChatThread(socket).start();
this.add(jPanel);
this.setVisible(true);
//为发送按钮添加时间监听
sendjButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//获取发送的内容
String message=jTextArea1.getText();
if(message.length()==0){
JOptionPane.showMessageDialog(null, "发送栏不能为空","提示",JOptionPane.WARNING_MESSAGE);
}
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
String str=format.format(new Date());
String msg=account+" "+str+"\n";
msg+=message;
try {
dataOutputStream.writeUTF(msg);
jTextArea1.setText(" ");//清空发送框
} catch (IOException ioException) {
JOptionPane.showMessageDialog(null, "与服务器端连接失败,请检查连接","提示",JOptionPane.WARNING_MESSAGE);
}
}
});
//为窗口添加时间监听
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
int result = JOptionPane.showConfirmDialog(null, "你确定要退出聊天吗","操作提示",JOptionPane.OK_CANCEL_OPTION);
if(result==0){
new Login();
dispose();
}
}
});
}
//创建一个内部类,继承Thread,用来监听服务器端有没有发送消息
class ChatThread extends Thread{
DataInputStream dataInputStream;
public ChatThread(Socket socket) throws IOException {
dataInputStream=new DataInputStream(socket.getInputStream());
}
@Override
public void run() {
while(true)
{
try {
String msg=dataInputStream.readUTF();
jTextArea.append(msg+"\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
案例效果: