简单的例子

JFrame是GUI中的容器
JButton是最常见的组件- 按钮
注意:f.setVisible(true); 会对所有的组件进行渲染,所以一定要放在最后面

package gui;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {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);}
}

按钮监听

创建一个匿名类实现ActionListener接口,当按钮被点击时,actionPerformed方法就会被调用

package gui;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 200);f.setLayout(null);final JLabel l = new JLabel();ImageIcon i = new ImageIcon("e:/project/j2se/shana.png");l.setIcon(i);l.setBounds(50, 50, i.getIconWidth(), i.getIconHeight());JButton b = new JButton("隐藏图片");b.setBounds(150, 200, 100, 30);// 给按钮 增加 监听b.addActionListener(new ActionListener() {// 当按钮被点击时,就会触发 ActionEvent事件// actionPerformed 方法就会被执行public void actionPerformed(ActionEvent e) {l.setVisible(false);}});f.add(l);f.add(b);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

键盘监听

键盘监听器: KeyListener
keyPressed 代表 键被按下
keyReleased 代表 键被弹起
keyTyped 代表 一个按下弹起的组合动作
KeyEvent.getKeyCode() 可以获取当前点下了哪个键

package gui;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 200);f.setLayout(null);final JLabel l = new JLabel();ImageIcon i = new ImageIcon("e:/project/j2se/shana.png");l.setIcon(i);l.setBounds(50, 50, i.getIconWidth(), i.getIconHeight());// 增加键盘监听f.addKeyListener(new KeyListener() {// 键被弹起public void keyReleased(KeyEvent e) {// 39代表按下了 “右键”if (e.getKeyCode() == 39) {// 图片向右移动 (y坐标不变,x坐标增加)l.setLocation(l.getX() + 10, l.getY());}}//键被按下public void keyPressed(KeyEvent e) {// TODO Auto-generated method stub}// 一个按下弹起的组合动作public void keyTyped(KeyEvent e) {}});f.add(l);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

鼠标监听

MouseListener 鼠标监听器
mouseReleased 鼠标释放
mousePressed 鼠标按下
mouseExited 鼠标退出
mouseEntered 鼠标进入
mouseClicked 鼠标点击
在本例中,使用mouseEntered,当鼠标进入图片的时候,图片就移动位置

package gui;import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;public class TestGUI {public static void main(String[] args) {final JFrame f = new JFrame("LoL");f.setSize(800, 600);f.setLocationRelativeTo(null);f.setLayout(null);final JLabel l = new JLabel();ImageIcon i = new ImageIcon("e:/project/j2se/shana_heiheihei.png");l.setIcon(i);l.setBounds(375, 275, i.getIconWidth(), i.getIconHeight());f.add(l);l.addMouseListener(new MouseListener() {// 释放鼠标public void mouseReleased(MouseEvent e) {// TODO Auto-generated method stub}// 按下鼠标public void mousePressed(MouseEvent e) {// TODO Auto-generated method stub}// 鼠标退出public void mouseExited(MouseEvent e) {// TODO Auto-generated method stub}// 鼠标进入public void mouseEntered(MouseEvent e) {Random r = new Random();int x = r.nextInt(f.getWidth() - l.getWidth());int y = r.nextInt(f.getHeight() - l.getHeight());l.setLocation(x, y);}// 按下释放组合动作为点击鼠标public void mouseClicked(MouseEvent e) {// TODO Auto-generated method stub}});f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

适配器

MouseAdapter 鼠标监听适配器
一般说来在写监听器的时候,会实现MouseListener。
但是MouseListener里面有很多方法实际上都没有用到,比如mouseReleased ,mousePressed,mouseExited等等。
这个时候就可以使用 鼠标监听适配器,MouseAdapter 只需要重写必要的方法即可。

package gui;import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;public class TestGUI {public static void main(String[] args) {final JFrame f = new JFrame("LoL");f.setSize(800, 600);f.setLocationRelativeTo(null);f.setLayout(null);final JLabel l = new JLabel("");ImageIcon i = new ImageIcon("e:/project/j2se/shana_heiheihei.png");l.setIcon(i);l.setBounds(375, 275, i.getIconWidth(), i.getIconHeight());f.add(l);// MouseAdapter 适配器,只需要重写用到的方法,没有用到的就不用写了l.addMouseListener(new MouseAdapter() {// 只有mouseEntered用到了public void mouseEntered(MouseEvent e) {Random r = new Random();int x = r.nextInt(f.getWidth() - l.getWidth());int y = r.nextInt(f.getHeight() - l.getHeight());l.setLocation(x, y);}});f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

容器

java的图形界面中,容器是用来存放 按钮,输入框等组件的。

窗体型容器有两个,一个是JFrame,一个是JDialog

JFrame

JFrame是最常用的窗体型容器,默认情况下,在右上角有最大化最小化按钮

package gui;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {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);}
}

JDialog

JDialog也是窗体型容器,右上角没有最大和最小化按钮

package gui;import javax.swing.JButton;
import javax.swing.JDialog;public class TestGUI {public static void main(String[] args) {//普通的窗体,带最大和最小化按钮JDialog d = new JDialog();d.setTitle("LOL");d.setSize(400, 300);d.setLocation(200, 200);d.setLayout(null);JButton b = new JButton("一键秒对方基地挂");b.setBounds(50, 50, 280, 30);d.add(b);d.setVisible(true);}
}

模态JDialog

当一个对话框被设置为模态的时候,其背后的父窗体,是不能被激活的,除非该对话框被关闭

package gui;import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("外部窗体");f.setSize(800, 600);f.setLocation(100, 100);// 根据外部窗体实例化JDialogJDialog d = new JDialog(f);// 设置为模态d.setModal(true);d.setTitle("模态的对话框");d.setSize(400, 300);d.setLocation(200, 200);d.setLayout(null);JButton b = new JButton("一键秒对方基地挂");b.setBounds(50, 50, 280, 30);d.add(b);f.setVisible(true);d.setVisible(true);}
}

窗体大小不可变化

通过调用方法 setResizable(false); 做到窗体大小不可变化

package gui;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {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.setResizable(false);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

布局器

布局器是用在容器上的。 用来决定容器上的组件摆放的位置和大小

绝对定位

绝对定位就是指不使用布局器,组件的位置和大小需要单独指定

package gui;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);// 设置布局器为null,即进行绝对定位,容器上的组件都需要指定位置和大小f.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");f.add(b1);f.add(b2);f.add(b3);// b4没有指定位置和大小,不会出现在容器上f.add(b4);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

FlowLayout

设置布局器为FlowLayout,顺序布局器
容器上的组件水平摆放
加入到容器即可,无需单独指定大小和位置

package gui;import java.awt.FlowLayout;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);// 设置布局器为FlowLayerout// 容器上的组件水平摆放f.setLayout(new FlowLayout());JButton b1 = new JButton("英雄1");JButton b2 = new JButton("英雄2");JButton b3 = new JButton("英雄3");// 加入到容器即可,无需单独指定大小和位置f.add(b1);f.add(b2);f.add(b3);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

BorderLayout

设置布局器为BorderLayout
容器上的组件按照上北 下南 左西 右东 中的顺序摆放

package gui;import java.awt.BorderLayout;
import java.awt.FlowLayout;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);// 设置布局器为BorderLayerout// 容器上的组件按照上北下南左西右东中的顺序摆放f.setLayout(new BorderLayout());JButton b1 = new JButton("洪七");JButton b2 = new JButton("段智兴");JButton b3 = new JButton("欧阳锋");JButton b4 = new JButton("黄药师");JButton b5 = new JButton("周伯通");// 加入到容器的时候,需要指定位置f.add(b1, BorderLayout.NORTH);f.add(b2, BorderLayout.SOUTH);f.add(b3, BorderLayout.WEST);f.add(b4, BorderLayout.EAST);f.add(b5, BorderLayout.CENTER);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

GridLayout

GridLayout,即网格布局器

package gui;import java.awt.GridLayout;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);// 设置布局器为GridLayerout,即网格布局器// 该GridLayerout的构造方法表示该网格是2行3列f.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("周伯通");f.add(b1);f.add(b2);f.add(b3);f.add(b4);f.add(b5);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

setPreferredSize

即便 使用 布局器 ,也可以 通过setPreferredSize,向布局器建议该组件显示的大小.
注 只对部分布局器起作用,比如FlowLayout可以起作用。 比如GridLayout就不起作用,因为网格布局器必须对齐

package gui;import java.awt.Dimension;
import java.awt.FlowLayout;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new FlowLayout());JButton b1 = new JButton("英雄1");JButton b2 = new JButton("英雄2");JButton b3 = new JButton("英雄3");// 即便 使用 布局器 ,也可以 通过setPreferredSize,向布局器建议该组件显示的大小b3.setPreferredSize(new Dimension(180, 40));f.add(b1);f.add(b2);f.add(b3);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

