GUI学习
GUI学习
前言:本来不打算学习Gui的,不过最近需要用到还是学习一下吧
1.1 awt 与swing
java的图形化界面的对象存在于awt与swing包中,awt需要调用本地系统方法实现功能,在不同的
平台下显示不同,swing是在awt的基础上实现的一套图形化界面,提供了更多组件,由于全部都适
用java完成,所以在不同平台下显示相同,这就给移植到不同平台提供了可能。
在java gui中,所有的内容都是通过组件实现的。组件和容器
1.2 Frame的使用
package com.ch2;
import javax.swing.*;
import java.awt.*;
public class Gui {
public static void main(String[] args){
Frame frame =new Frame("first gui");
frame.setVisible(true);//可视化
frame.setSize(300,300);
frame.setBackground(new Color(135, 36, 36));//背景颜色
frame.setLocation(100,100);//窗口位置
frame.setResizable(false);//不能缩放大小
}
}
通过上述操作,我们就生成了一个窗口,并设定了大小,背景颜色等
每次都要初始化比较麻烦,我们通过继承进行封装
package com.ch2;
import java.awt.*;
public class Test {
public static void main(String[] args)
{
new Nframe(100,200,300,200);
new Nframe(380,200,300,200);
new Nframe(700,200,300,200);
}
}
class Nframe extends Frame{
static int id=0;
public Nframe(int x,int y,int w,int h){
super("Frame"+id++);
this.setVisible(true);
this.setBounds(x,y,w,h);
this.setBackground(new Color(241, 232, 232));
}
}
1.3 Panel的使用
package com.ch2;
import javax.swing.*;
import java.awt.*;
public class Gui {
public static void main(String[] args) {
Frame frame =new Frame();
Panel panel=new Panel();
frame.setLayout(null);
frame.setBackground(Color.red);
frame.setBounds(100,100,500,500);
panel.setBackground(Color.blue);
panel.setBounds(10,10,500,500);
frame.add(panel);
panel.setVisible(true);
frame.setVisible(true);
}
}
panel并不像frame一样直接具有可见性,想要利用panel必须将其添加到容器中比如frame我们在
设置panel时 panel.setBounds(10,10,500,500);选定的是相对其父容器的位置,也就是0,0点是该
frame的左上角
1.4 关闭窗口
就比如我们上面的那个窗口,如果我们想要关闭需要怎么操作呢
package com.ch2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Gui {
public static void main(String[] args) {
Frame frame =new Frame();
Panel panel=new Panel();
frame.setLayout(null);
frame.setBackground(Color.red);
frame.setBounds(100,100,500,500);
panel.setBackground(Color.blue);
panel.setBounds(10,10,500,500);
frame.add(panel);
panel.setVisible(true);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
向窗口中添加一个窗口监听器,重写在点击关闭键时需要调用的方法,我们这里只需要关闭当前窗
口即可。
1.5 布局方式
流式布局
package com.ch2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Gui {
public static void main(String[] args) {
Frame frame =new Frame();
Panel panel=new Panel();
frame.setLayout(null);
frame.setBackground(new Color(248, 244, 244));
frame.setBounds(100,100,500,500);
// panel.setBackground(Color.blue);
// panel.setBounds(10,10,500,500);
// frame.add(panel);
// panel.setVisible(true);
frame.setVisible(true);
Button button1 = new Button("Button1");
Button button2 = new Button("Button2");
frame.add(button1);
frame.add(button2);
frame.setLayout(new FlowLayout());//流式布局
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
当我们向面板中添加比如按钮等组件时(这里先放在窗口中),需要设置组件的布局方式,即这些组件需要放
的位置,通过setLayout(); 来设置,我们先学习流式布局 即FlowLayout(),按行从上到下进行布局,一行满
了进入下一行,如果不加参数的话,默认情况下在同一行是进行居中放置的。
我们想要靠右可以new FlowLayout(FlowLayout.RIGHT)
靠左同理
东西南北中布局
如果我们想要让组件按东西南北中分布,则可以像下面这样操作
package com.ch2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Gui {
public static void main(String[] args) {
Frame frame =new Frame();
Panel panel=new Panel();
frame.setBackground(new Color(248, 244, 244));
frame.setBounds(100,100,500,500);
// panel.setBackground(Color.blue);
// panel.setBounds(10,10,500,500);
// frame.add(panel);
// panel.setVisible(true);
frame.setVisible(true);
Button button1 = new Button("Button1");
Button button2 = new Button("Button2");
Button button3 = new Button("Button3");
Button button4 = new Button("Button4");
frame.add(button1, BorderLayout.SOUTH);
frame.add(button2, BorderLayout.NORTH);
frame.add(button3, BorderLayout.WEST);
frame.add(button4, BorderLayout.EAST);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
这种布局只能这样设置
表格布局
package com.ch2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Gui {
public static void main(String[] args) {
Frame frame =new Frame();
Panel panel=new Panel();
frame.setBackground(new Color(248, 244, 244));
frame.setBounds(100,100,500,500);
// panel.setBackground(Color.blue);
// panel.setBounds(10,10,500,500);
// frame.add(panel);
// panel.setVisible(true);
frame.setVisible(true);
Button button1 = new Button("Button1");
Button button2 = new Button("Button2");
Button button3 = new Button("Button3");
Button button4 = new Button("Button4");
frame.setLayout(new GridLayout(2,2));
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.pack();
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
frame.setLayout(new GridLayout(2,2));
用于设置表格布局,表格布局将容器按我们要求进行划分
比如当前设置的是两行两列,然后按照我们添加顺序对其进行填充。pack()是用于自动调整窗口的大小,以适
应其内容
布局间可以进行组合,通过不同布局的组合来实现不同的布局,比如我们可以这样用:
package com.ch2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Gui {
public static void main(String[] args) {
Frame frame =new Frame();
frame.setVisible(true);
frame.setBounds(100,100,400,400);
frame.setLayout(new GridLayout(2,1));
Panel panel1 =new Panel(new BorderLayout());
Panel panel2 =new Panel(new GridLayout(2,1));
Panel panel3 =new Panel(new GridLayout(2,1));
Panel panel4 =new Panel(new BorderLayout());
panel1.add(new Button("left"),BorderLayout.EAST);
panel1.add(new Button("right"),BorderLayout.WEST);
panel4.add(new Button("right"),BorderLayout.WEST);
panel4.add(new Button("left"),BorderLayout.EAST);
panel2.add(new Button("up"));
panel2.add(new Button("down"));
panel1.add(panel2,BorderLayout.CENTER);
panel3.add(new Button("up"));
panel3.add(new Button("down"));
panel4.add(panel3,BorderLayout.CENTER);
frame.add(panel1);
frame.add(panel4);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
1.6事件监听
监听点击事件
package com.ch2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Gui {
public static void main(String[] args) {
Frame frame =new Frame();
Button button=new Button("button");
//button.addActionListener(e -> System.out.println("111"));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("111");
}
});
frame.add(button, BorderLayout.CENTER);
frame.setBounds(100,100,300,300);
frame.setVisible(true);
windowClose(frame);
}
private static void windowClose(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
我们利用匿名内部类去实现该操作,因为该接口是一个函数接口,所以我们也可以使用lambda表达式去写,
就是注释掉的那里
触发事件时我们重构的函数中的e是事件信息,我们可以自己去设计事件信息,使用setActionComand()
e也有方法去获取该信息 getActionComand()
1.7 输入框
在java中,输入框组件是TextField,
package com.ch2;
import org.w3c.dom.Text;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Gui {
public static void main(String[] args) {
new Mframe();
}
}
class Mframe extends Frame {
public Mframe(){
TextField textfield = new TextField();
add(textfield);//调用的是父类的add方
MyListener myListener=new MyListener();
textfield.addActionListener(myListener);
setVisible(true);
setBounds(100,100,300,300);
//pack();
}
}
class MyListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
TextField field=(TextField) e.getSource();
System.out.println(field.getText());
}
}
其中ActionEvent 的getSource()方法的返回值是触发事件的对象,我们获得后就可
以在触发事件时对该对象进行各种操作。不过为了方便使用是用Object来指向的,
所以我们在后面需要用到强制类型转换去转换,该事件在我们在输入框输入内容后
按下回车时触发。
如果我们不想输入的内容被直接显示,可以使用setEchoChar来给出一个char类型
字符对输入的值在显示上进行替换,实际上还是原来的值只不过显示被我们设置的
字符替代
如果我们想要回车后将输入框清空,使用setText()即可
package com.ch2;
import org.w3c.dom.Text;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Gui {
public static void main(String[] args) {
new Mframe();
}
}
class Mframe extends Frame {
public Mframe(){
TextField textfield = new TextField();
add(textfield);//调用的是父类的add方
MyListener myListener=new MyListener();
textfield.addActionListener(myListener);
setVisible(true);
setBounds(100,100,300,300);
textfield.setEchoChar('*');
}
}
class MyListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
TextField field=(TextField) e.getSource();
System.out.println(field.getText());
field.setText(null);
}
}
1.8加法计算器
既然我们学会了上面的这些内容,我们可以试着写一些小东西了,比如下面的加法
计算器
package com.ch2;
import org.w3c.dom.Text;
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 Gui {
public static void main(String[] args) {
new Calc();
}
}
class Calc extends Frame{
Calc() {
TextField textField1 = new TextField(10);
TextField textField2 = new TextField(10);
TextField textField3 = new TextField(20);
Button button = new Button("=");
Label label = new Label("+");
setLayout(new FlowLayout());
MyActionListener myActionListener = new MyActionListener(textField1,textField2,textField3);
button.addActionListener(myActionListener);
add(textField1);
add(label);
add(textField2);
add(button);
add(textField3);
setVisible(true);
pack();
windowClose(this);
}
private void windowClose(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyActionListener implements ActionListener{
private TextField num1,num2,num3;
public MyActionListener(TextField n1,TextField n2,TextField n3){
num1 = n1;
num2 = n2;
num3 = n3;
}
@Override
public void actionPerformed(ActionEvent e) {
int n1=Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
int n3= n1+n2;
num3.setText(Integer.toString(n3));
num1.setText(null);
num2.setText(null);
}
}
我们使用组合类将其结合一下:
package com.ch2;
import org.w3c.dom.Text;
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 Gui {
public static void main(String[] args) {
new Calc();
}
}
class Calc extends Frame{
TextField textField1,textField2,textField3;
Calc() {
textField1 = new TextField(10);
textField2 = new TextField(10);
textField3= new TextField(20);
Button button = new Button("=");
Label label = new Label("+");
setLayout(new FlowLayout());
MyActionListener myActionListener = new MyActionListener(this);
button.addActionListener(myActionListener);
add(textField1);
add(label);
add(textField2);
add(button);
add(textField3);
setVisible(true);
pack();
windowClose(this);
}
private void windowClose(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyActionListener implements ActionListener{
Calc calc;
public MyActionListener(Calc calc){
this.calc=calc;
}
@Override
public void actionPerformed(ActionEvent e) {
int n1=Integer.parseInt(calc.textField1.getText());
int n2 = Integer.parseInt(calc.textField2.getText());
int n3= n1+n2;
calc.textField3.setText(Integer.toString(n3));
calc.textField2.setText(null);
calc.textField1.setText(null);
}
}
如果我们使用内部类进行优化
package com.ch2;
import org.w3c.dom.Text;
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 Gui {
public static void main(String[] args) {
new Calc();
}
}
class Calc extends Frame{
TextField textField1,textField2,textField3;
Calc() {
textField1 = new TextField(10);
textField2 = new TextField(10);
textField3= new TextField(20);
Button button = new Button("=");
Label label = new Label("+");
setLayout(new FlowLayout());
MyActionListener myActionListener = new MyActionListener();
button.addActionListener(myActionListener);
add(textField1);
add(label);
add(textField2);
add(button);
add(textField3);
setVisible(true);
pack();
windowClose(this);
}
private void windowClose(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) {
int n1=Integer.parseInt(textField1.getText());
int n2 = Integer.parseInt(textField2.getText());
int n3= n1+n2;
textField3.setText(Integer.toString(n3));
textField2.setText(null);
textField1.setText(null);
}
}
}
1.9 画笔
在java中我们可以在窗口中进行绘画,使用的就是画笔
下面我们看一下具体的用法
package com.ch2;
import org.w3c.dom.Text;
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 Gui {
public static void main(String[] args) {
new MyPaint().loadframe();
}
}
class MyPaint extends Frame{
public void loadframe(){
this.setBounds(100,100,500,500);
this.setVisible(true);
}
public void paint(Graphics g){
g.setColor(Color.red);
g.drawOval(100,100,100,100);//画一个圆环
g.fillOval(300,300,100,100);//画一个实心圆
g.drawRect(200,200,100,100);//画一个矩形框
g.fillRect(400,400,100,100);//画一个实心矩形
windowClose();
}
private void windowClose (){
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
2.0 鼠标监听
我们使用鼠标监听实现在画板中画一个个点
package com.ch2;
import org.w3c.dom.Text;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;
public class Gui {
public static void main(String[] args) {
new Myframe("paint");
}
}
class Myframe extends Frame {
ArrayList<Point> points = new ArrayList<Point>();
public Myframe(String title) {
super(title);
setBounds(100, 100, 500, 500);
MyMouseListener ml = new MyMouseListener();
addMouseListener(ml);
setVisible(true);
windowclose();
}
private void windowclose(){
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
class MyMouseListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
Myframe myframe = (Myframe) e.getSource();
points.add(new Point(e.getX(), e.getY()));
repaint();
}
}
@Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
Iterator<Point> it = points.iterator();
while (it.hasNext()) {
Point p = it.next();
g.fillOval(p.x, p.y, 5, 5);
}
}
}
2.1 键盘监听
package com.ch2;
import org.w3c.dom.Text;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;
public class Gui {
public static void main(String[] args) {
new Myframe("paint");
}
}
class Myframe extends Frame {
ArrayList<Point> points = new ArrayList<Point>();
public Myframe(String title) {
super(title);
setBounds(100, 100, 500, 500);
MyKeyListener mykeylistener = new MyKeyListener();
addKeyListener(mykeylistener);
setVisible(true);
windowclose();
}
private void windowclose(){
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
//setVisible(false);
System.exit(0);
}
});
}
class MyKeyListener extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_SPACE){
System.out.println("space");
}
}
}
}
KeyEvent.VK_SPACE
空格所代表的按键代码,在keyevent类中存储了所有的按键带代
码
2.2 JFrame
我们看一下JFrame的基础用法
package com.ch2;
import org.w3c.dom.Text;
import java.awt.event.MouseAdapter;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;
public class Gui {
public void init(){
JFrame jframe = new JFrame("TEST");
JLabel jlabel = new JLabel("lable");
jframe.setBounds(100,100,500,500);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//还有其他设置,比如隐藏,此处的WindowConstants是用接口定义的只存储静态常量的抽象类
Container container = jframe.getContentPane();
container.add(jlabel);
jlabel.setHorizontalAlignment(JLabel.RIGHT);//和关闭窗口的设置一样,可以设置标签的位置。
container.setBackground(Color.blue);
}
public static void main(String[] args) {
new Gui().init();
}
}
在swing中,jframe只用来触发窗口事件,设置窗口位置大小等操作,不实际操作其内
容,这是和AWT最大的区别,我们如果想要给窗口添加内容,设置颜色,应该使用内容
窗口,用getContentPane来获取,在上述代码中,我们想要更改窗口的背景颜色,直
接更改jframe是无效的,必须更改container的color才可以。
2.3 弹窗(JDialog)
弹窗也是一个新的窗口
package com.ch2;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class MyDialog extends JFrame{
public MyDialog() {
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setBounds(100,100,500,500);
Container container = getContentPane();
container.setLayout(null);//绝对定位,根据坐标决定布局
JButton button = new JButton("点击");
button.setBounds(30,30,200,50);
container.add(button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new Dia();
}
});
}
public static void main(String[] args) {
new MyDialog();
}
class Dia extends JDialog{
public Dia (){
setVisible(true);
setLayout(null);
setBounds(100,100,400,400);
}
}
}
通过该方式实现弹窗,需要注意的是当我们new一个Dialog时,已经默认有了窗口宽鼻
功能,所以弹窗的窗口关闭功能我们就不需要自己去写了。