GUI

本文详细介绍Java图形用户界面(GUI)编程的基础知识,包括组件、容器的概念,如何创建窗口、面板,以及常用的布局管理器如FlowLayout、BorderLayout等。此外,还介绍了事件处理机制,如监听器的使用方法,以及如何通过Graphics类进行绘图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


component:可以显示的图文界面(按钮、下拉菜单等)

container:用来容纳其他component的元素

window是可以独立显示的

panel可以容纳其他元素,但是必须附加到window里面才能显示

Frame:可以独立显示的窗口

Dialog:对话框,模态(不处理背后的主程序不能使用)非模态(点不点对话框主程序都能运行)


创建窗口

1.调用Frame类

package gui;
import java.awt.*;
public class TestFrame {
	public static void main(String[] args){
		Frame f = new Frame("My first Test");
		f.setSize(170,100);
		f.setBackground(Color.BLACK);
		f.setVisible(true);
	}
}

2.继承Frame类(可以有自己的成员变量)

package gui;
import java.awt.*;
public class TestFrame2 {
	public static void main(String[] args){
		MyFrame f1 = 
				new MyFrame(100,100,200,200,Color.blue);
		MyFrame f2 =
				new MyFrame(300,100,200,200,Color.YELLOW);
		MyFrame f3 =
				new MyFrame(100,300,200,200,Color.green);
		MyFrame f4 =
				new MyFrame(300,300,200,200,Color.magenta);
		
	}
}

class MyFrame extends Frame{
	static int id = 0;
	MyFrame(int x, int y, int w, int h, Color color ){
		super("MyFrame"+ (++id) );
		setBackground(color);//这里能直接调用方法是因为继承了Frame
		setLayout(null);//布局管理
		setBounds(x, y, w, h);
		setVisible(true);
	}
}

Panel

用add方法将Panel添加进去
package gui;
import java.awt.*;
public class TestPanel {
	public static void main(String[] args){
		new MyFrame2("haha",300,300,400,300);
	}
}

class MyFrame2 extends Frame{
	private Panel p1;
	MyFrame2(String s, int x, int y, int w, int h){
		super(s);
		p1 = new Panel(null);		
		p1.setBounds(w/4, h/4, w/2, h/2);
		p1.setBackground(Color.yellow);
		setBounds(x,y,w,h);		
		setVisible(true);
		setBackground(Color.BLUE);
		add(p1);
		setLayout(null);
	}
}

布局管理器

每一个容器都有自己的布局管理器,不需要自己设计具体的细节

1.FlowLayout

Panel类默认布局管理器,从左到右排列型,可以设置对其方式,左右,上下的间距

package gui;
import java.awt.*;
public class TestFlowLayout {
	public static void main(String[] args){
		Frame f = new Frame("Flow Layout");
		Button button1 = new Button("ok");
		Button button2 = new Button("Open");
		Button button3 = new Button("Close");
		f.setLayout(new FlowLayout());
		f.add(button1);
		f.add(button2);
		f.add(button3);
		f.setSize(100,100);
		f.setVisible(true);
	}

	
}

2.BorderLayout

Frame类的默认布局管理器
把区域分成东南西北中四个区域,默认添加到中
每个区域只能加入一个组件Compoment,添加多了会覆盖

package gui;
import java.awt.*;
public class TestBorderLayout {
	public static void main(String[] args){
		Frame f = new Frame("BorderLayout");
		
		f.add(new Button("BN"), BorderLayout.NORTH);
		f.add(new Button("BS"), BorderLayout.SOUTH);
		f.add(new Button("BW"), BorderLayout.WEST);
		f.add(new Button("BE"), BorderLayout.EAST);
		f.add(new Button("BC"), BorderLayout.CENTER);
		
		f.setSize(200,200);
		f.setVisible(true);
		
	}
}



3.GridLayout

把空间划分成矩形的单元格
GridLayout(3,4)设置单元格的行和列
pack方法包住里面的按钮,刚好合适



事件管理器

在java.awt.event包下面
要监听什么事件就要实现什么接口,并将其添加到相应的组件上

ActionEvent

package gui;
import java.awt.*;
import java.awt.event.*;
public class TestActionEvent {
	public static void main(String[] args){
		Frame f = new Frame("Test");
		Button b1 = new Button("Start");
		Button b2 = new Button("Stop");
		Monitor bh = new Monitor();
		b1.addActionListener(bh);
		b2.addActionListener(bh);
		b2.setActionCommand("This is Stop");
		f.add(b1, BorderLayout.NORTH);
		f.add(b2, BorderLayout.CENTER);
		f.pack();
		f.setVisible(true);
	}
}