组件

标签

Label用于显示文字

package gui;import java.awt.Color;import javax.swing.JFrame;
import javax.swing.JLabel;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(null);JLabel l = new JLabel("LOL文字");//文字颜色l.setForeground(Color.red);l.setBounds(50, 50, 280, 30);f.add(l);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

使用JLabel显示图片

java GUI 显示图片是通过在label上设置图标实现的
注: 这里的图片路径是e:/project/j2se/shana.png,所以要确保这里有图片,不然不会显示
注: 图片的后缀名和真实格式,必须保持一致,否则很有可能无法正常显示。 什么意思呢?就是文件本来是jpg的,但是仅仅是把后缀名修改成了png,那么会导致显示失败。

package gui;import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 200);f.setLayout(null);JLabel l = new JLabel();//根据图片创建ImageIcon对象ImageIcon i = new ImageIcon("e:/project/j2se/shana.png");//设置ImageIconl.setIcon(i);//label的大小设置为ImageIcon,否则显示不完整l.setBounds(50, 50, i.getIconWidth(), i.getIconHeight());f.add(l);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

按钮

JButton 普通按钮

package gui;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {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);}
}

复选框

JCheckBox 复选框

使用isSelected来获取是否选中了

package gui;import javax.swing.JCheckBox;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 200);f.setLayout(null);JCheckBox bCheckBox = new JCheckBox("物理英雄");//设置 为 默认被选中bCheckBox.setSelected(true);bCheckBox.setBounds(50, 50, 130, 30);JCheckBox bCheckBox2 = new JCheckBox("魔法 英雄");bCheckBox2.setBounds(50, 100, 130, 30);//判断 是否 被 选中System.out.println(bCheckBox2.isSelected());f.add(bCheckBox);f.add(bCheckBox2);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

单选框

JRadioButton 单选框
使用isSelected来获取是否选中了

在这个例子里,两个单选框可以被同时选中,为了实现只能选中一个,还需要用到ButtonGroup

package gui;import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JRadioButton;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 200);f.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());f.add(b1);f.add(b2);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

按钮组

ButtonGroup 对按钮进行分组,把不同的按钮,放在同一个分组里 ,同一时间,只有一个 按钮 会被选中

package gui;import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JRadioButton;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 240);f.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);f.add(b1);f.add(b2);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

下拉框

