就是个人学习的笔记,按照下面的Demo一个一个复制粘贴跑起来大概就会使用Swing了
Swing
- Swing 是一个为Java设计的GUI工具包。
Swing开发的图形界面比AWT更加轻量级,使用100%的java开发不再依赖本地图形界面可以在所有平台保持相同的运行效果。
优点:
- Swing组建不再依赖本地平台GUI无需采用各种平台的GUI交集,因此Swing提供大量图形界面组件
- Swing组建不再依赖本地GUI不会产生平台相关bug
- Swing组件在各种平台上运行可以保证具有相同的图形界面外观
- Swing采用MVC(model-view-controller,模型-视图-控制器)设计模式,模型用于维护组件的状态,视图是组件的可视化表现,控制器用于控制各个事件,组件做出怎么样的响应。模型发生改变,它通知所有依赖它的视图,视图根据模型数据来更新自己。
一.快速开始
- JFrame是GUI中的容器
- JButton是最常见的组件- 按钮
注意:
f.setVisible(true);
会对所有的组件进行渲染,所以一定要放在最后面
public static void main(String[] args) {
// 主窗体
JFrame f = new JFrame("LoL");
// 主窗体设置大小
f.setSize(400, 300);
// 主窗体设置位置
f.setLocation(200, 200);
// 主窗体中的组件设置为绝对定位
f.setLayout(null);
// 按钮组件
JButton b = new JButton("一键秒对方基地挂");
// 同时设置组件的大小和位置
b.setBounds(50, 50, 280, 30);
// 把按钮加入到主窗体中
f.add(b);
// 关闭窗体的时候,退出程序
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 让窗体变得可见
f.setVisible(true);
}
结果
练习-在上次关闭位置启动窗口
比如这次使用这个窗口,导致窗口被移动到了右下角。 关闭这个窗口,下一次再启动的时候,就会自动出现在右下角。
思路提示:
- 启动一个线程,每个100毫秒读取当前的位置信息,保存在文件中,比如location.txt文件。
- 启动的时候,从这个文件中读取位置信息,如果是空的,就使用默认位置,如果不是空的,就把位置信息设置在窗口上。
- 读取位置信息的办法: f.getX() 读取横坐标信息,f.getY()读取纵坐标信息。
注: 这个练习要求使用多线程
来完成。 还有另一个思路来完成,就是使用监听器
,因为刚开始学习GUI,还没有掌握监听器的使用,所以暂时使用多线程来完成这个功能。
public class TestGUI {
public static void main(String[] args) {
//classPath下面创建名为location.txt的文件用户保存窗口坐标
String fileName = "location.txt";
String data = readClassPathFile(fileName);
if (StringUtils.isEmpty(data)) {
data = writeLocation(null, data);
}
JSONObject location = JSONObject.parseObject(data);
// 主窗体
JFrame f = new JFrame("LoL");
// 主窗体设置大小
f.setSize(400, 300);
// 主窗体设置位置
f.setLocation(location.getInteger("x"), location.getInteger("y"));
// 主窗体中的组件设置为绝对定位
f.setLayout(null);
// 按钮组件
JButton b = new JButton("一键秒对方基地挂");
// 设置按钮组件的大小和位置
b.setBounds(50, 50, 280, 30);
// 把按钮加入到主窗体中
f.add(b);
// 关闭窗体的时候,退出程序
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 让窗体变得可见
f.setVisible(true);
//异步保存当前窗口坐标
new Thread(() -> {
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(1500);
writeLocation(f, fileName);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 写入窗口坐标到clpassPath下面的文件
* @param f
* @param fileName
*/
public static String writeLocation(JFrame f, String fileName) {
JSONObject json = new JSONObject();
if (f == null) {
json.put("x", "200");
json.put("y", "200");
System.out.println("初始坐标=>" + json);
} else {
json.put("x", f.getX());
json.put("y", f.getY());
System.out.println("当前坐标=>" + json);
writeClassPathFile(fileName, json.toJSONString());
}
return json.toJSONString();
}
/**
* 读取classPath下面的文件并转换成字符串
* @param fileName
* @return
*/
public static String readClassPathFile(String fileName) {
StringBuilder sb = new StringBuilder();
String content = null;
try (
//读取classPath下面文件流
InputStream in = TestGUI.class.getClassLoader().getResourceAsStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
) {
while ((content = br.readLine()) != null) {
sb.append(content);
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
/**
* 向classPath下的文件写入指定内容
* @param fileName
* @return
*/
public static boolean writeClassPathFile(String fileName, String data) {
URL url = TestGUI.class.getClassLoader().getResource(fileName);
File file = new File(url.getFile());
try (
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
) {
bw.write(data);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
二.事件监听
关键字 | 简介 |
---|---|
ActionListener | 按钮监听 |
KeyListener | 键盘监听 |
MouseListener | 鼠标监听 |
Adapter | 适配器 |
2.1.按钮监听
创建一个匿名类实现ActionListener接口,当按钮被点击时,actionPerformed方法就会被调用
- 在本例中,使用
ActionListener
监听按钮点击使用,通过点击按钮控制图片显示和隐藏
public static void main(String[] args) {
JFrame jFrame = new JFrame("LoL");
jFrame.setSize(400, 300);
jFrame.setLocation(580, 200);
jFrame.setLayout(null);
final JLabel jLabel = new JLabel();
String imgPath = "e:/data/gareen.jpg";
ImageIcon imageIcon = new ImageIcon(imgPath);
jLabel.setIcon(imageIcon);
jLabel.setBounds(50, 50, imageIcon.getIconWidth(), imageIcon.getIconHeight());
JButton button = new JButton("隐藏图片");
button.setBounds(150, 200, 100, 30);
//原子性保存显示和隐藏状态
AtomicBoolean isHide = new AtomicBoolean(false);
// 给按钮 增加 监听
button.addActionListener((e) -> {
//按钮显示文本
String txt = isHide.get() ? "显示图片" : "隐藏图片";
//切换状态
isHide.set(!isHide.get());
//设置显示状态 true显示 /false隐藏
jLabel.setVisible(isHide.get());
//设置按钮文本
button.setText(txt);
});
jFrame.add(jLabel);
jFrame.add(button);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
}
2.2.键盘监听
键盘监听器: KeyListener
- keyPressed 代表 键被按下
- keyReleased 代表 键被弹起
- keyTyped 代表 一个按下弹起的组合动作
KeyEvent.getKeyCode()
可以获取当前点下了哪个键
- 在本例中,使用KeyListener监听键盘被按下动作,当按下键盘的上下左右时窗口会进行对应移动
- 提示:keyCode与方向的对应关系38 上,40 下,37 左,39 右
public static void main(String[] args) {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 200);
frame.setLayout(null);
final JLabel label = new JLabel();
String imgPath = "e:/data/gareen.jpg";
ImageIcon imageIcon = new ImageIcon(imgPath);
label.setIcon(imageIcon);
label.setBounds(50, 50, imageIcon.getIconWidth(), imageIcon.getIconHeight());
// 增加键盘监听
frame.addKeyListener(new KeyListener() {
// 键被弹起
@Override
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased=>" + e);
}
//键被按下时控制窗口坐标
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 38) {
// 38代表按下了 “上键”
// 图片向右移动 (窗口x坐标不变,y坐标减少)
frame.setLocation(frame.getX(), frame.getY() - 10);
} else if (e.getKeyCode() == 40) {
//40代表按下了 “下键”
// 图片向右移动 (窗口x坐标不变,y坐标增加)
frame.setLocation(frame.getX(), frame.getY() + 10);
} else if (e.getKeyCode() == 37) {
// 37代表按下了 “左键”
// 图片向左移动 (窗口y坐标不变,x坐标减少)
frame.setLocation(frame.getX() - 10, frame.getY());
} else if (e.getKeyCode() == 39) {
// 39代表按下了 “右键”
// 图片向右移动 (窗口y坐标不变,x坐标增加)
frame.setLocation(frame.getX() + 10, frame.getY());
}
}
// 一个按下弹起的组合动作
@Override
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped=>" + e);
}
});
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
2.3.鼠标监听
MouseListener 鼠标监听器
- mouseReleased 鼠标释放
- mousePressed 鼠标按下
- mouseExited 鼠标退出
- mouseEntered 鼠标进入
- mouseClicked 鼠标点击
在本例中,使用mouseEntered,当鼠标进入图片的时候,图片就会移动位置
public static void main(String[] args) {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 200);
frame.setLayout(null);
final JLabel label = new JLabel();
String imgPath = "e:/data/gareen.jpg";
ImageIcon imageIcon = new ImageIcon(imgPath);
label.setIcon(imageIcon);
label.setBounds(50, 50, imageIcon.getIconWidth(), imageIcon.getIconHeight());
label.addMouseListener(new MouseListener() {
// 释放鼠标
@Override
public void mouseReleased(MouseEvent e) {
}
// 按下鼠标
@Override
public void mousePressed(MouseEvent e) {
}
// 鼠标退出
@Override
public void mouseExited(MouseEvent e) {
}
// 鼠标进入
@Override
public void mouseEntered(MouseEvent e) {
Random r = new Random();
int x = r.nextInt(frame.getWidth() - label.getWidth());
int y = r.nextInt(frame.getHeight() - label.getHeight());
label.setLocation(x, y);
}
// 按下释放组合动作为点击鼠标
@Override
public void mouseClicked(MouseEvent e) {
}
});
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
2.4.适配器
这里以MouseAdapter 鼠标监听适配器为例,一般说来在写监听器的时候,会实现MouseListener接口
。
但是MouseListener
接口里面有很多方法都没有用到,比如mouseReleased ,mousePressed,mouseExited等等。
- 这个时候就可以使用
鼠标监听适配器MouseAdapter
,只需要重写必要的方法即可。
在本例中,使用MouseAdapter只重写了mouseEntered方法,当鼠标进入图片的时候,图片就会移动位置
public static void main(String[] args) {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 200);
frame.setLayout(null);
final JLabel label = new JLabel();
String imgPath = "e:/data/gareen.jpg";
ImageIcon imageIcon = new ImageIcon(imgPath);
label.setIcon(imageIcon);
label.setBounds(50, 50, imageIcon.getIconWidth(), imageIcon.getIconHeight());
// MouseAdapter 适配器,只需要重写用到的方法,没有用到的就不用写了
label.addMouseListener(new MouseAdapter() {
// 只有mouseEntered用到了
@Override
public void mouseEntered(MouseEvent e) {
Random r = new Random();
int x = r.nextInt(frame.getWidth() - label.getWidth());
int y = r.nextInt(frame.getHeight() - label.getHeight());
label.setLocation(x, y);
}
});
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
三.容器
java的图形界面中,容器
是用来存放按钮
,输入框
等组件的。
- 窗体型容器有两个,一个是
JFrame
,一个是JDialog
3.1.JFrame
JFrame是最常用的窗体型容器,默认
在右上角有最大化最小化
按钮
public static void main(String[] args) {
//普通的窗体,带最大和最小化按钮
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
JButton btn = new JButton("一键秒对方基地挂");
btn .setBounds(50, 50, 280, 30);
frame.add(btn );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
3.2.JDialog
JDialog也是窗体型容器,右上角没有最大和最小化按钮
,通常做为弹窗
来使用
public static void main(String[] args) {
//普通的窗体,带最大和最小化按钮,而对话框却不带
JDialog dialog = new JDialog();
dialog .setTitle("LOL");
dialog .setSize(400, 300);
dialog .setLocation(200, 200);
dialog .setLayout(null);
JButton btn = new JButton("一键秒对方基地挂");
btn .setBounds(50, 50, 280, 30);
dialog .add(btn );
dialog .setVisible(true);
}
3.3.模态JDialog+锁定窗体大小
当一个对话框被设置为模态的时候,其背后
的父窗体,是不能被激活的,除非该对话框被关闭
通过调用方法
setResizable(false)
; 做到窗体大小不可变化、默认为true,不锁定窗口大小
本例是一个JFrame,上面有一个按钮,文字是 “打开一个模态况”。 点击该按钮后,随即打开一个模态窗口。 在这个模态窗口中有一个按钮,文本是 “锁定大小”, 点击后,这个模态窗口的大小就被锁定住,不能改变。 再次点击,就回复能够改变大小
public static void main(String[] args) {
JFrame frame = new JFrame("外部窗体");
frame.setSize(800, 600);
frame.setLocation(100, 100);
frame.setLayout(null);
JButton button1 = new JButton("打开一个模态框");
button1.setBounds(200, 200, 280, 30);
frame.add(button1);
button1.addActionListener((e) -> {
// 根据外部窗体实例化JDialog
JDialog dialog = new JDialog();
// 设置为模态
dialog.setModal(true);
dialog.setTitle("模态的对话框");
dialog.setSize(400, 300);
dialog.setLocation(200, 200);
dialog.setLayout(null);
JButton button2 = new JButton("锁定大小");
button2.setBounds(50, 50, 280, 30);
dialog.add(button2);
AtomicBoolean aBoolean = new AtomicBoolean(true);
button2.addActionListener(e2 -> {
aBoolean.set(!aBoolean.get());
button2.setText(aBoolean.get()?"锁定大小" : "解锁大小");
//通过调用方法 setResizable(false); 做到窗体大小不可变化
dialog.setResizable(aBoolean.get());//默认为true,不锁定大小
});
dialog.setVisible(true);
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
四.常见的布局器
布局器是用在容器上
的。 用来决定容器上的组件摆放的位置和大小
- 绝对定位
- FlowLayout
- BorderLayout
- GridLayout
- setPreferredSize
- CardLayout
4.1.绝对定位
绝对定位就是指不使用布局器
,组件的位置
和大小
需要单独指定
@Test
public void absolute_positioning() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
// 设置布局器为null,即进行绝对定位,容器上的组件都需要指定位置和大小
frame.setLayout(null);
JButton b1 = new JButton("英雄1");
// 指定位置和大小
b1.setBounds(50, 50, 80, 30);
JButton b2 = new JButton("英雄2");
b2.setBounds(150, 50, 80, 30);
JButton b3 = new JButton("英雄3");
b3.setBounds(250, 50, 80, 30);
// 没有指定位置和大小,不会出现在容器上
JButton b4 = new JButton("英雄3");
frame.add(b1);
frame.add(b2);
frame.add(b3);
// b4没有指定位置和大小,不会出现在容器上
frame.add(b4);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
4.2.FlowLayout
设置布局器为FlowLayout(顺序布局器)
:容器上的组件水平摆放
加入到容器即可,(无需单独指定大小和位置
)
@Test
public void FlowLayout() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
// 设置布局器为FlowLayerout=>容器上的组件水平摆放
frame.setLayout(new FlowLayout());
JButton b1 = new JButton("英雄1");
JButton b2 = new JButton("英雄2");
JButton b3 = new JButton("英雄3");
// 加入到容器即可,无需单独指定大小和位置
frame.add(b1);
frame.add(b2);
frame.add(b3);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
4.3.BorderLayout
设置布局器为BorderLayout:容器上的组件按照上北 下南 左西 右东 中
的顺序摆放
@Test
public void BorderLayout() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
// 设置布局器为BorderLayerout=>容器上的组件按照上北下南左西右东中的顺序摆放
frame.setLayout(new BorderLayout());
JButton northB = new JButton("洪七");
JButton southB = new JButton("段智兴");
JButton westB = new JButton("欧阳锋");
JButton eastB = new JButton("黄药师");
JButton centerB = new JButton("周伯通");
// 加入到容器的时候,需要指定位置
frame.add(northB, BorderLayout.NORTH);//上北
frame.add(southB, BorderLayout.SOUTH);//下南
frame.add(westB, BorderLayout.WEST);//左西
frame.add(eastB, BorderLayout.EAST);//右东
frame.add(centerB, BorderLayout.CENTER);//中间
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
4.4.GridLayout
GridLayout,即网格布局器
@Test
public void GridLayout() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
// 设置布局器为GridLayerout,即网格布局器=>该GridLayerout的构造方法表示该网格是2行3列
frame.setLayout(new GridLayout(2, 3));
JButton b1 = new JButton("洪七");
JButton b2 = new JButton("段智兴");
JButton b3 = new JButton("欧阳锋");
JButton b4 = new JButton("黄药师");
JButton b5 = new JButton("周伯通");
frame.add(b1);
frame.add(b2);
frame.add(b3);
frame.add(b4);
frame.add(b5);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
4.5.setPreferredSize
即使使用了布局器 ,也可以 通过setPreferredSize
,向布局器建议该组件显示的大小.
注 只对部分布局器起作用,比如
FlowLayout
可以起作用。 比如GridLayout就不起作用
,因为网格布局器必须对齐
@Test
public void setPreferredSize() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(new FlowLayout());
JButton b1 = new JButton("英雄1");
JButton b2 = new JButton("英雄2");
JButton b3 = new JButton("英雄3");
// 即便 使用布局器 ,也可以 通过setPreferredSize,向布局器建议该组件b3按钮显示的大小
b3.setPreferredSize(new Dimension(180, 40));
frame.add(b1);
frame.add(b2);
frame.add(b3);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
4.6.CardLayout
因为需要用到面板,放在后面讲: CardLayout
4.7.练习:使用布局器做出计算器上的按钮效果
@Test
public void practice() throws InterruptedException {
JFrame frame = new JFrame("计算器");
frame.setBounds(300, 400, 800, 600);//坐标为 300,400 长宽为600/800
frame.setLayout(new GridLayout(4, 5, 8, 8));//网格布局为4行4列 上下左右间隔为8/8
String[] arr = {
"7", "8", "9", "/", "sq", "4", "5", "6", "*", "%", "1", "2", "3", "-", "1/x", "0", "+/-", ".", "+", "="};
for (int i = 0; i < 20; i++) {
frame.add(new JButton(arr[i]));
}
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
五.组件
JAVA的图形界面下有两组控件,一组是awt
,一组是swing
。一般都是使用swing
- JLabel 标签
- setIcon 使用JLabel显示图片
- JButton 按钮
- JCheckBox 复选框
- JRadioButton 单选框
- ButtonGroup 按钮组
- JComboBox 下拉框
- JOptionPane 对话框
- JTextField 文本框
- JPasswordField 密码框
- JTextArea 文本域
- JProgressBar 进度条
- JFileChooser 文件选择器
5.1.Label
Label(标签)用于显示文字
@Test
public void JLabel() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);//
JLabel label = new JLabel("LOL文字");
//文字颜色
label.setForeground(Color.red);
label.setBounds(50, 50, 280, 30);
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.2.使用JLabel显示图片
Java GUI 显示图片是通过在label上设置图标实现的
- 注: 这里的图片路径是
e:/data/gareen.jpg
,所以要确保这里有图片,不然不会显示
@Test
public void JLabelShowImg() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 200);
frame.setLayout(null);
JLabel label = new JLabel();
String imgPath = "e:/data/gareen.jpg";
//根据图片创建ImageIcon对象
ImageIcon img = new ImageIcon(imgPath);
//设置ImageIcon
label.setIcon(img);
//label的大小设置为ImageIcon,否则显示不完整
label.setBounds(50, 50, img.getIconWidth(), img.getIconHeight());
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.3.按钮
JButton 普通按钮
@Test
public void JButton() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
JButton b = new JButton("一键秒对方基地挂");
b.setBounds(50, 50, 280, 30);
frame.add(b);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.4.复选框
JCheckBox 复选框
使用
isSelected
来获取是否选中了
@Test
public void JCheckBox() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 200);
frame.setLayout(null);
JCheckBox bCheckBox1 = new JCheckBox("物理英雄");
//设置 为 默认被选中
bCheckBox1.setSelected(true);
bCheckBox1.setBounds(50, 50, 130, 30);
JCheckBox bCheckBox2 = new JCheckBox("魔法 英雄");
bCheckBox2.setBounds(50, 100, 130, 30);
//判断 是否 被 选中
System.out.println(bCheckBox2.isSelected());
frame.add(bCheckBox1);
frame.add(bCheckBox2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.5.单选框
JRadioButton 单选框
- 使用isSelected来获取是否选中了
在这个例子里,两个单选框可以被同时选中
,为了实现只能选中一个,还需要用到ButtonGroup
@Test
public void JRadioButton() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 200);
frame.setLayout(null);
JRadioButton b1 = new JRadioButton("物理英雄");
// 设置 为 默认被选中
b1.setSelected(true);
b1.setBounds(50, 50, 130, 30);
JRadioButton b2 = new JRadioButton("魔法 英雄");
b2.setBounds(50, 100, 130, 30);
System.out.println(b2.isSelected());
frame.add(b1);
frame.add(b2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.6.按钮组
ButtonGroup 对按钮进行分组
,把不同的按钮,放在同一个分组里 ,同一时间,只有一个 按钮 会被选中
(比如说单选框)
@Test
public void ButtonGroup() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 240);
frame.setLayout(null);
JRadioButton b1 = new JRadioButton("物理英雄");
b1.setSelected(true);
b1.setBounds(50, 50, 130, 30);
JRadioButton b2 = new JRadioButton("魔法 英雄");
b2.setBounds(50, 100, 130, 30);
// 按钮分组
ButtonGroup bg = new ButtonGroup();
// 把b1,b2放在 同一个 按钮分组对象里 ,这样同一时间,只有一个 按钮 会被选中
bg.add(b1);
bg.add(b2);
frame.add(b1);
frame.add(b2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.7.下拉框
JComboBox 下拉框
- 使用getSelectedItem来获取被选中项
- 使用setSelectedItem() 来指定要选中项
@Test
public void JComboBox() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 240);
frame.setLayout(null);
//下拉框出现的条目
String[] heros = new String[]{
"卡特琳娜", "库奇"};
JComboBox cb = new JComboBox(heros);
cb.setBounds(50, 50, 80, 30);
frame.add(cb);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.8.对话框
JOptionPane 用于弹出对话框
-
JOptionPane.showConfirmDialog(f, “是否 使用外挂 ?”);:表示询问,
第一个参数
是该对话框以哪个组件对齐
-
JOptionPane.showInputDialog(f, “请输入yes,表明使用外挂后果自负”);:接受用户的输入
-
JOptionPane.showMessageDialog(frame, “你使用外挂被抓住! 罚拣肥皂3次!”);:显示消息
@Test
public void JOptionPane() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(580, 240);
frame.setLayout(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
int option = JOptionPane.showConfirmDialog(frame, "是否 使用外挂 ?");
if (JOptionPane.OK_OPTION == option) {
String answer = JOptionPane.showInputDialog(frame, "请输入yes,表明使用外挂后果自负");
if ("yes".equals(answer)) {
JOptionPane.showMessageDialog(frame, "你使用外挂被抓住! 罚拣肥皂3次!");
}
}
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.9.文本框+密码框
JTextField 输入框
- setText 设置文本
- getText 获取文本
JTextField 是单行文本框,如果要输入多行数据,请使用
JTextArea
tfPassword.grabFocus(); 表示让密码输入框获取焦点
JPasswordField 密码框
与文本框不同,获取密码框里的内容,推荐使用getPassword
,该方法会返回一个字符数组,而非字符串
@Test
public void JInputAndPawword() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(new FlowLayout());
JLabel lName = new JLabel("账号:");
// 输入框
JTextField tfName = new JTextField("");
tfName.setText("请输入账号");
tfName.setPreferredSize(new Dimension(80, 30));
JLabel lPassword = new JLabel("密码:");
// 密码框
JPasswordField tfPassword = new JPasswordField("");
tfPassword.setText("&48kdh4@#");
tfPassword.setPreferredSize(new Dimension(80, 30));
// 与文本框不同,获取密码框里的内容,推荐使用getPassword,该方法会返回一个字符数组,而非字符串
char[] password = tfPassword.getPassword();
String p = String.valueOf(password);
System.out.println(p);
frame.add(lName);
frame.add(tfName);
frame.add(lPassword);
frame.add(tfPassword);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
tfPassword.grabFocus();
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.10.文本域
JTextArea:文本域可以输入多行数据
- 如果要给文本域初始文本,通过
\n
来实现换行效果
- JTextArea通常会用到
append
来进行数据追加 - 如果文本太长,会跑出去,可以通过
setLineWrap(true)
来做到自动换行
@Test
public void JTextArea() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(new FlowLayout());
JLabel l = new JLabel("文本域:");
JTextArea ta = new JTextArea();
ta.setPreferredSize(new Dimension(300, 100));//设置大小
//\n换行符
ta.setText("抢人头!\n抢你妹啊抢!\n");
//追加数据
ta.append("我去送了了了了了了了了了了了了了了了了了了了了了了了了");
//设置自动换行
ta.setLineWrap(true);
frame.add(l);
frame.add(ta);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.11.进度条
@Test
public void JProgressBar() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(new FlowLayout());
JProgressBar pb = new JProgressBar();
//进度条最大1000
pb.setMaximum(1000);
//当前进度是50
pb.setValue(50);
//显示当前进度
pb.setStringPainted(true);
frame.add(pb);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
5.12.文件选择器
JFileChooser 表示文件选择器
使用FileFilter用于仅选择xlsx
文件
fileChooser.setFileFilter(new FileFilter() {
@Override
public String getDescription() {
return ".xlsx";
}
@Override
public boolean accept(File frame) {
return frame.getName().toLowerCase().endsWith(".xlsx");
}
});
- fileChooser.showOpenDialog();
用于打开文件
- fileChooser.showSaveDialog();
用于保存文件
@Test
public void JFileChooser() throws InterruptedException {
JFrame frame = new JFrame("LOL");
frame.setLayout(new FlowLayout());
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileFilter(new FileFilter() {
@Override
public String getDescription() {
return ".xlsx";
}
@Override
public boolean accept(File frame) {
return frame.getName().toLowerCase().endsWith(".xlsx");
}
});
JButton bOpen = new JButton("打开文件");
JButton bSave = new JButton("保存文件");
frame.add(bOpen);
frame.add(bSave);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250, 150);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//打开文件
bOpen.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int returnVal = fileChooser.showOpenDialog(frame);
File file = fileChooser.getSelectedFile();
if (returnVal == JFileChooser.APPROVE_OPTION) {
JOptionPane.showMessageDialog(frame, "计划打开文件:" + file.getAbsolutePath());
}
}
});
//保存文件
bSave.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int returnVal = fileChooser.showSaveDialog(frame);
File file = fileChooser.getSelectedFile();
if (returnVal == JFileChooser.APPROVE_OPTION) {
JOptionPane.showMessageDialog(frame, "计划保存到文件:" + file.getAbsolutePath());
}
}
});
//设置休眠时间,是为了延缓主线程销毁
TimeUnit.SECONDS.sleep(1000);
}
六.面板
- 基本面板
- ContentPane
- SplitPanel
- JScrollPanel
- TabbedPanel
- CardLayerout
6.1.基本面板
JPanel即为基本面板
- 面板和JFrame一样都是容器,不过面板一般用来充当
中间容器
,把组件放在面板上,然后再把面板放在窗体上。 一旦移动一个面板,其上面的组件,就会全部统一跟着移动
,采用这种方式,便于进行整体界面
的设计`
@Test
public void base() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
JPanel panel1 = new JPanel();
// 设置面板大小
panel1.setBounds(50, 50, 300, 60);
// 设置面板背景颜色
panel1.setBackground(Color.RED);
// 这一句可以没有,因为JPanel默认就是采用的FlowLayout
panel1.setLayout(new FlowLayout());
JButton b1 = new JButton("英雄1");
JButton b2 = new JButton("英雄2");
JButton b3 = new JButton("英雄3");
// 把按钮加入面板
panel1.add(b1);
panel1.add(b2);
panel1.add(b3);
JPanel panel2 = new JPanel();
JButton b4 = new JButton("英雄4");
JButton b5 = new JButton("英雄5");
JButton b6 = new JButton("英雄6");
// 把按钮加入面板
panel2.add(b4);
panel2.add(b5);
panel2.add(b6);
panel2.setBackground(Color.BLUE);
panel2.setBounds(10, 150, 300, 60);
// 把面板加入窗口
frame.add(panel1);
frame.add(panel2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
TimeUnit.SECONDS.sleep(1000);
}
6.2.ContentPane
JFrame上有一层面板,叫做ContentPane
- 平时通过
frame.add()
向JFrame增加组件,其实是向JFrame上的 ContentPane加东西
@Test
public void ContentPane() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
JButton b = new JButton("一键秒对方基地挂");
b.setBounds(50, 50, 280, 30);
frame.add(b);
// frame.add等同于frame.getContentPane().add(b);
frame.getContentPane().add(b);
// b.getParent()获取按钮b所处于的容器
// 打印出来可以看到,实际上是ContentPane而非JFrame
System.out.println(b.getParent());//javax.swing.JPanel[null.contentPane,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
TimeUnit.SECONDS.sleep(1000);
}
6.3.SplitPanel
创建一个水平
JSplitPane,左边是pLeft,右边是pRight
@Test
public void SplitPanel() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
JPanel pLeft = new JPanel();
pLeft.setBounds(50, 50, 300, 60);
pLeft.setBackground(Color.RED);
pLeft.setLayout(new FlowLayout());
JButton b1 = new JButton("盖伦");
JButton b2 = new JButton("提莫");
JButton b3 = new JButton("安妮");
pLeft.add(b1);
pLeft.add(b2);
pLeft.add(b3);
JPanel pRight = new JPanel();
JButton b4 = new JButton("英雄4");
JButton b5 = new JButton("英雄5");
JButton b6 = new JButton("英雄6");
pRight.add(b4);
pRight.add(b5);
pRight.add(b6);
pRight.setBackground(Color.BLUE);
pRight.setBounds(10, 150, 300, 60);
// 创建一个水平JSplitPane,左边是p1,右边是p2
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pLeft, pRight); //JSplitPane.VERTICAL_SPLIT垂直分割 JSplitPane.HORIZONTAL_SPLIT水平分割
// 设置分割条的位置
splitPane.setDividerLocation(80);
// 把sp当作ContentPane
frame.setContentPane(splitPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
TimeUnit.SECONDS.sleep(1000);
}
6.4.JScrollPanel
使用带滚动条的面板有两种方式
- 在创建JScrollPane,把组件作为参数传进去
JScrollPane scrollPane = new JScrollPane(textArea);
- 希望带滚动条的面板显示其他组件的时候,调用setViewportView
scrollPane.setViewportView(textArea);
@Test
public void JScrollPanel() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
//准备一个文本域,在里面放很多数据
JTextArea textArea = new JTextArea();
for (int i = 0; i < 1000; i++) {
textArea.append(String.valueOf(i));
}
//自动换行
textArea.setLineWrap(true);
//这里使用第一种方式:在创建JScrollPane,把组件作为参数传进去
JScrollPane scrollPane = new JScrollPane(textArea);
frame.setContentPane(scrollPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
TimeUnit.SECONDS.sleep(1000);
}
6.5.TabbedPanel
标签面版 ,切换多个Tab
@Test
public void TabbedPanel() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
JPanel panel1 = new JPanel();
panel1.setBounds(50, 50, 300, 60);
panel1.setBackground(Color.RED);
panel1.setLayout(new FlowLayout());
JButton b1 = new JButton("英雄1");
JButton b2 = new JButton("英雄2");
JButton b3 = new JButton("英雄3");
panel1.add(b1);
panel1.add(b2);
panel1.add(b3);
JPanel panel2 = new JPanel();
JButton b4 = new JButton("英雄4");
JButton b5 = new JButton("英雄5");
JButton b6 = new JButton("英雄6");
panel2.add(b4);
panel2.add(b5);
panel2.add(b6);
panel2.setBackground(Color.BLUE);
panel2.setBounds(10, 150, 300, 60);
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.add(panel1);
tabbedPane.add(panel2);
// 设置tab的标题
tabbedPane.setTitleAt(0, "红色tab");
tabbedPane.setTitleAt(1, "蓝色tab");
ImageIcon i = new ImageIcon("e:/project/j2se/j.png");
tabbedPane.setIconAt(0, i);
tabbedPane.setIconAt(1, i);
frame.setContentPane(tabbedPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
TimeUnit.SECONDS.sleep(1000);
}
6.6.CardLayerout
CardLayerout
布局器 很像TabbedPanel
,在本例里面上面是一个下拉框,下面是一个CardLayerout 的JPanel
这个JPanel里有两个面板,可以通过CardLayerout方便的切换
@Test
public void CardLayerout() throws InterruptedException {
JFrame frame = new JFrame("CardLayerout");
JPanel comboBoxPane = new JPanel();
String buttonPanel = "按钮面板";
String inputPanel = "输入框面板";
String[] comboBoxItems = {
buttonPanel, inputPanel};
JComboBox<String> comboBoxArr = new JComboBox<>(comboBoxItems);
comboBoxPane.add(comboBoxArr);
// 两个Panel充当卡片
JPanel card1 = new JPanel();
card1.add(new JButton("按钮 1"));
card1.add(new JButton("按钮 2"));
card1.add(new JButton("按钮 3"));
JPanel card2 = new JPanel();
card2.add(new JTextField("输入框", 20));
JPanel cards; // a panel that uses CardLayout
cards = new JPanel(new CardLayout());
cards.add(card1, buttonPanel);
cards.add(card2, inputPanel);
frame.add(comboBoxPane, BorderLayout.NORTH);
frame.add(cards, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250, 150);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
comboBoxArr.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, (String) evt.getItem());
}
});
TimeUnit.SECONDS.sleep(1000);
}
6.7.练习-SplitPanel:点击左边panel按钮,切换右边panel图片
@Test
public void SplitPanelDemo() throws InterruptedException {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 300);
frame.setLocation(200, 200);
frame.setLayout(null);
//左边面板
JPanel pLeft = new JPanel();
pLeft.setBounds(50, 50, 300, 60);
pLeft.setBackground(Color.LIGHT_GRAY);
pLeft.setLayout(new FlowLayout());
JButton b1 = new JButton("盖伦");
JButton b2 = new JButton("提莫");
JButton b3 = new JButton("安妮");
pLeft.add(b1);
pLeft.add(b2);
pLeft.add(b3);
//右边面板
JPanel pRight = new JPanel();
JLabel lPic = new JLabel("");
ImageIcon imageIcon = new ImageIcon("e:/data/gareen.jpg");
lPic.setIcon(imageIcon);
pRight.add(lPic);
pRight.setBackground(Color.lightGray);
pRight.setBounds(10, 150, 300, 60);
// 创建一个水平JSplitPane,左边是p1,右边是p2
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pLeft, pRight);
// 设置分割条的位置
splitPane.setDividerLocation(80);
// 把sp当作ContentPane
frame.setContentPane(splitPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
switchPic(b1, "gareen", lPic);
switchPic(b2, "teemo", lPic);
switchPic(b3, "annie", lPic);
TimeUnit.SECONDS.sleep(1000);
}
//切换e:/data/{}/.jpg
private static void switchPic(JButton b1, String fileName, JLabel lPic) {
b1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ImageIcon i = new ImageIcon("e:/data/" + fileName + ".jpg");
lPic.setIcon(i);
}
});
}
6.8.练习-TabbedPanel:按照eclipse的风格显示多个java文件
首先准备一个JavaFilePane
专门用于显示文件内容的Panel
然后在TestGUI
中遍历e:/project/j2se/jdbc 下
的文件,并根据这些文件生成JavaFilePane
。接着把这些JavaFilePane
插入到TabbedPanel
中即可
public class JavaFilePane extends JPanel{
public JavaFilePane(File file){
this.setLayout(new BorderLayout());
String fileContent = getFileContent(file);
JTextArea ta = new JTextArea();
ta.setText(fileContent);
this.add(ta);
}
private String getFileContent(File f){
String fileContent = null;
try (FileReader fr = new FileReader(f)) {
char[] all = new char[(int) f.length()];
fr.read(all);
fileContent= new String(all);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return fileContent;
}
public static void main(String[] args) {
JFrame f =new JFrame();
f.setSize(400,300);
f.setContentPane(new JavaFilePane(new File("E:/project/j2se/src/gui/JavaFilePane.java")));
f.setVisible(true);
}
}
public class TestGUI {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(800, 600);
f.setLocationRelativeTo(null);
f.setLayout(null);
File folder = new File("E:/project/j2se/src/jdbc");
File[] fs=folder.listFiles();
JTabbedPane tp = new JTabbedPane();
ImageIcon icon = new ImageIcon("e:/project/j2se/j.png");
for (int i = 0; i < fs.length; i++) {
JavaFilePane jfp =new JavaFilePane(fs[i]);
tp.add(jfp);
tp.setIconAt(i,icon );
tp.setTitleAt(i, shortName(fs[i].getName()));
}
f.setContentPane(tp);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
private static String shortName(String name) {
int length = 6;
if(name.length()>length){
return name.substring(0,length) + "...";
}
return name;
}
}
七.组件综合练习
7.1.表单组件练习
public class LayoutDemo {
public static void main(String[] args) {
JFrame frame = new JFrame("LoL");
frame.setSize(400, 400);
frame.setLocation(200, 200);
int gap = 10;
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(4, 3, gap, gap));
JLabel lLocation = new JLabel("地名:");
JTextField tfLocation = new JTextField("");
JLabel lType = new JLabel("公司类型:");
JTextField tfType = new JTextField("");
JLabel lCompanyName = new JLabel("公司名称:");
JTextField tfCompanyName = new JTextField("");
JLabel lBossName = new JLabel("老板名称:");
JTextField tfBossName = new JTextField("");
JLabel lMoney = new JLabel("金额:");
JTextField tfMoney = new JTextField("");
JLabel lProduct = new JLabel("产品:");
JTextField tfProduct = new JTextField("");
JLabel lUnit = new JLabel("价格计量单位");
JTextField tfUnit = new JTextField("");
panel.add(lLocation);
panel.add(tfLocation);
panel.add(lType);
panel.add(tfType);
panel.add(lCompanyName);
panel.add(tfCompanyName);
panel.add(lBossName);
panel.add(tfBossName);
panel.add(lMoney);
panel.add(tfMoney);
panel.add(lProduct);
panel.add(tfProduct);
panel.add(lUnit);
panel.add(tfUnit);
frame.setLayout(null);
panel.setBounds(gap, gap, 375, 120);
JButton button = new JButton("生成");
JTextArea textArea = new JTextArea();
textArea.setLineWrap(true);
button.setBounds(150, 120 + 30, 80, 30);
textArea.setBounds(gap, 150 + 60, 375, 120);
frame.add(panel);
frame.add(button);
frame.add(textArea);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
button.addActionListener(new ActionListener() {
boolean checkedPass = true;
@Override
public void actionPerformed(ActionEvent e) {
checkedPass = true;
checkEmpty(tfLocation, "地址");
checkEmpty(tfType, "公司类型");
checkEmpty(tfCompanyName, "公司名称");
checkEmpty(tfBossName, "老板姓名");
checkNumber(tfMoney, "金额");
checkEmpty(tfProduct, "产品");
checkEmpty(tfUnit, "价格计量单位");
String location = tfLocation.getText();
String type = tfType.getText();
String companyName = tfCompanyName.getText();
String bossName = tfBossName.getText();
String money = tfMoney.getText();
String product = tfProduct.getText();
String unit = tfUnit.getText();
if (checkedPass) {
String model = "%s最大%s%s倒闭了,王八蛋老板%s吃喝嫖赌,欠下了%s个亿,"
+ "带着他的小姨子跑了!我们没有办法,拿着%s抵工资!原价都是一%s多、两%s多、三%s多的%s,"
+ "现在全部只卖二十块,统统只要二十块!%s王八蛋,你不是人!我们辛辛苦苦给你干了大半年,"
+ "你不发工资,你还我血汗钱,还我血汗钱!";
String result = String.format(model, location, type, companyName, bossName, money, product, unit, unit, unit, product, bossName);
textArea.setText("");
textArea.append(result);
}
}
private void checkNumber(JTextField textField, String msg) {
if (!checkedPass) {
return;
}
String value = textField.getText();
try {
Integer.parseInt(value);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(frame, msg + " 必须是整数");
textField.grabFocus();
checkedPass = false;
}
}
private void checkEmpty(JTextField textField, String msg) {
if (!checkedPass) {
return;
}
String value = textField.getText();
if (0 == value.length()) {
JOptionPane.showMessageDialog(frame, msg + " 不能为空");
textField.grabFocus();
checkedPass = false;
}
}
});
}
}
7.2.登录校验(连接数据库)
-
准备两个JTextFiled,一个用于输入账号,一个用于输入密码。
-
再准备一个JButton,上面的文字是登陆
点击按钮之后,首先进行为空判断,如果都不为空,则把账号和密码,拿到数据库中进行比较(SQL语句判断账号密码是否正确),根据判断结果,使用JOptionPane进行提示。
public class LoginDemo {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
JPanel pNorth = new JPanel();
pNorth.setLayout(new FlowLayout());
JPanel pCenter = new JPanel();
JLabel lName = new JLabel("账号:");
JTextField tfName = new JTextField("");
tfName.setText("");
tfName.setPreferredSize(new Dimension(80, 30));
JLabel lPassword = new JLabel("密码:");
JPasswordField tfPassword = new JPasswordField("");
tfPassword.setText("");
tfPassword.setPreferredSize(new Dimension(80, 30));
pNorth.add(lName);
pNorth.add(tfName);
pNorth.add(lPassword);
pNorth.add(tfPassword);
JButton b = new JButton("登陆");
pCenter.add(b);
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = tfName.getText();
String password = new String(tfPassword.getPassword());
if (0 == name.length()) {
JOptionPane.showMessageDialog(f, "账号不能为空");
tfName.grabFocus();
return;
}
if (0 == password.length()) {
JOptionPane.showMessageDialog(f, "密码不能为空");
tfPassword.grabFocus();
return;
}
if (check(name, password)) {
JOptionPane.showMessageDialog(f, "登陆成功");
} else {
JOptionPane.showMessageDialog(f, "密码错误");
}
}
});
f.setLayout(new BorderLayout());
f.add(pNorth, BorderLayout.NORTH);
f.add(pCenter, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public static boolean check(String name, String password) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
boolean result = false;
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8", "root", "root");
Statement s = c.createStatement();
) {
String sql = "select * from user where name = '" + name + "' and password = '" + password + "'";
// 执行查询语句,并把结果集返回给ResultSet
ResultSet rs = s.executeQuery(sql);
if (rs.next()) {
result = true;
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
}
7.3.随机进度条
创建一个线程,每隔100毫秒,就把进度条的进度+1。从0%一直加到100%
- 刚开始加的比较快,以每隔100毫秒的速度增加,随着进度的增加,越加越慢,让处女座的使用者,干着急
public static void main(String[] args) {
JFrame frame = new JFrame("进度条");
frame.setSize(450, 140);
frame.setLocation(200, 200);
frame.setLayout(new FlowLayout());
JLabel label = new JLabel("文件复制进度:");
JProgressBar progressBar = new JProgressBar();
progressBar.setMaximum(100);
//当前进度是0
progressBar.setValue(0);
progressBar.setStringPainted(true);
frame.add(label);
frame.add(progressBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Thread(()-> {
while (progressBar.getValue() != progressBar.getMaximum()) {
try {
if (progressBar.getValue() > 80) {
TimeUnit.MILLISECONDS.sleep(500);
}else {
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.setValue(progressBar.getValue() + 1);
}
}).start();
frame.setVisible(true);
}
7.4.显示文件夹复制进度条
public class CopyProgressBarDemoPlus {
static long allFileSize = 0; // 所有需要复制的文件大小
static long currentFileSizeCopied = 0;// 已复制的文件总大小
/**
* 遍递归历文件夹获取文件夹内容总大小-赋值给全局变量
*
* @param file
*/
public static void calcLateAllFileSize(File file) {
if (file.isFile()) {
allFileSize += file.length();
return;
}
if (file.isDirectory()) {
File[] fs = file.listFiles();
for (File frame : fs) {
calcLateAllFileSize(frame);
}
}
}
/**
* 遍递归历文件夹获取文件夹内容总大小(增强版)
*
* @param file
*/
public static int calcLateAllFileSizePlus(File file) {
int fileSizeSum = 0;
if (file.isFile()) {
fileSizeSum += file.length();
}
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File frame : files) {
fileSizeSum += calcLateAllFileSizePlus(frame);
}
}
return fileSizeSum;
}
public static void main(String[] args) {
JFrame frame = new JFrame("带进度条的文件夹复制");
frame.setSize(450, 140);
frame.setLocation(200, 200);
frame.setLayout(new FlowLayout());
// 文件地址
JLabel lStr = new JLabel("源文件地址:");
JTextField strTf = new JTextField("");
strTf.setText("e:/data");
strTf.setPreferredSize(new Dimension(100, 30));
JLabel lDest = new JLabel("复制到:");
JTextField destTf = new JTextField("");
destTf.setText("e:/data2");
destTf.setPreferredSize(new Dimension(100, 30));
frame.add(lStr);
frame.add(strTf);
frame.add(lDest);
frame.add(destTf);
JButton bStartCopy = new JButton("开始复制");
bStartCopy.setPreferredSize(new Dimension(100, 30));
JLabel label = new JLabel("文件复制进度:");
JProgressBar progressBar = new JProgressBar();
progressBar.setMaximum(100);
progressBar.setStringPainted(true);
frame.add(bStartCopy);
frame.add(label);
frame.add(progressBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
// 计算需要复制的文件的总大小
String srcPath = strTf.getText();
File folder = new File(srcPath);
allFileSize = calcLateAllFileSizePlus(folder);
// 点击开始复制
bStartCopy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
currentFileSizeCopied = 0;
String srcPath = strTf.getText();
String destPath = destTf.getText();
new Thread(() -> copyFolder(srcPath, destPath)).start();
bStartCopy.setEnabled(false);
}
//复制文件
public void copyFile(String srcPath, String destPath) {
File srcFile = new File(srcPath);
File destFile = new File(destPath);
// 缓存区,一次性读取1024字节
byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);) {
while (true) {
// 实际读取的长度是 actuallyReaded,有可能小于1024
int actuallyReaded = fis.read(buffer);
// -1表示没有可读的内容了
if (-1 == actuallyReaded) {
break;
}
fos.write(buffer, 0, actuallyReaded);
fos.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//复制目录
public void copyFolder(String srcPath, String destPath) {
File srcFolder = new File(srcPath);
File destFolder = new File(destPath);
if (!srcFolder.exists()) {
return;
}
if (!srcFolder.isDirectory()) {
return;
}
if (destFolder.isFile()) {
return;
}
if (!destFolder.exists()) {
destFolder.mkdirs();
}
File[] files = srcFolder.listFiles();
assert files != null;
for (File srcFile : files) {
if (!(srcFile.isDirectory())) {
File newDestFile = new File(destFolder, srcFile.getName());
copyFile(srcFile.getAbsolutePath(), newDestFile.getAbsolutePath());
currentFileSizeCopied += srcFile.length();
System.out.println(srcFile.length());
double current = (double) currentFileSizeCopied / (double) allFileSize;
int progress = (int) (current * 100);
progressBar.setValue(progress);
if (progress == 100) {
JOptionPane.showMessageDialog(frame, "复制完毕");
bStartCopy.setEnabled(true);
}
}
if (srcFile.isDirectory()) {
File newDestFolder = new File(destFolder, srcFile.getName());
copyFolder(srcFile.getAbsolutePath(), newDestFolder.getAbsolutePath());
}
}
}
});
}
}