class Monitor implements ActionListener{//监听器,监听什么动作就要实现什么类
	public void actionPerformed(ActionEvent e){
		System.out.println(e.getActionCommand());//获取当前哪个按钮被触发的标记
	}
}

TextField事件监听

文本框输入
在一个类中,想访问另一个类的原对象,可以通过getSource方法,获得事件发生时对象的信息
getSource方法会返回一个父类对象, 要注意强制转化
package gui;
import java.awt.*;
import java.awt.event.*;
public class TestField {
	public static void main(String[] args){
		new TFFrame("text");
	}
}

class TFFrame extends Frame{
	TFFrame(String name){//重写构造方法
		super(name);
		TextField tf = new TextField();
		add(tf);
		tf.addActionListener(new TFActionListener() );
		pack();
		setVisible(true);
	}
}

class TFActionListener implements ActionListener{
	public void actionPerformed(ActionEvent e){
		TextField tf = (TextField)e.getSource();//获得监听器的信息,把tf指向上面那个类的文本输入
		System.out.println(tf.getText());
		tf.setText("");
	}
}

密码框的输入

在TextField里加入
tf.setEchoChar('*');
便可以使输入变为星号


持有对方引用

把其他的类作为参数传入,这样在其他的类中可以对这个类中的成员变量进行操作
package gui;
import java.awt.*;
import java.awt.event.*;
public class TFMath {
	public static void main(String[] args){
		new TFFrame1().launchFrame();//调用启动器方法
	}
}

class TFFrame1 extends Frame{
	TextField num1,num2,num3;//务必设置成成员变量,这样才可以从别的类访问这些变量
	
	public void launchFrame(){//启动器方法
		 num1 = new TextField(10);
		 num2 = new TextField(10);
		 num3 = new TextField(15);
		Label lbplus = new Label("+");//静态的字符
		Button btnEqual = new Button("=");
		btnEqual.addActionListener(new MyMonitor(this) );//把当前的类作为参数传给其他类
		setLayout(new FlowLayout() );
		add(num1);
		add(lbplus);
		add(num2);
		add(btnEqual);
		add(num3);
		pack();
		setVisible(true);
		
	}
}

class MyMonitor implements ActionListener{
	TFFrame1 tf= null;
	
	public MyMonitor(TFFrame1 tf){//把TFFrame作为参数传进来,这样就获得了该类的引用
		this.tf = tf;
	}
	
	public void actionPerformed(ActionEvent e){
		int n1 = Integer.parseInt(tf.num1.getText());//把两个对话框内的字符串转化为int
		int n2 = Integer.parseInt(tf.num2.getText());
		tf.num3.setText(String.valueOf(n1+n2));
		
	}
}

内部类

好处:1.可以方便的访问包装类的成员变量成员方法
2.可以防止该类被其他类访问(例如上面的监听器,不需要被别的类访问,所以可以写在Frame内部内,加上Private,不会外部的类访问了)

适时使用:这个类不需要被其他类访问的时候

package gui;
import java.awt.*;
import java.awt.event.*;
public class TFMath {
	public static void main(String[] args){
		new TFFrame1().launchFrame();//调用启动器方法
	}
}

class TFFrame1 extends Frame{
	TextField num1,num2,num3;//务必设置成成员变量,这样才可以从别的类访问这些变量
	
	public void launchFrame(){//启动器方法
		 num1 = new TextField(10);
		 num2 = new TextField(10);
		 num3 = new TextField(15);
		Label lbplus = new Label("+");//静态的字符
		Button btnEqual = new Button("=");
		btnEqual.addActionListener(new MyMonitor() );//把当前的类作为参数传给其他类
		setLayout(new FlowLayout() );
		add(num1);
		add(lbplus);
		add(num2);
		add(btnEqual);
		add(num3);
		pack();
		setVisible(true);
		
	}
	
	class MyMonitor implements ActionListener{//写在了类的内部
		
		
		public void actionPerformed(ActionEvent e){
			int n1 = Integer.parseInt(num1.getText());//把两个对话框内的字符串转化为int
			int n2 = Integer.parseInt(num2.getText());
			num3.setText(String.valueOf(n1+n2));
			
		}
	}
}



Graphics类

每个Component都有一个Paint(Graphics g)方法用于绘图,每次重画该Compoent的时候都会自动调用这个方法(例如切屏等)
Graphics中好多子类可以花不同的图像
Graphics相当于一个画笔,在窗口上绘图

package gui;
import java.awt.*;
public class TestPaint {
	public static void main(String[] args){
		new PaintFrame().launchFrame();//不需要调用Paint方法,在Frame出现时会自动的调用
	}
}