JComboBox 下拉框
使用getSelectedItem来获取被选中项
使用setSelectedItem() 来指定要选中项

package gui;import javax.swing.JComboBox;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 240);f.setLayout(null);//下拉框出现的条目String[] heros = new String[] { "卡特琳娜", "库奇" };JComboBox cb = new JComboBox(heros);cb.setBounds(50, 50, 80, 30);f.add(cb);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

对话框

JOptionPane 用于弹出对话框

JOptionPane.showConfirmDialog(f, "是否 使用外挂 ?");
表示询问,第一个参数是该对话框以哪个组件对齐
JOptionPane.showInputDialog(f, "请输入yes,表明使用外挂后果自负");
接受用户的输入
JOptionPane.showMessageDialog(f, "你使用外挂被抓住! 罚拣肥皂3次!");
显示消息

package gui;import javax.swing.JFrame;
import javax.swing.JOptionPane;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 240);f.setLayout(null);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);int option = JOptionPane.showConfirmDialog(f, "是否 使用外挂 ?");if (JOptionPane.OK_OPTION == option) {String answer = JOptionPane.showInputDialog(f, "请输入yes,表明使用外挂后果自负");if ("yes".equals(answer))JOptionPane.showMessageDialog(f, "你使用外挂被抓住! 罚拣肥皂3次!");}}
}

文本框

JTextField 输入框
setText 设置文本
getText 获取文本
JTextField 是单行文本框,如果要输入多行数据,请使用JTextArea

tfPassword.grabFocus(); 表示让密码输入框获取焦点

package gui;import java.awt.Dimension;
import java.awt.FlowLayout;import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new FlowLayout());JLabel lName = new JLabel("账号:");// 输入框JTextField tfName = new JTextField("");tfName.setText("请输入账号");tfName.setPreferredSize(new Dimension(80, 30));JLabel lPassword = new JLabel("密码:");// 输入框JTextField tfPassword = new JTextField("");tfPassword.setText("请输入密码");tfPassword.setPreferredSize(new Dimension(80, 30));f.add(lName);f.add(tfName);f.add(lPassword);f.add(tfPassword);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);tfPassword.grabFocus();}
}

密码框

JPasswordField 密码框
与文本框不同,获取密码框里的内容,推荐使用getPassword,该方法会返回一个字符数组,而非字符串

package gui;import java.awt.Dimension;
import java.awt.FlowLayout;import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new FlowLayout());JLabel l = new JLabel("密码:");// 密码框JPasswordField pf = new JPasswordField("");pf.setText("&48kdh4@#");pf.setPreferredSize(new Dimension(80, 30));// 与文本框不同,获取密码框里的内容,推荐使用getPassword,该方法会返回一个字符数组,而非字符串char[] password = pf.getPassword();String p = String.valueOf(password);System.out.println(p);f.add(l);f.add(pf);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

文本域

JTextArea:文本域。
和文本框JTextField不同的是,文本域可以输入多行数据
如果要给文本域初始文本,通过\n来实现换行效果
JTextArea通常会用到append来进行数据追加
如果文本太长,会跑出去,可以通过setLineWrap(true) 来做到自动换行

package gui;import java.awt.Dimension;
import java.awt.FlowLayout;import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new FlowLayout());JLabel l = new JLabel("文本域:");JTextArea ta = new JTextArea();ta.setPreferredSize(new Dimension(200, 150));//\n换行符ta.setText("抢人头!\n抢你妹啊抢!\n");//追加数据ta.append("我去送了了了了了了了了了了了了了了了了了了了了了了了了");//设置自动换行ta.setLineWrap(true);f.add(l);f.add(ta);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

进度条

package gui;import java.awt.Dimension;
import java.awt.FlowLayout;import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new FlowLayout());JProgressBar pb = new JProgressBar();//进度条最大100pb.setMaximum(100);//当前进度是50pb.setValue(50);//显示当前进度pb.setStringPainted(true);f.add(pb);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

文件选择器

JFileChooser 表示文件选择器
使用FileFilter用于仅选择.txt文件

fc.setFileFilter(new FileFilter() {

public String getDescription() {

return ".txt";

}

public boolean accept(File f) {

return f.getName().toLowerCase().endsWith(".txt");

}

});
fc.showOpenDialog(); 用于打开文件
fc.showSaveDialog(); 用于保存文件

package gui;import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LOL");f.setLayout(new FlowLayout());JFileChooser fc = new JFileChooser();fc.setFileFilter(new FileFilter() {@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn ".txt";}@Overridepublic boolean accept(File f) {return f.getName().toLowerCase().endsWith(".txt");}});JButton bOpen = new JButton("打开文件");JButton bSave = new JButton("保存文件");f.add(bOpen);f.add(bSave);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setSize(250, 150);f.setLocationRelativeTo(null);f.setVisible(true);bOpen.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {int returnVal =  fc.showOpenDialog(f);File file = fc.getSelectedFile();if (returnVal == JFileChooser.APPROVE_OPTION) {JOptionPane.showMessageDialog(f, "计划打开文件:" + file.getAbsolutePath());}}});bSave.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {int returnVal =  fc.showSaveDialog(f);File file = fc.getSelectedFile();if (returnVal == JFileChooser.APPROVE_OPTION) {JOptionPane.showMessageDialog(f, "计划保存到文件:" + file.getAbsolutePath());}}});}}

面板

基本面板

JPanel即为基本面板
面板和JFrame一样都是容器,不过面板一般用来充当中间容器,把组件放在面板上,然后再把面板放在窗体上。
一旦移动一个面板,其上面的组件,就会全部统一跟着移动,采用这种方式,便于进行整体界面的设计

