基于Swing的图形化用户界面——学习笔记
前言:WindowBuilder它不香吗?(划掉)
由于学Java,还是老老实实用代码实现吧,布局布的我心态爆炸,还不如使用空布局(正如老师所说:真正的高手往往都是手中无剑,心中有剑,hhh)
好吧,废话不多说,还是切入正题吧!
前几次作业感觉布局还好,都不是特别麻烦,但是这次作业,如果要想界面做的比较好看的话,就必须能够很好的掌握布局。。。。。。(尤其是网格包布局 和 空布局)
康康题目吧:
————————————————————————————————————————————
1. 现有Happy聊天室登录界面,请进行合理的事件处理,使得当点击“登录”按钮时进行如下逻辑判断:
(1) 如果用户名或密码为空,则提示:“请输入用户名和密码!”;
(2) 如果用户名为zhangsan,密码为123456,则弹出消息窗口提示:“恭喜你,成功登录!”,否则提示:“你的输入有误,请重新输入!”。
提示:弹出消息窗口语法: JOptionPane.showMessageDialog(null,“请输入用户名和密码!”);
————————————————————————————————————————————
这道题还是相对于来讲,比较容易布局的了
我是整体用的垂直盒布局,其中每行采用水平盒布局,然后稍微对事件做下处理就出来了
界面截图:
下面给出界面实现代码(只在这题给出MainClass代码,下面不再重复,只需new下这个类的对象,调用display方法即可)==
Login类
package swing.test3;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Login {
JFrame jf=new JFrame();
JLabel userName=new JLabel("用户名:",10);
JLabel password=new JLabel("密 码:",10);
JTextField userTxt=new JTextField(20);
JPasswordField passwordTxt=new JPasswordField(20);
JButton loginBtn=new JButton("登录");
JButton registerBtn=new JButton("注册");
Container con; //内容面板 ,整体用垂直盒布局,每行用水平盒布局
JPanel pane1=new JPanel(); //第一行
JPanel pane2=new JPanel(); //第二行
JPanel pane3=new JPanel(); //第三行
BoxLayout boxlayout2=new BoxLayout(pane1,BoxLayout.X_AXIS);
BoxLayout boxlayout3=new BoxLayout(pane2,BoxLayout.X_AXIS);
BoxLayout boxlayout4=new BoxLayout(pane3,BoxLayout.X_AXIS);
LoginListener handler=new LoginListener();
public void display() {
loginBtn.addActionListener(handler);
pane1.add(userName);
pane1.add(userTxt);
pane2.add(password);
pane2.add(passwordTxt);
pane3.add(loginBtn);
pane3.add(registerBtn);
con=jf.getContentPane();
con.setLayout(new BoxLayout(con,BoxLayout.Y_AXIS));
con.add(pane1);
con.add(pane2);
con.add(pane3);
jf.setVisible(true);
jf.setLocationRelativeTo(null);
jf.setSize(400,200);
}
private class LoginListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
String username=userTxt.getText();
String password=passwordTxt.getText();
if(username.trim().equals("")||password.trim().equals("")) {
JOptionPane.showMessageDialog(null, "请输入用户名和密码!");
}
else if(username.equals("zhangsan")||password.equals("123456")) {
JOptionPane.showMessageDialog(null, "恭喜你,成功登录!");
}
else {
JOptionPane.showMessageDialog(null, "你的输入有误,请重新输入!");
}
}
}
}
MainClass 类
package swing.test3;
import java.awt.*;
import javax.swing.*;
public class MainClass {
public static void main(String args[]) {
Login test=new Login();
test.display();
}
}
————————————————————————————————————————————
2. 现有Motel168客户住房登记界面,请进行合理的事件处理实现以下效果:
(1) 当点击“Cancel”按钮时,退出整个应用程序;
(2) 当点击窗口右上角的“关闭”按钮时,退出整个应用程序;
(3) 当点击“OK”按钮时,判断客户名和客户ID是否为空,如果为空,则弹出消息框提示“请输入姓名和ID!”,否则,弹出消息框显示客户订房信息,消息格式为:
————————————————————————————————————————————
这道题就感觉有点难度了,关键开始的简单布局无法使界面变得比较好看了,于是就想到用GridBagLayout布局(即:网格包布局)
关于网格包布局需要注意一些实现方法:
网格包布局所管理的每个组件都与GridBagConstraints类的对象有关
通过调用:
.setConstraints(arg1,arg2);
其中arg1为你指定的组件名 ,arg2位GridBagConstraints对象
其中对于组件大小,位置设置还有方法:
方法 | 作用 |
---|---|
gridx,gridy | 指定组件左上角在网格中的行与列 |
gridwidth,gridheight | 组件显示区域所占的列数和行数 |
fill(主要包括.HORIZONTAL(组件横向填充,高度不变), .VERTICAL(列向填充,宽度不变), .BOTH(横向、纵向均填充)) | 组件填充网格的方式 |
insets(c.insets=new Insets(top,left,bottom,right) | 组件间的填充,也就是组件之间的距离(其中四个参数英文也很好懂,分别为:上部,左部,下部,右部) |
… | … |
界面截图:
至于事件处理,还是比较简单的,稍微注意下就行,具体见代码:
package swing.test3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class CustomerRegistration {
JFrame jf=new JFrame("客户住房登记");
JLabel userName=new JLabel("客户姓名");
JTextField userNameText=new JTextField(20);
JLabel userID=new JLabel("客 户 ID");
JTextField userIDText=new JTextField(20);
JLabel country=new JLabel("国 家");
JTextField countryText=new JTextField(20);
JLabel phoneNumber=new JLabel("电 话");
JTextField phoneText=new JTextField(20);
JLabel code=new JLabel("邮区代码");
JTextField codeText=new JTextField(20);
JLabel date=new JLabel("入住时间");
JTextField dateText=new JTextField(20);
JLabel roomNumber=new JLabel("房 间 号");
JComboBox comboBoxRoomID=new JComboBox();
Vector<String> roomIDVector=new Vector<String>();
JLabel roomType=new JLabel("房间类型 ");
JComboBox comboBoxRoomType=new JComboBox();
Vector<String>roomTypeVector=new Vector<String>();
JButton queryBtn=new JButton("查询房间");
JButton ok=new JButton("OK");
JButton cancel=new JButton("Cancel");
JPanel pane=new JPanel();
Container con=new Container();
//注册事件
CancelSolution cancelSolution=new CancelSolution();
WindowClosedSolution windowClosedSolution =new WindowClosedSolution();
RoomIdSolution roomIdSolution =new RoomIdSolution();
RoomTypeSolution roomTypeSolution =new RoomTypeSolution();
OKSolution okSolution =new OKSolution();
//客户的房间号和房间类型
String roomIdStr=new String();
String roomTypeStr=new String();
public void display() {
cancel.addActionListener(cancelSolution);
ok.addActionListener(okSolution);
comboBoxRoomID.addItemListener(roomIdSolution);
comboBoxRoomType.addItemListener(roomTypeSolution);
roomIDVector.add("101");
roomIDVector.add("102");
roomIDVector.add("103");
roomIDVector.add("104");
roomIDVector.add("105");
for(int i=0;i<roomIDVector.size();i++) {
comboBoxRoomID.addItem(roomIDVector.get(i));
}
roomTypeVector.add("普通单人间");
roomTypeVector.add("普通双人间");
roomTypeVector.add("豪华单人间");
roomTypeVector.add("豪华双人间");
for(int i=0;i<roomTypeVector.size();i++) {
comboBoxRoomType.addItem(roomTypeVector.get(i));
}
jf.setVisible(true);
jf.setLocationRelativeTo(null);
jf.setSize(400,400);
GridBagLayout gridbag=new GridBagLayout();
GridBagConstraints c=new GridBagConstraints();
c.fill=GridBagConstraints.BOTH; //使组件完全填满其显示部分
c.insets=new Insets(1,1,5,5); //设置组件之间距离,第一个参数:上,第二个参数:左,第三个参数:下,第四个参数:右
c.gridx=0;
c.gridy=1;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(userName,c);
c.gridx=5;
c.gridy=1;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(userNameText, c);
c.gridx=0;
c.gridy=2;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(userID, c);
c.gridx=5;
c.gridy=2;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(userIDText, c);
c.gridx=0;
c.gridy=3;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(country, c);
c.gridx=5;
c.gridy=3;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(countryText, c);
c.gridx=0;
c.gridy=4;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(phoneNumber, c);
c.gridx=5;
c.gridy=4;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(phoneText, c);
c.gridx=0;
c.gridy=5;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(code, c);
c.gridx=5;
c.gridy=5;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(codeText, c);
c.gridx=0;
c.gridy=6;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(date, c);
c.gridx=5;
c.gridy=6;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(dateText, c);
c.gridx=0;
c.gridy=7;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(roomNumber, c);
c.gridx=5;
c.gridy=7;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(comboBoxRoomID, c);
c.gridx=0;
c.gridy=8;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(roomType, c);
c.gridx=5;
c.gridy=8;
c.gridwidth=20;
c.gridheight=1;
gridbag.setConstraints(comboBoxRoomType, c);
c.gridx=0;
c.gridy=9;
c.gridwidth=2;
c.gridheight=1;
gridbag.setConstraints(queryBtn, c);
c.gridx=5;
c.gridy=9;
gridbag.setConstraints(ok, c);
c.gridx=10;
c.gridy=9;
c.gridwidth=GridBagConstraints.REMAINDER;
gridbag.setConstraints(cancel, c);
con=jf.getContentPane();
con.setLayout(gridbag);
con.add(userName);
con.add(userNameText);
con.add(userID);
con.add(userIDText);
con.add(country);
con.add(countryText);
con.add(phoneNumber);
con.add(phoneText);
con.add(code);
con.add(codeText);
con.add(date);
con.add(dateText);
con.add(roomNumber);
con.add(comboBoxRoomID);
con.add(roomType);
con.add(comboBoxRoomType);
con.add(queryBtn);
con.add(ok);
con.add(cancel);
}
//取消按钮事件实现
private class CancelSolution implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
//关闭窗口事件实现
private class WindowClosedSolution extends WindowAdapter{
public void windowClosed(WindowEvent e) {
System.exit(0);
}
}
//ok按钮事件实现
private class OKSolution implements ActionListener{
public void actionPerformed(ActionEvent e) {
String userNameTxt=userNameText.getText();
String userIdTxt =userIDText.getText();
if(userNameTxt.trim().equals("")||userIdTxt.trim().equals("")) {
JOptionPane.showMessageDialog(null, "请输入姓名和ID!");
}
else {
JOptionPane.showMessageDialog(null,"客户:"+userNameTxt+" 所订房间:"+roomIdStr);
}
}
}
//房间号选择事件实现
private class RoomIdSolution implements ItemListener{
public void itemStateChanged(ItemEvent e) {
roomIdStr=comboBoxRoomID.getSelectedItem().toString();
}
}
//房间类型选择事件实现(虽然这道题不要求)
private class RoomTypeSolution implements ItemListener{
public void itemStateChanged(ItemEvent e) {
roomTypeStr=comboBoxRoomType.getSelectedItem().toString();
}
}
}
————————————————————————————————————————————
3. 编程实现如下图所示聊天窗口:
————————————————————————————————————————————
这道题有变得复杂点了,我觉得用网格包布局仍然比较麻烦,于是就用的空布局,那个设置位置给我搞的
首先还是要注意空布局一些基本要求
1、设置JFrame为空布局(不然默认是BorderLayout(边界布局))
.setLayout(null);
2、手工设置组件大小和位置:
方法 | 作用 |
---|---|
setLocation(arg1,arg2) | 其中第一个参数为:组件左上角所在x坐标,第二个参数为:组件左上角所在y坐标 |
setSize(arg1,arg2) | 其中第一个参数为组件的宽度,第二个参数为组件的高度 |
setBounds(arg1,arg2,arg3,arg4) | 对前面两个方法的合并,四个参数分别为:组件左上角所在x坐标,组件左上角所在y坐标,组件的宽度,组件的高度 |
由于作业没对事件做要求,所以事件没有做处理,后面有时间可以玩玩。。。
界面截图:
具体见代码:
package swing.test3;
import java.awt.*;
import javax.swing.*;
import java.util.*;
public class HappyChat {
JFrame jf=new JFrame("Happy聊天室");
JLabel label=new JLabel("欢迎进入Happy聊天室!!");
JTextArea mainTextArea=new JTextArea(30,5);
JTextField editText=new JTextField(50);
JTextArea announcement=new JTextArea("----------- 公告 -----------");
String[] object={"小花","水月","灵儿"};
JList chatObjectList =new JList(object);
JScrollPane scrollPane=new JScrollPane(chatObjectList);
JLabel to=new JLabel("To:");
JComboBox objectComboBox=new JComboBox();
JButton sentBtn=new JButton("发送消息");
JButton exitBtn=new JButton("退出聊天室");
//布局:采用空布局
Container con;
public void display() {
Vector<String>objectVector =new Vector<String>();
objectVector.add("小花");
objectVector.add("水月");
objectVector.add("灵儿");
jf.setLayout(null);
jf.setVisible(true);
jf.setLocationRelativeTo(null);
jf.setSize(580,500);
label.setLocation(200,0);
label.setSize(200,50);
mainTextArea.setEditable(false);
mainTextArea.setLocation(20,55);
mainTextArea.setSize(400,300);
editText.setLocation(20,360);
editText.setSize(400,25);
announcement.setEditable(false);
announcement.setLocation(425,55);
announcement.setSize(130,100);
chatObjectList.setLocation(425,160);
chatObjectList.setSize(130,220);
to.setLocation(100,400);
to.setSize(100,25);
for(int i=0;i<objectVector.size();i++) {
objectComboBox.addItem(objectVector.get(i));
}
objectComboBox.setLocation(150,400);
objectComboBox.setSize(100,25);
sentBtn.setLocation(300,400);
sentBtn.setSize(100,25);
exitBtn.setLocation(450,400);
exitBtn.setSize(100,25);
con=jf.getContentPane();
con.setBackground(Color.PINK);
con.add(label);
con.add(mainTextArea);
con.add(editText);
con.add(announcement);
con.add(chatObjectList);
con.add(to);
con.add(objectComboBox);
con.add(sentBtn);
con.add(exitBtn);
}
}
————————————————————————————————————————————
4. 使用Java AWT/Swing开发一个简易版的记事本,要求提供菜单栏。
————————————————————————————————————————————
这题还是比较简单的,至少不要用尽心思去想怎么布局好看,只需提供下菜单栏,和一些基本的菜单项即可
这里没有对很多事件进行处理,只对退出事件进行了下处理,以后有时间完善
稍微复习下菜单栏相关知识:
至于它们的从属关系(可能说法不太准确,但是我觉得很好理解)
JMenuBar ----> JMenu ----> JMenuItem
其中至于菜单框的加法,与组件加法有点不同,是直接在JFrame对象上加
.setJMenuBar();
对于菜单栏中的那些分割符,得用到:
.addSeparator();
界面截图(这里可能不太清楚,因为有些菜单栏中的内容看不到):
于是代码如下:
package swing.test3;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JavaTxt {
JFrame jf=new JFrame("记事本");
JMenuBar menuBar=new JMenuBar();
JMenu fileMenu=new JMenu("文件(F)");
JMenu editMenu=new JMenu("编辑(E)");
JMenu fontMenu=new JMenu("格式(O)");
JMenu seeMenu=new JMenu("查看(V)");
JMenu help=new JMenu("帮助(H)");
JMenuItem fileItem1=new JMenuItem("新建(N) Ctrl+N");
JMenuItem fileItem2=new JMenuItem("新窗口(W) Ctrl+Shift+N");
JMenuItem fileItem3=new JMenuItem("打开(O)... Ctrl+O");
JMenuItem fileItem4=new JMenuItem("保存(S) Ctrl+S");
JMenuItem fileItem5=new JMenuItem("另存为(A)... Ctrl+Shift+S");
JMenuItem fileItem6=new JMenuItem("页面设置(U)... ");
JMenuItem fileItem7=new JMenuItem("打印(O)... Ctrl+O");
JMenuItem fileItem8=new JMenuItem("退出(X) ");
JMenuItem editItem1=new JMenuItem("撤销(U) Ctrl+Z");
JMenuItem editItem2=new JMenuItem("剪切(T) Ctrl+X");
JMenuItem editItem3=new JMenuItem("复制(C) Ctrl+C");
JMenuItem editItem4=new JMenuItem("粘贴(P) Ctrl+V");
JMenuItem editItem5=new JMenuItem("删除(L) Del");
JMenuItem fontItem1=new JMenuItem("自动换行(W)");
JMenuItem fontItem2=new JMenuItem("字体(F)...");
JMenuItem seeItem1=new JMenuItem("缩放(Z)");
JMenuItem seeItem2=new JMenuItem("状态栏(S)");
JMenuItem helpItem1=new JMenuItem("查看帮助(H)");
JMenuItem helpItem2=new JMenuItem("发送反馈(F)");
JMenuItem helpItem3=new JMenuItem("关于记事本(A)");
JTextArea text=new JTextArea();
Container con=jf.getContentPane();
JPanel pane=new JPanel();
exitHanlder exit=new exitHanlder();
public void display() {
jf.setVisible(true);
jf.setLocationRelativeTo(null);
jf.setSize(1000,800);
jf.setJMenuBar(menuBar);
fileMenu.add(fileItem1);
fileMenu.add(fileItem2);
fileMenu.add(fileItem3);
fileMenu.add(fileItem4);
fileMenu.add(fileItem5);
fileMenu.addSeparator();
fileMenu.add(fileItem6);
fileMenu.add(fileItem7);
fileMenu.addSeparator();
fileMenu.add(fileItem8);
fileItem8.addActionListener(exit);
editMenu.add(editItem1);
editMenu.addSeparator();
editMenu.add(editItem2);
editMenu.add(editItem3);
editMenu.add(editItem4);
editMenu.add(editItem5);
fontMenu.add(fontItem1);
fontMenu.add(fontItem2);
seeMenu.add(seeItem1);
seeMenu.add(seeItem2);
help.add(helpItem1);
help.add(helpItem2);
help.addSeparator();
help.add(helpItem3);
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(fontMenu);
menuBar.add(seeMenu);
menuBar.add(help);
con.add(text);
}
//这里只给退出注册了事件,其他功能有待完善
private class exitHanlder implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}
做个界面就做的我。。。。。。
休息会,gun去做题吧