GUI编程
简介
GUI:图形用户界面编程
Gui的核心技术 : Swing AWT
但不太流行因为
- 界面不美观
- 需要jre环境
但它可以写出自己心中想要的小工具,了解MVC架构,了解监听
AWT
awt是一个对象,意思是抽象的窗口工具,包含了很多的类和方法
有很多元素:窗口,按钮,文本框
组件和容器
Frame
import java.awt.*;
public class Test01 {
public static void main(String[] args) {
//Frame 可以看jdk帮助文档,也可以看源码,建议直接读源码
Frame frame = new Frame("我的第一个窗口");
//需要设置可见性
frame.setVisible(true);
//设置窗口大小
frame.setSize(400,400);
//设置窗口颜色 这里需要一个 color类,直接点进去看源码,就能找到想要的颜色
//frame.setBackground(Color.pink);这是固定的颜色,也可以自己随意设置
frame.setBackground(new Color(200, 108, 232));
//弹出的初始位置
frame.setLocation(200,200);
//设置是否可以改变窗口大小
frame.setResizable(true);
}
}
运行结果为:
那如何创建多个窗口呢,就需要用到封装的思想
import java.awt.*;
public class Test02 {
public static void main(String[] args) {
MyFrame myFrame1 = new MyFrame(100,100,200,200,Color.BLACK);
MyFrame myFrame2 = new MyFrame(300,100,200,200,Color.pink);
MyFrame myFrame3 = new MyFrame(100,300,200,200,Color.blue);
}
}
class MyFrame extends Frame {
static int id = 0;//可能存在多个窗口,用一个计数器记录
//设置一个方法,封装之前的基本设置
public MyFrame(int x, int y, int w, int h,Color color) {
super("My frame+"+(++id));
setBackground(color);
setBounds(x, y, w, h);
setVisible(true);
}
}
窗口关不掉因为我们没有设置,直接终止程序就好了
面板Panel
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Test03 {
public static void main(String[] args) {
Frame frame = new Frame();
//布局的概念
Panel panel = new Panel();
//设置布局
frame.setLayout(null);
//设置坐标
frame.setBounds(200,200,400,400);
frame.setBackground(Color.orange);
//panel设置坐标
panel.setBounds(20,40,300,50);
panel.setBackground(Color.RED);
//把panel放在窗口里,可以通过源码知道panel也是一个Component
frame.add(panel);
//可见性
frame.setVisible(true);
//通过增加监听事件来关闭窗口,System.exit(0);
//用适配器模式来取消大量重写
frame.addWindowListener(new WindowAdapter() {
//窗口点击关闭的时候做什么事
@Override
public void windowClosing(WindowEvent e) {
//super.windowClosing(e);
System.exit(0);
}
});
}
}
解决了关闭问题,结果如下:
布局管理器
-
流式布局
import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class TestFlowLayout { public static void main(String[] args) { Frame frame = new Frame(); //组件 - 按钮 Button button1 = new Button("01"); Button button2 = new Button("02"); Button button3 = new Button("03"); //设置为流式布局 //frame.setLayout(new FlowLayout()); //可以增加参数来让布局内按钮靠左,默认是居中 frame.setLayout(new FlowLayout(FlowLayout.LEFT)); frame.setSize(400,400); //添加按钮 frame.add(button1); frame.add(button2); frame.add(button3); //可见性 frame.setVisible(true); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } }
-
东西南北中
import java.awt.*; public class TestBorderLayout { public static void main(String[] args) { Frame frame = new Frame("BorderLayout"); Button button1 = new Button("east"); Button button2 = new Button("west"); Button button3 = new Button("south"); Button button4 = new Button("north"); Button button5 = new Button("center"); frame.add(button1,BorderLayout.EAST); frame.add(button2,BorderLayout.WEST); frame.add(button3,BorderLayout.SOUTH); frame.add(button4,BorderLayout.NORTH); frame.add(button5,BorderLayout.CENTER); frame.setVisible(true); frame.setSize(400,400); } }
-
表格布局
import java.awt.*; public class TestGridLayout { public static void main(String[] args) { Frame frame = new Frame(); frame.setSize(400,400); Button btn1 = new Button("btn1"); Button btn2 = new Button("btn2"); Button btn3 = new Button("btn3"); Button btn4 = new Button("btn4"); //设置一个表格布局,具体参数源码一看便知 frame.setLayout(new GridLayout(2,2)); frame.add(btn1); frame.add(btn2); frame.add(btn3); frame.add(btn4); //frame.pack();//这是一个java函数,自动整好看一点,在你没有设置窗口大小时候 frame.setVisible(true); } }
复杂的布局也都是由简单布局拼凑而成
举个例子
import java.awt.*;
public class TestWorkLayout {
public static void main(String[] args) {
Frame frame = new Frame("test");
frame.setSize(600,400);
frame.setLayout(new GridLayout(2,1));
frame.setVisible(true);
//four panel
Panel panel1 = new Panel(new BorderLayout());
Panel panel2 = new Panel(new BorderLayout());
Panel panel3 = new Panel(new GridLayout(2,1));
Panel panel4 = new Panel(new GridLayout(2,2));
panel1.add(new Button("1"),BorderLayout.WEST);
panel1.add(new Button("2"),BorderLayout.EAST);
panel3.add(new Button("1"));
panel3.add(new Button("2"));
panel1.add(panel3,BorderLayout.CENTER);
panel2.add(new Button("1"),BorderLayout.WEST);
panel2.add(new Button("2"),BorderLayout.EAST);
panel4.add(new Button("1"));
panel4.add(new Button("2"));
panel4.add(new Button("3"));
panel4.add(new Button("4"));
panel2.add(panel4,BorderLayout.CENTER);
frame.add(panel1);
frame.add(panel2);
}
}
事件监听
当某个事情发生的时候,干什么,就是事件监听。
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestAction01 {
public static void main(String[] args) {
//按下按钮,触发一些事件
Frame frame = new Frame();
Button button = new Button("button");
//因为.addActionListener();需要一个ActionListener所以我们创建一个类
MyActionListener myActionListener = new MyActionListener();
button.addActionListener(myActionListener);
frame.add(button,BorderLayout.CENTER);
frame.setSize(400,200);
close(frame);
frame.setVisible(true);
}
//把关闭窗口抽取成一个方法
private static void close(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("aaa");
}
}
那如果让两个按钮监听一个事件呢,比如一个管开始,一个管关闭
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestAction {
public static void main(String[] args) {
Frame frame = new Frame("start - close");
frame.pack();
frame.setVisible(true);
Button button1 = new Button("start");
Button button2 = new Button("close");
MyListener myListener = new MyListener();
button1.addActionListener(myListener);
button2.addActionListener(myListener);
frame.add(button1,BorderLayout.NORTH);
frame.add(button2,BorderLayout.SOUTH);
}
}
class MyListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被按了 + "+e.getActionCommand());
}
}
读者可以自行演示,结果如下
按钮被按了 + close
按钮被按了 + start
输入框TextField
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestText {
public static void main(String[] args) {
//main只用做启动,
MyFrame frame = new MyFrame();
close(frame);
}
public static void close(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyFrame extends Frame {
public MyFrame(){
TextField textField = new TextField();
add(textField);
//监听文本框输入
MyListener1 myListener1 = new MyListener1();
//按下enter就会触发输入框的事件
textField.addActionListener(myListener1);
//设置替换编码
textField.setEchoChar('*');
setVisible(true);
pack();
}
}
class MyListener1 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
TextField field = (TextField) e.getSource();//获得一些资源,返回一个类
System.out.println(field.getText());//打印输入框获得的文本
field.setText("");//设置为空,不能是null
}
}
简易计算器
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//简易计算器
public class TestCalc {
public static void main(String[] args) {
new Calculator();
}
}
//计算器类
class Calculator extends Frame{
public Calculator(){
//3个文本框
TextField num1 = new TextField(10);
TextField num2 = new TextField(10);
TextField num3 = new TextField(20);
//1个按钮
Button button = new Button("=");
//为了让结果出来,需要加一个监听事件
button.addActionListener(new CalculatorListener(num1,num2,num3));
//1个标签
Label label = new Label("+");
//布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
}
//监听器类
class CalculatorListener implements ActionListener{
//获取三个变量
private TextField num1,num2,num3;
public CalculatorListener(TextField num1,TextField num2,TextField num3){
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}
@Override
public void actionPerformed(ActionEvent e) {
//1.获得加数和被加数,因为要转换成int类型才能运算
//创建i1,用textField1.getText()获取输入的string类型,然后用Integer.parseInt来转换成int类型
int i1 = Integer.parseInt(num1.getText());
int i2 = Integer.parseInt(num2.getText());
//2.将这两个数加起来,传到第三个框内
num3.setText(""+(i1+i2));
//3.把前两个文本框清除
num1.setText("");
num2.setText("");
}
}
显示结果
这个代码可以优化,更加专业版本:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//简易计算器
public class TestCalc {
public static void main(String[] args) {
new Calculator().loadCalculator();
}
}
//计算器类
class Calculator extends Frame{
//属性
TextField num1,num2,num3;
//方法
public void loadCalculator(){
//组件先写好
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(20);
Button button = new Button("=");
Label label = new Label("+");
//监听器写好
button.addActionListener(new CalculatorListener(this));
//布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
}
//监听器类
class CalculatorListener implements ActionListener{
//获取计算器这个类,在一个类里组合另一个类
Calculator calculator = null;
public CalculatorListener(Calculator calculator){
this.calculator = calculator;
}
@Override
public void actionPerformed(ActionEvent e) {
int i1 = Integer.parseInt(calculator.num1.getText());
int i2 = Integer.parseInt(calculator.num2.getText());
calculator.num3.setText(""+(i1+i2));
calculator.num1.setText("");
calculator.num2.setText("");
}
}
这就是面向对象的写法,面向对象才是java真正的重点
但这个代码还可以优化,这就要用到内部类
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//简易计算器
public class TestCalc {
public static void main(String[] args) {
new Calculator().loadCalculator();
}
}
//计算器类
class Calculator extends Frame{
//属性
TextField num1,num2,num3;
//方法
public void loadCalculator(){
//组件先写好
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(20);
Button button = new Button("=");
Label label = new Label("+");
//监听器写好
button.addActionListener(new CalculatorListener());
//布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
//监听器类
//内部类最好的地方就是可以畅通无阻的访问外部类
private class CalculatorListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
int i1 = Integer.parseInt(num1.getText());
int i2 = Integer.parseInt(num2.getText());
num3.setText(""+(i1+i2));
num1.setText("");
num2.setText("");
}
}
}
画笔
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestPaint {
public static void main(String[] args) {
new MyPaint().loadPaint();
}
}
class MyPaint extends Frame{
public void loadPaint(){
setBounds(200,200,800,600);
setVisible(true);
}
@Override
public void paint(Graphics g) {
//画笔可以画画,要设置颜色
g.setColor(Color.GREEN);
//g.fill是画实心图案,g.draw是画空心
g.fillOval(100,100,100,100);
g.setColor(Color.blue);
g.drawRect(300,300,100,100);
}
}
实现效果:
鼠标监听
目标:试图实现鼠标画画
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
public class TestMouse {
public static void main(String[] args) {
new MyFrame("paint");
}
}
class MyFrame extends Frame{
//需要画笔,需要鼠标监听位置,需要集合存储
ArrayList points;
public MyFrame(String title) {
super(title);
setBounds(200,200,600,400);
//存鼠标的点
points = new ArrayList<>();
setVisible(true);
//鼠标监听器,正对这个窗口
this.addMouseListener(new MyMouseListener());
}
@Override
public void paint(Graphics g) {
Iterator iterator = points.iterator();
while ((iterator.hasNext())){
Point point = (Point)iterator.next();
g.setColor(Color.red);
g.fillOval(point.x, point.y,10,10);
}
}
public void addPaint(Point point){
points.add(point);
}
private static class MyMouseListener extends MouseAdapter{
@Override
public void mousePressed(MouseEvent e) {
MyFrame framer = (MyFrame) e.getSource();
framer.addPaint(new Point(e.getX(),e.getY()));
framer.repaint();
}
}
}
实现结果:
实现思路:
-
需要一个页面,需要一个画笔,需要一个集合存储,需要一个鼠标监听器
-
设计界面,设计集合,用集合来存储画笔画的东西,
-
监听鼠标,把监听到的位置发送给集合,刷新画笔
-
把画出的点在窗口上实现
窗口监听
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestWindow {
public static void main(String[] args) {
new WindowFrame();
}
}
class WindowFrame extends Frame{
public WindowFrame(){
setBounds(100,100,400,400);
setBackground(Color.CYAN);
setVisible(true);
this.addWindowListener(
//匿名内部类
new WindowAdapter(){
//最常用的两个
@Override
public void windowClosing(WindowEvent e) {
System.out.println("windowClosing");
System.exit(0);
}
@Override
public void windowActivated(WindowEvent e) {
System.out.println("windowActivated");
}
}
);
}
}
键盘监听
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class TestKey {
public static void main(String[] args) {
new KeyFrame();
}
}
class KeyFrame extends Frame{
public KeyFrame(){
setSize(400,400);
setVisible(true);
this.addKeyListener(
new KeyAdapter() {
//见方法名称即知,按压效果
@Override
public void keyPressed(KeyEvent e) {
//获得按下的键是哪一个键
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_UP){
System.out.println("你按了上键");
}
}
}
);
}
}
Swing
窗口,面板
import javax.swing.*;
import java.awt.*;
public class JFrameTest01 {
public static void main(String[] args) {
new MyJFrame().init();
}
}
class MyJFrame extends JFrame {
public void init(){
setTitle("title");
setBounds(100,100,300,300);
setVisible(true);
//设置文字
JLabel label = new JLabel("真神奇");
//设置居中
label.setHorizontalAlignment(SwingConstants.CENTER);
add(label);
//获得一个容器
Container container = this.getContentPane();
container.setBackground(Color.CYAN);
//关闭事件
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
这里有一个容器的思想,JFrame是顶级容器,需要设置容器才能设置颜色,其他的与之前的Frame并无不同
弹窗
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Dialog extends JFrame {
public static void main(String[] args) {
new Dialog();
}
public Dialog(){
this.setVisible(true);
this.setSize(300,300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//JFrame放东西的容器
Container container = this.getContentPane();
//绝对布局
container.setLayout(null);
//设置按钮
JButton button = new JButton("弹出");
//因为绝对布局,所以直接设置固定位置就好了
button.setBounds(10,10,100,20);
//点击这个按钮弹出一个弹窗,设置监听
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//需要一个弹窗
new MyDialog();
}
});
container.add(button);
}
private static class MyDialog extends JDialog{
public MyDialog() {
setVisible(true);
setBounds(100,100,300,300);
Container container = getContentPane();
container.setLayout(null);
}
}
}
标签
Icon
import javax.swing.*;
import java.awt.*;
public class IconTest extends JFrame implements Icon {
private int Width;
private int Height;
public IconTest() {}//无参构造
public IconTest(int Width,int Height) {
this.Height = Height;
this.Width = Width;
}
public void init(){
IconTest iconTest = new IconTest(15, 15);
//图标放在标签上,也可以放在按钮上
JLabel jLabel = new JLabel("icon", iconTest, SwingConstants.CENTER);
Container container = getContentPane();
container.add(jLabel);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.fillOval(x,y,Width,Height);
}
@Override
public int getIconWidth() {
return this.Width;
}
@Override
public int getIconHeight() {
return this.Height;
}
public static void main(String[] args) {
new IconTest().init();
}
}
ImageIcon
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class ImageIconTest extends JFrame{
public ImageIconTest() {
//获取图片地址
JLabel label = new JLabel("ImageIcon");
URL url = ImageIconTest.class.getResource("tp.jpg");
ImageIcon imageIcon = new ImageIcon(url);
label.setIcon(imageIcon);
label.setHorizontalAlignment(SwingConstants.CENTER);
Container container = getContentPane();
container.add(label);
setBounds(100,100,400,400);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new ImageIconTest();
}
}
这里有个细节,图片要放到src目录下面才行
看起来在L4里面,其实不是
面板
JPanel
import javax.swing.*;
import java.awt.*;
public class JPanelTest extends JFrame {
public JPanelTest() {
Container container = getContentPane();
container.setLayout(new GridLayout(2,1,10,10));
JPanel jPanel = new JPanel(new GridLayout(1,2));
jPanel.add(new JButton("1"));
jPanel.add(new JButton("2"));
container.add(jPanel);
this.setSize(300,200);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JPanelTest();
}
}
ps:没什么意思,之前会了这也会,就是个容器加JPanel
JScrollPanel
import javax.swing.*;
import java.awt.*;
public class JScrollTest extends JFrame {
public JScrollTest() {
Container container = this.getContentPane();
this.setSize(400,200);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//文本域
JTextArea textArea = new JTextArea(50,50);
textArea.setText("在这里哦");
//Scroll面板
JScrollPane scrollPane = new JScrollPane(textArea);
container.add(scrollPane);
}
public static void main(String[] args) {
new JScrollTest();
}
}
显示为:
按钮
图片按钮
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class JButtonTest extends JFrame {
public JButtonTest() {
Container container = this.getContentPane();
//将一个图片变成图标
URL url = JButtonTest.class.getResource("tp.jpg");
Icon icon = new ImageIcon(url);
//把这个图标放在按钮上
JButton jButton = new JButton();
jButton.setIcon(icon);
jButton.setToolTipText("图片按钮");
//add
container.add(jButton);
this.setSize(400,200);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JButtonTest();
}
}
单选按钮
import javax.swing.*;
import java.awt.*;
public class JButtonTest02 extends JFrame {
public JButtonTest02() {
Container container = this.getContentPane();
this.setSize(400,200);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JRadioButton button1 = new JRadioButton("1");
JRadioButton button2 = new JRadioButton("2");
JRadioButton button3 = new JRadioButton("3");
//单选框只能选一个,所以用分组实现,一个分组里只能选择一个
ButtonGroup group = new ButtonGroup();
group.add(button1);
group.add(button2);
group.add(button3);
container.add(button1,BorderLayout.SOUTH);
container.add(button2,BorderLayout.NORTH);
container.add(button3,BorderLayout.CENTER);
}
public static void main(String[] args) {
new JButtonTest02();
}
}
复选按钮
import javax.swing.*;
import java.awt.*;
public class JButton03 extends JFrame {
public JButton03() {
Container container = this.getContentPane();
this.setSize(400,200);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JCheckBox box01 = new JCheckBox("Box01");
JCheckBox box02 = new JCheckBox("Box02");
container.add(box01,BorderLayout.SOUTH);
container.add(box02,BorderLayout.NORTH);
}
public static void main(String[] args) {
new JButton03();
}
}
列表
下拉框
import javax.swing.*;
import java.awt.*;
public class JComboBoxTest extends JFrame{
public JComboBoxTest() {
Container container = this.getContentPane();
this.setBounds(100,100,400,200);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JComboBox comboBox = new JComboBox();
comboBox.addItem(null);
comboBox.addItem("start");
comboBox.addItem("half");
comboBox.addItem("finish");
container.add(comboBox);
}
public static void main(String[] args) {
new JComboBoxTest();
}
}
列表框
列表框就是生成一个列表,然后存放东西。
比如存放数组:String[] contents = {“1”,“2”,“3”};
JList jlist = new JList(contents);
container.add(jlist);
这样就行了,存放别的类型,就设置别的类型列表就好了
- 应用场景:
- 选择地区,或一些单个选项
- 列表,展示信息,一般是动态扩容的
文本框
-
普通文本框
和之前一样,只不过这里是JTextField,如果多个文本记得布局
-
密码框
也很简单,new JPasswordField();默认***
-
文本域
参考JScrollPanel,里面有涉及。