package gui;import java.awt.Color;
import java.awt.FlowLayout;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(null);JPanel p1 = new JPanel();// 设置面板大小p1.setBounds(50, 50, 300, 60);// 设置面板背景颜色p1.setBackground(Color.RED);// 这一句可以没有,因为JPanel默认就是采用的FlowLayoutp1.setLayout(new FlowLayout());JButton b1 = new JButton("英雄1");JButton b2 = new JButton("英雄2");JButton b3 = new JButton("英雄3");// 把按钮加入面板p1.add(b1);p1.add(b2);p1.add(b3);JPanel p2 = new JPanel();JButton b4 = new JButton("英雄4");JButton b5 = new JButton("英雄5");JButton b6 = new JButton("英雄6");p2.add(b4);p2.add(b5);p2.add(b6);p2.setBackground(Color.BLUE);p2.setBounds(10, 150, 300, 60);// 把面板加入窗口f.add(p1);f.add(p2);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

ContentPane

JFrame上有一层面板,叫做ContentPane
平时通过f.add()向JFrame增加组件,其实是向JFrame上的 ContentPane加东西

package gui;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {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);// JFrame上有一层面板,叫做ContentPane// 平时通过f.add()向JFrame增加组件,其实是向JFrame上的 ContentPane加东西// f.add等同于f.getContentPane().add(b);f.getContentPane().add(b);// b.getParent()获取按钮b所处于的容器// 打印出来可以看到,实际上是ContentPane而非JFrameSystem.out.println(b.getParent());f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

SplitPanel

创建一个水平JSplitPane,左边是pLeft,右边是pRight

package gui;import java.awt.Color;
import java.awt.FlowLayout;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.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,右边是p2JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pLeft, pRight);// 设置分割条的位置sp.setDividerLocation(80);// 把sp当作ContentPanef.setContentPane(sp);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

JScrollPanel

使用带滚动条的面板有两种方式
1. 在创建JScrollPane,把组件作为参数传进去

JScrollPane sp = new JScrollPane(ta);

2. 希望带滚动条的面板显示其他组件的时候,调用setViewportView

sp.setViewportView(ta);

package gui;import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(null);//准备一个文本域,在里面放很多数据JTextArea ta = new JTextArea();for (int i = 0; i < 1000; i++) {ta.append(String.valueOf(i));}//自动换行ta.setLineWrap(true);JScrollPane sp = new JScrollPane(ta);f.setContentPane(sp);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

TabbedPanel

package gui;import java.awt.Color;
import java.awt.FlowLayout;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(null);JPanel p1 = new JPanel();p1.setBounds(50, 50, 300, 60);p1.setBackground(Color.RED);p1.setLayout(new FlowLayout());JButton b1 = new JButton("英雄1");JButton b2 = new JButton("英雄2");JButton b3 = new JButton("英雄3");p1.add(b1);p1.add(b2);p1.add(b3);JPanel p2 = new JPanel();JButton b4 = new JButton("英雄4");JButton b5 = new JButton("英雄5");JButton b6 = new JButton("英雄6");p2.add(b4);p2.add(b5);p2.add(b6);p2.setBackground(Color.BLUE);p2.setBounds(10, 150, 300, 60);JTabbedPane tp = new JTabbedPane();tp.add(p1);tp.add(p2);// 设置tab的标题tp.setTitleAt(0, "红色tab");tp.setTitleAt(1, "蓝色tab");ImageIcon i = new ImageIcon("e:/project/j2se/j.png");tp.setIconAt(0,i );tp.setIconAt(1,i );f.setContentPane(tp);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

CardLayerout

CardLayerout 布局器 很像TabbedPanel ,在本例里面上面是一个下拉框,下面是一个CardLayerout 的JPanel
这个JPanel里有两个面板,可以通过CardLayerout方便的切换

package gui;import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("CardLayerout");JPanel comboBoxPane = new JPanel();String buttonPanel = "按钮面板";String inputPanel = "输入框面板";String comboBoxItems[] = { buttonPanel, inputPanel };JComboBox<String> cb = new JComboBox<>(comboBoxItems);comboBoxPane.add(cb);// 两个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 CardLayoutcards = new JPanel(new CardLayout());cards.add(card1, buttonPanel);cards.add(card2, inputPanel);f.add(comboBoxPane, BorderLayout.NORTH);f.add(cards, BorderLayout.CENTER);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setSize(250, 150);f.setLocationRelativeTo(null);f.setVisible(true);cb.addItemListener(new ItemListener() {@Overridepublic void itemStateChanged(ItemEvent evt) {CardLayout cl = (CardLayout) (cards.getLayout());cl.show(cards, (String) evt.getItem());}});    }}

菜单

菜单栏和菜单

package gui;import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);// 菜单栏JMenuBar mb = new JMenuBar();// 菜单JMenu mHero = new JMenu("英雄");JMenu mItem = new JMenu("道具");JMenu mWord = new JMenu("符文");JMenu mSummon = new JMenu("召唤师");JMenu mTalent = new JMenu("天赋树");// 把菜单加入到菜单栏mb.add(mHero);mb.add(mItem);mb.add(mWord);mb.add(mSummon);mb.add(mTalent);// 把菜单栏加入到frame,这里用的是set而非addf.setJMenuBar(mb);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

菜单项

菜单项