class PaintFrame extends Frame{
	
	public void launchFrame(){
		setBounds(200,200,640,480);
		setVisible(true);
	}
	
	public void paint(Graphics g){//自动回调用这个方法
		Color c = g.getColor();
		g.setColor(Color.RED);
		g.fillOval(50, 50, 30, 30);
		g.setColor(Color.black);
		g.fillRect(80, 80, 40, 40);
		g.setColor(c);//把画笔颜色还原,良好习惯
	}
}


鼠标事件适配器

抽象类java.awt.event.MouseAdapter实现了MouseListener接口,可以使用其子类作为MouseEvent的监听器,重写即可

repaint方法可以使窗口重新绘制,过程是先调用repairntupdate-paint

package gui;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class MyMouseAdapter {
	public static void main(String[] args){
		new MyFrame5("drawing....");
	}
}

class MyFrame5 extends Frame{
	ArrayList points = null;//创建一个保存点的容器
	
	MyFrame5(String name){
		super(name);
		points = new ArrayList();
		setLayout(null);
		setBackground(new Color(204,204,255) );
		setBounds(300,300,400,400);
		setVisible(true);
		addMouseListener( new Monitor1() );//在当前的窗口内添加一个鼠标监听器
	}
	
	public void paint(Graphics g){//窗口的画图方法,自动调用
		Iterator i = points.iterator();//把所有的点都存在List里,每次刷新再画出
		while(i.hasNext()){
			Point p = (Point)i.next();
			g.setColor(Color.blue);
			g.fillOval(p.x, p.y, 10, 10);
		}
	}
	
	public void addPoint(Point p){//向List中添加点
		points.add(p);
	}
}

class Monitor1 extends MouseAdapter{//监听器类,用Adapter作用是不用重写多余的方法
	public void mouseClicked(MouseEvent e){//监听到事件发生执行此
		MyFrame5 f = (MyFrame5)e.getSource();
		f.addPoint(new Point(e.getX(),e.getY()));
		f.repaint();//这里特别注意要使用repaint方法
	}
}

Window事件--内部类

内部类,某各类,只在某个方法内部有效,写在某个方法的参数的位置,没有名字,匿名类

内部类使用的时候这个类比较简单,并且不需要变动的时候比较好用
package gui;
import java.awt.*;
import java.awt.event.*;
public class TestWindowClose {
	public static void main(String[] args){
		new MyFrame55("window");
	}
}

class MyFrame55 extends Frame{
	MyFrame55(String name){
		super(name);
		setLayout(null);
		setBounds(300, 300, 400, 400);
		setBackground(new Color(204, 204, 255));
		setVisible(true);
		this.addWindowListener(//内部类的写法,写在括号内
				new WindowAdapter(){
					public void windowClosing(WindowEvent e){
						setVisible(false);
						System.exit(-1);
					}
				}
				);
	}
}

计数器——action、window监听器内部类

package gui;
import java.awt.*;
import java.awt.event.*;
public class TestAnonymous2 {
	Frame f = new Frame("Test");
	TextField tf = new TextField(10);
	Button b1 = new Button("Start");
	
	TestAnonymous2(){
		f.add(b1, BorderLayout.NORTH);
		f.add(tf, BorderLayout.SOUTH);
		
		b1.addActionListener(new ActionListener(){//按钮监听器的内部类
			private int i=0;
			public void actionPerformed(ActionEvent e){
				tf.setText(e.getActionCommand() + ++i);
			}
}
				);
		
		f.addWindowListener(new WindowAdapter(){//窗口关闭
			public void windowClosing(WindowEvent e){
				System.exit(0);
			}
		});
		
		f.pack();
		f.setVisible(true);
		f.setLocation(500,500);
	}
	
	public static void main(String[] args){
		new TestAnonymous2();
	}
}


键盘事件

键盘的每一个按键对应一个虚拟的静态常量在KeyEvent中
对比按键的虚拟编号可以确定是哪个键被按下

package gui;
import java.awt.*;
import java.awt.event.*;
public class TestKey {
	public static void main(String[] args){
		new KeyFrame().launchFrame();
	}
}


class KeyFrame extends Frame{
	public void launchFrame(){
		setSize(200, 200);
		setLocation(300, 300);
		addKeyListener(new MykeyMonitor());
		setVisible(true);
	}
}

class MykeyMonitor extends KeyAdapter{
	public void keyPressed(KeyEvent e){
		int keycode = e.getKeyCode();//获得键盘的按键
		if(keycode == KeyEvent.VK_UP){
		System.out.println("up");
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值