package gui;import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 400);f.setLocation(200, 200);JMenuBar mb = new JMenuBar();JMenu mHero = new JMenu("英雄");JMenu mItem = new JMenu("道具");JMenu mWord = new JMenu("符文");JMenu mSummon = new JMenu("召唤师");JMenu mTalent = new JMenu("天赋树");// 菜单项mHero.add(new JMenuItem("近战-Warriar"));mHero.add(new JMenuItem("远程-Range"));mHero.add(new JMenuItem("物理-physical"));mHero.add(new JMenuItem("坦克-Tank"));mHero.add(new JMenuItem("法系-Mage"));mHero.add(new JMenuItem("辅助-Support"));mHero.add(new JMenuItem("打野-Jungle"));mHero.add(new JMenuItem("突进-Charge"));mHero.add(new JMenuItem("男性-Boy"));mHero.add(new JMenuItem("女性-Girl"));// 分隔符mHero.addSeparator();mHero.add(new JMenuItem("所有-All"));mb.add(mHero);mb.add(mItem);mb.add(mWord);mb.add(mSummon);mb.add(mTalent);f.setJMenuBar(mb);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

工具栏

package gui;import java.awt.BorderLayout;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);// 菜单addMenu(f);// 工具栏JToolBar tb = new JToolBar();// 为工具栏增加按钮JButton b1 = new JButton(new ImageIcon("e:/project/j2se/1.jpg"));JButton b2 = new JButton(new ImageIcon("e:/project/j2se/2.jpg"));JButton b3 = new JButton(new ImageIcon("e:/project/j2se/3.jpg"));JButton b4 = new JButton(new ImageIcon("e:/project/j2se/4.jpg"));JButton b5 = new JButton(new ImageIcon("e:/project/j2se/5.jpg"));JButton b6 = new JButton(new ImageIcon("e:/project/j2se/6.jpg"));tb.add(b1);tb.add(b2);tb.add(b3);tb.add(b4);tb.add(b5);tb.add(b6);// 把工具栏放在north的位置f.setLayout(new BorderLayout());f.add(tb, BorderLayout.NORTH);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}private static void addMenu(JFrame f) {JMenuBar mb = new JMenuBar();JMenu mHero = new JMenu("英雄");JMenu mItem = new JMenu("道具");JMenu mWord = new JMenu("符文");JMenu mSummon = new JMenu("召唤师");JMenu mTalent = new JMenu("天赋树");// 菜单项mHero.add(new JMenuItem("近战-Warriar"));mHero.add(new JMenuItem("远程-Range"));mHero.add(new JMenuItem("物理-physical"));mHero.add(new JMenuItem("坦克-Tank"));mHero.add(new JMenuItem("法系-Mage"));mHero.add(new JMenuItem("辅助-Support"));mHero.add(new JMenuItem("打野-Jungle"));mHero.add(new JMenuItem("突进-Charge"));mHero.add(new JMenuItem("男性-Boy"));mHero.add(new JMenuItem("女性-Girl"));mb.add(mHero);mb.add(mItem);mb.add(mWord);mb.add(mSummon);mb.add(mTalent);f.setJMenuBar(mb);}
}

给按钮设置提示信息

当鼠标放在按钮上的时候会出现提示

package gui;import java.awt.BorderLayout;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);addMenu(f);JToolBar tb = new JToolBar();JButton b1 = new JButton(new ImageIcon("e:/project/j2se/1.jpg"));JButton b2 = new JButton(new ImageIcon("e:/project/j2se/2.jpg"));JButton b3 = new JButton(new ImageIcon("e:/project/j2se/3.jpg"));JButton b4 = new JButton(new ImageIcon("e:/project/j2se/4.jpg"));JButton b5 = new JButton(new ImageIcon("e:/project/j2se/5.jpg"));JButton b6 = new JButton(new ImageIcon("e:/project/j2se/6.jpg"));tb.add(b1);tb.add(b2);tb.add(b3);tb.add(b4);tb.add(b5);tb.add(b6);// 给按钮设置提示信息b1.setToolTipText("坑爹英雄");// 把工具栏放在north的位置f.setLayout(new BorderLayout());f.add(tb, BorderLayout.NORTH);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}private static void addMenu(JFrame f) {JMenuBar mb = new JMenuBar();JMenu mHero = new JMenu("英雄");JMenu mItem = new JMenu("道具");JMenu mWord = new JMenu("符文");JMenu mSummon = new JMenu("召唤师");JMenu mTalent = new JMenu("天赋树");// 菜单项mHero.add(new JMenuItem("近战-Warriar"));mHero.add(new JMenuItem("远程-Range"));mHero.add(new JMenuItem("物理-physical"));mHero.add(new JMenuItem("坦克-Tank"));mHero.add(new JMenuItem("法系-Mage"));mHero.add(new JMenuItem("辅助-Support"));mHero.add(new JMenuItem("打野-Jungle"));mHero.add(new JMenuItem("突进-Charge"));mHero.add(new JMenuItem("男性-Boy"));mHero.add(new JMenuItem("女性-Girl"));mb.add(mHero);mb.add(mItem);mb.add(mWord);mb.add(mSummon);mb.add(mTalent);f.setJMenuBar(mb);}
}

禁止工具栏拖动

默认情况下 工具栏可以通过鼠标拖动

setFloatable(false);

可以禁止鼠标拖动功能

package gui;import java.awt.BorderLayout;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);addMenu(f);JToolBar tb = new JToolBar();JButton b1 = new JButton(new ImageIcon("e:/project/j2se/1.jpg"));JButton b2 = new JButton(new ImageIcon("e:/project/j2se/2.jpg"));JButton b3 = new JButton(new ImageIcon("e:/project/j2se/3.jpg"));JButton b4 = new JButton(new ImageIcon("e:/project/j2se/4.jpg"));JButton b5 = new JButton(new ImageIcon("e:/project/j2se/5.jpg"));JButton b6 = new JButton(new ImageIcon("e:/project/j2se/6.jpg"));tb.add(b1);tb.add(b2);tb.add(b3);tb.add(b4);tb.add(b5);tb.add(b6);b1.setToolTipText("坑爹英雄");// 禁止工具栏拖动tb.setFloatable(false);// 把工具栏放在north的位置f.setLayout(new BorderLayout());f.add(tb, BorderLayout.NORTH);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}private static void addMenu(JFrame f) {JMenuBar mb = new JMenuBar();JMenu mHero = new JMenu("英雄");JMenu mItem = new JMenu("道具");JMenu mWord = new JMenu("符文");JMenu mSummon = new JMenu("召唤师");JMenu mTalent = new JMenu("天赋树");// 菜单项mHero.add(new JMenuItem("近战-Warriar"));mHero.add(new JMenuItem("远程-Range"));mHero.add(new JMenuItem("物理-physical"));mHero.add(new JMenuItem("坦克-Tank"));mHero.add(new JMenuItem("法系-Mage"));mHero.add(new JMenuItem("辅助-Support"));mHero.add(new JMenuItem("打野-Jungle"));mHero.add(new JMenuItem("突进-Charge"));mHero.add(new JMenuItem("男性-Boy"));mHero.add(new JMenuItem("女性-Girl"));mb.add(mHero);mb.add(mItem);mb.add(mWord);mb.add(mSummon);mb.add(mTalent);f.setJMenuBar(mb);}
}

基本表格

显示一个Table需要两组数据
1. 一维数组: String[]columnNames 表示表格的标题
2. 二维数组: String[][] heros 表格中的内容
默认情况下,表格的标题是不会显示出来了,除非使用了JScrollPane

package gui;import java.awt.BorderLayout;import javax.swing.JFrame;
import javax.swing.JTable;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new BorderLayout());// 表格上的titleString[] columnNames = new String[] { "id", "name", "hp", "damage" };// 表格中的内容,是一个二维数组String[][] heros = new String[][] { { "1", "盖伦", "616", "100" },{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };JTable t = new JTable(heros, columnNames);f.add(t, BorderLayout.CENTER);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

JScrollPane

JScrollPane: 带滚动条的Panel
把table放进去就可以看到table的title
同样的把textarea放进去,并且textarea内容够长的话,就会看到滚动条

package gui;import java.awt.BorderLayout;import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new BorderLayout());String[] columnNames = new String[] { "id", "name", "hp", "damage" };String[][] heros = new String[][] { { "1", "盖伦", "616", "100" },{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };JTable t = new JTable(heros, columnNames);// 根据t创建 JScrollPaneJScrollPane sp = new JScrollPane(t);//或则创建一个空的JScrollPane,再通过setViewportView把table放在JScrollPane中// JScrollPane sp = new JScrollPane(t);// sp.setViewportView(t);// 把sp而非JTable加入到JFrame上,f.add(sp, BorderLayout.CENTER);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

列宽

设置列宽度

package gui;import java.awt.BorderLayout;import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new BorderLayout());String[] columnNames = new String[] { "id", "name", "hp", "damage" };String[][] heros = new String[][] { { "1", "盖伦", "616", "100" },{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };JTable t = new JTable(heros, columnNames);JScrollPane sp = new JScrollPane(t);// 设置列宽度t.getColumnModel().getColumn(0).setPreferredWidth(10);f.add(sp, BorderLayout.CENTER);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

TableModel

首先说下TableModel的设计思想,在Model这种思想的指导下,数据和显示分离开来了。 比如对于JTable而言,有数据部分,也有显示部分(比如列宽等信息)。 数据部分,专门做一个类,叫做TableModel,就用于存放要显示的数据。

使用TableModel的方式存放Table需要显示的数据
HeroTableModel 继承AbstractTableModel ,进而实现了接口TableModel
在HeroTableModel 中提供一个table显示需要的所有信息
1. getRowCount 返回一共有多少行
2. getColumnCount 返回一共有多少列
3. getColumnName 每一列的名字
4. isCellEditable 单元格是否可以修改
5. getValueAt 每一个单元格里的值

当图形界面需要渲染第一个单元格的数据的时候,就会调用方法TabelModel的getValueAt(0,0) ,把返回值拿到并显示

package gui;import javax.swing.table.AbstractTableModel;public class HeroTableModel extends AbstractTableModel {String[] columnNames = new String[] { "id", "name", "hp", "damage" };String[][] heros = new String[][] { { "1", "盖伦", "616", "100" },{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };// 返回一共有多少行public int getRowCount() {// TODO Auto-generated method stubreturn heros.length;}// 返回一共有多少列public int getColumnCount() {// TODO Auto-generated method stubreturn columnNames.length;}// 获取每一列的名称public String getColumnName(int columnIndex) {// TODO Auto-generated method stubreturn columnNames[columnIndex];}// 单元格是否可以修改public boolean isCellEditable(int rowIndex, int columnIndex) {return false;}// 每一个单元格里的值public Object getValueAt(int rowIndex, int columnIndex) {// TODO Auto-generated method stubreturn heros[rowIndex][columnIndex];}}package gui;import java.awt.BorderLayout;import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(200, 200);f.setLayout(new BorderLayout());//创建一个TableModelHeroTableModel htm= new HeroTableModel();//根据 TableModel来创建 TableJTable t = new JTable(htm);JScrollPane sp = new JScrollPane(t);f.add(sp, BorderLayout.CENTER);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

Swing中的线程

三种线程

在Swing程序的开发中,需要建立3种线程的概念
1. 初始化线程
初始化线程用于创建各种容器,组件并显示他们,一旦创建并显示,初始化线程的任务就结束了。

2. 事件调度线程
通过事件监听的学习,我们了解到Swing是一个事件驱动的模型,所有和事件相关的操作都放是放在事件调度线程 (Event Dispatch)中进行的。比如点击一个按钮,对应的ActionListener.actionPerformed 方法中的代码,就是在事件调度线程 Event Dispatch Thread中执行的。

3. 长耗时任务线程
有时候需要进行一些长时间的操作,比如访问数据库,文件复制,连接网络,统计文件总数等等。 这些操作就不适合放在事件调度线程中进行,因为占用时间久了,会让使用者感觉界面响应很卡顿。 为了保持界面响应的流畅性,所有长耗时任务都应该放在专门的 长耗时任务线程中进行

事件调度线程是单线程的

在开始讲解这3种线程之前, 要建立一个概念: 事件调度线程是单线程的。
为什么呢?
这是因为 Swing里面的各种组件类,比如JTextField,JButton 都不是线程安全的,这就意味着,如果有多个线程,那么同一个JTextField的setText方法,可能会被多个线程同时调用,这会导致同步问题以及错误数据的发生。

如果把组件类设计成为线程安全的,由于Swing事件调度的复杂性,就很有可能导致死锁的发生。

为了规避同步问题,以及降低整个Swing设计的复杂度,提高Swing的相应速度,Swing中的 事件调度线程被设计成为了单线程模式,即只有一个线程在负责事件的响应工作。

初始化线程

顶折

如代码所示,同时我们在初始化一个图形界面的时候,都会直接在主方法的主线程里,直接调用如下代码来进行初始化

new TestFrame().setVisible(true);

如果是小程序这没有什么问题,如果是复杂的程序就有可能产生问题了。因为这里有两个线程在同时访问组件:1. 主线程 2. 事件调度线程。 如果是复杂的图形界面程序,就有可能出现这两个线程同时操作的情况,导致同步问题的产生。

为了规避这个问题的产生,创建和显示界面的工作,最好也交给事件调度线程,这样就保证了只有一个线程在访问这些组件

SwingUtilities.invokeLater(new Runnable() {

public void run() {

new TestFrame().setVisible(true);

}

});

像这样,new TestFrame().setVisible(true); 这段代码就是在事件调度线程中执行了。

还可以使用SwingUtilities.isEventDispatchThread()来判断当前线程是否是事件调度线程

package gui;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;public class TestGUI {public static void main(String[] args) {new TestFrame().setVisible(true);//      SwingUtilities.invokeLater(new Runnable() {
//          public void run() {
//              new TestFrame().setVisible(true);
//          }
//      });}static class TestFrame extends JFrame {public TestFrame() {setTitle("LoL");setSize(400, 300);setLocation(200, 200);setLayout(null);JButton b = new JButton("一键秒对方基地挂");b.setBounds(50, 50, 280, 30);add(b);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setVisible(true);System.out.println("当前线程是否是 事件调度线程: " + SwingUtilities.isEventDispatchThread());}}
}

事件调度线程

以 按钮监听 中的代码为例,ActionListener.actionPerformed 中的代码,就是事件调度线程执行的。

可以借助SwingUtilities.isEventDispatchThread() 确认,是事件调度线程在执行相应的代码

那么事件调度线程又是如何去执行这段代码的呢? 这就不用你操心啦, 要解释这个问题,就需要剖析整个Swing的框架,就不是本章节所能展示的内容啦

package gui;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(400, 300);f.setLocation(580, 200);f.setLayout(null);final JLabel l = new JLabel();ImageIcon i = new ImageIcon("e:/project/j2se/shana.png");l.setIcon(i);l.setBounds(50, 50, i.getIconWidth(), i.getIconHeight());JButton b = new JButton("隐藏图片");b.setBounds(150, 200, 100, 30);b.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {l.setVisible(false);System.out.println("当前使用的是事件调度线程:" + SwingUtilities.isEventDispatchThread());}});f.add(l);f.add(b);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}
}

步骤 5 :

长耗时任务线程

有时候需要执行长耗时任务,比如数据库查询,文件复制,访问网络等等。

而这些操作一般都会在事件响应后发起,就会自动进入事件调度线程。 而事件调度线程又是单线程模式,其结果就会是在执行这些长耗时任务的时候,界面就无响应了。

如图所示,当点击第一个按钮的时候,会在其中进行一个5秒钟的任务,这个期间,第一个按钮会保持按下状态,其他按钮也无法点击,出现了无响应了状态。

为了解决这个问题,Swing提供了一个SwingWorker类来解决。 SwingWorker是一个抽象类,为了使用,必须实现方法 doInBackground,在doInBackground中,就可以编写我们的任务,然后执行SwingWorker的execute方法,放在专门的工作线程中去运行。

SwingWorker worker = new SwingWorker() {

protected Object doInBackground() throws Exception {

//长耗时任务

return null;

}

};

worker.execute();

SwingWorker又是如何工作的呢?
当SwingWorker执行execute的时候,调用默认有10根线程的线程池,执行doInBackground中的代码,通过如下代码,可以获知执行当前SwingWorder的线程名称

System.out.println("执行这个SwingWorder的线程是:" + Thread.currentThread().getName());

package gui;import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;public class TestGUI {public static void main(String[] args) {JFrame f = new JFrame("LoL");f.setSize(300, 300);f.setLocation(200, 200);f.setLayout(new FlowLayout());JButton b1 = new JButton("在事件调度线程中执行长耗时任务");JButton b2 = new JButton("使用SwingWorker执行长耗时任务");JLabel l = new JLabel("任务执行结果");f.add(b1);f.add(b2);f.add(l);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);b1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {l.setText("开始执行完毕");try {Thread.sleep(5000);} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}l.setText("任务执行完毕");}});b2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {@Overrideprotected Void doInBackground() throws Exception {System.out.println("执行这个SwingWorder的线程是:" + Thread.currentThread().getName());l.setText("开始执行完毕");try {Thread.sleep(5000);} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}l.setText("任务执行完毕");return null;}};worker.execute();}});f.setVisible(true);}
}

设置皮肤

只需要提供一句代码

javax.swing.UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel");

就可以把所有的组件切换成不同的风格。

注: 这句话需要加在最前面,如果已经创建了界面,再加这个有时候不能正常起作用。

package gui;import javax.swing.JButton;
import javax.swing.JFrame;public class TestGUI {public static void main(String[] args) {//设置皮肤setLookAndFeel();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);}private static void setLookAndFeel() {try {javax.swing.UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.smart.SmartLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.mcwin.McWinLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.luna.LunaLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.aluminium.AluminiumLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.bernstein.BernsteinLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.hifi.HiFiLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.mint.MintLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.aero.AeroLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.fast.FastLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.acryl.AcrylLookAndFeel");
//          javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.noire.NoireLookAndFeel");} catch (Exception e) {e.printStackTrace();// handle exception}}
}

JAVA中级之图形界面相关推荐

  1. 【JAVA】基本图形界面设计

    [JAVA]基本图形界面设计 基本知识点 JAVA中的组件包: 1:采用java.awt.*(abstract Windowing Toolkit) 2:采用javax.swing.* 特点: 前者: ...

  2. java中的图形界面编辑界面_第58节:Java中的图形界面编程-GUI

    欢迎到我的简书查看我的文集 前言: GUI是图形用户界面,在Java中,图形用户界面我们用GUI表示,而GUI的完整英文为: Graphical User Interface(图形用户接口), 所谓图 ...

  3. java转成图形界面_【转】java图形界面设计(AWT)

    [转自]http://blog.sina.com.cn/s/blog_616e189f0100ne1t.html 1.       基本的java Frame操作. Java的图形界面的类主要包括AW ...

  4. 求java用人民币来转换美元,NJUPT JAVA语言 综合图形界面程序设计

    一. 实验目的和要求 学习和理解JAVA SWING中的容器,部件,布局管理器和部件事件处理方法. 通过编写和调试程序,掌握JAVA图形界面程序设计的基本方法. 实验内容: 设计和编写一个用于将人民币 ...

  5. java怎么开发图形界面_Java Swing 图形界面开发简介

    1. Swing简介 Swing 是 Java 为图形界面应用开发提供的一组工具包,是 Java 基础类的一部分. Swing 包含了构建图形界面(GUI)的各种组件,如: 窗口.标签.按钮.文本框等 ...

  6. 第58节:Java中的图形界面编程-GUI

    欢迎到我的简书查看我的文集 前言: GUI是图形用户界面,在Java中,图形用户界面我们用GUI表示,而GUI的完整英文为: Graphical User Interface(图形用户接口), 所谓图 ...

  7. Java中的图形界面编程-GUI

    欢迎到我的简书查看我的文集 前言: GUI是图形用户界面,在Java中,图形用户界面我们用GUI表示,而GUI的完整英文为: Graphical User Interface(图形用户接口), 所谓图 ...

  8. java山寨qq_java图形界面之 山寨QQ登陆界面

    要山寨出QQ登陆界面,首先要对java的图形界面有一定的了解.在jdk1.4之前,图形界面所用到的所有类和接口都在javax.awt之下,在其之后就都在javax.swing里了. 关于图形界面的开发 ...

  9. java复习之图形界面设计

    图形界面设计 AWT和Swing 组件 顶层容器 JFrame类常用的构造方法 内容窗格 面板 JPanel类常用的构造方法 AWT滚动条组件 标签 按钮 JButton构造方法 JButton类常用 ...

最新文章

  1. ASP.NET Razor – 标记简介
  2. 常州IBMV3700数据恢复成功
  3. mysql mediumtext longtext
  4. 小学生学python-小学生都学Python了,你还不知道如何开始
  5. 测试机的版本高于Xcode的版本的解决方法
  6. 工作与生活的平衡-一些955的良心公司
  7. boost::gil::color_spaces_are_compatible用法的测试程序
  8. SAP Fiori Elements 里 Smart Table column 的宽度问题
  9. mysql优化 运维_MySQL运维---MySQL优化
  10. goldengate简单配置
  11. 在access窗体中加图片_如何在Access窗体中显示指定路径的图片
  12. 淘宝宝贝类目怎么更换?
  13. 2串口两串口三串口多串口3串口转WiFi透传模块实现多通道与服务器透传
  14. 用Python玩转数据(一)
  15. S7-300 PLC的一次系统故障
  16. 过桥问题--马儿赛跑问题--智力题
  17. 【esp32-adf】按键服务源码分析
  18. 弘辽科技:千人千面你理解清楚了吗?
  19. DOCTYPE与怪异模式
  20. php递归函数的理解

热门文章

  1. 从新东方被裁转行互联网。月薪过万,入职百度外包的真实感受。
  2. 一区即将要洗的DVD片子
  3. 稀疏数组,稀疏矩阵概念
  4. 报错:[plugin:vite:import-analysis] Failed to resolve import “./Child“ from “src\views\home.vue“. Doe
  5. 腾讯QQ到底有多强大?
  6. 安裝Drupal 7简体中文版
  7. javancss中的NCSS和CCN
  8. Redis 过期Expires
  9. [百度]2014百度校园招聘之最长回文串
  10. 外汇天眼:美国通胀数据公布前,诸央行消息甚嚣尘上