黑马程序员----拜拜DOS,helloGUI

本文介绍了GUI的概念,对比了GUI与DOS命令行的区别,强调GUI在用户体验方面的优势。文章详细讲解了Java中GUI涉及的包,如Swing和Awt,以及Awt的组件体系。还探讨了GUI的基础知识,包括事件处理、焦点组件和对话框。最后,通过一个小练习解释了模态窗口的工作原理,并分享了GUI编程的心得。

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

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

GUI

1.什么是GUI?

顾名思义:Graphical User Interface,也就是图形用户界面。

通俗讲就是,原来没有GUI的时候,我们与计算机的交互就是通过那个黑框框,也就是DOS命令行,这种方式有很多弊端,比如不友好,不容易掌握,需要记住大量的命令等,这对普通用户来说是难以想象的,因为不可能每个人都花大量的时间去学习如何使用DOS。

因此出现了GUI,就像现在的计算机的操作系统基本都是图形界面的,当然了也有类似DOS命令行的,下面我们分析下这两种方式的区别。GUI的出现,无疑对计算机的普及起了难以想象的作用,我敢说如果没有GUI,那么就不可能像现在这样,计算机成为家电的一部分,而应该还是那些实验室,工作单位才有的工作用品。GUI使得人们操作计算机变得异常的简单,任何人都能使用计算机达到自己的目的。这就是GUI 的威力。

而DOS命令行则不然,我们可以想象一下,计算机的处理能力是有限的,对于人们来说GUI更适合绝大部分人的需求,但是我估计计算机更喜欢DOS这份“简单工作”吧,因为对于计算机来说,DOS命令行只占用很少一部分内存,而GUI不能,由于GUI需要大量描绘图形,也就需要占用大量的内存,对计算机来说,这可是个“重活”。因此GUI的电脑的速度要比DOS的要慢一些,这是无可厚非的。



2.Java中GUI涉及的包

java.Awt:重量级组件,比较依赖于系统。
javax.Swing:基于Awt,属轻量级组件,不依赖系统。(开发用)

Swing相对于Awt来说,更加的与平台无关,而Awt构建出的程序,在各个平台上的体现略有差别,这是因为它使用到了跟操作系统底层有关的东西,而Swing不同,Swing在每个系统下的表现都是一致的,因此开发中常用Swing。



3.Awt包体系

Component组件:
|--Container容器(通过add可以向自己内部添加组件):
|--Panel面板
|--Window窗口
|--Frame
|--Dialog
|--Button
|--Label
|--CheckBox
|--....


4.GUI基础知识点

布局类
流失布局:FlowLayout
边界布局:BorderLayout(Frame默认为此布局)
网格布局:GridLayout
网格包布局:GridBagLayout
卡片布局:CardLayout
创建窗体(每个窗体都在一个独立的线程中运行,因此只要有窗体未关,主线程不会结束):
1.创建frame对象
2.设置大小,位置,布局等
3.通过add添加组件
4.使用setVisible使窗口可见
重点:事件监听机制
特点:事件源,事件,监听器,事件处理
事件源:awt和swing那些组件。
事件:每一个事件源都有自己的对应事件和共性事件。
监听器:将可以触发某个事件的动作(不止一个)封装到监听器中。
监听器都是接口,通常它都有一个适配器来方便我们创建对象。
以上三者在java都已定义好了,只需使用其对象就可以了,我们要做的就是事件处理部分,也就是对产生的动作进行自定义处理。

当我们需要给组件添加监听器时,需要查阅组件类,看它支持哪种监听器。
共性事件(由于是组件共有的,因此定义在Component中):鼠标键盘事件,这些事件是每个组件都可以处理的
当前持有焦点的组件才会响应事件requestFocus()方法用于使组件获得焦点。
对话框:Dialog
菜单:MenuBar--Menu--MenuItem
jar包双击执行:
1.生成包,记得要Public一个主类
2.使用记事本写好配置信息(Main-Class:空格包名.main所在的class文件回车)
3.jar -cvfm jar包名 配置信息所在文件 包名
4.双击执行jar包

分析:当我们双击一个普通jar包时会报错,Main-Class错误,这是因为它要找到main方法在的class文件才能正确运行,因此需要使用配置信息告诉jar包main在哪里。
为什么可以双击执行呢?
这是因为jar后缀名文件与javaw程序相关联了,也就是说当我们打开一个jar时,系统就会使用javaw来打开,并运行。这个可以自己配置的,如果是安装版的java那么就已经配置好了。



5.GUI小练习

//创建GUI程序一般做法
//鼠标键盘事件测试
import java.awt.*;
import java.awt.event.*;
class FrameDemo 
{
	//定义所需组件引用
	private Frame f;
	private Button b,b2;
	private Label l;
	private TextField tf;

	FrameDemo()
	{
	
	}

	public void init()
	{
		//创建f,b并初始化
		f=new Frame("窗体");
		f.setBounds(100,100,300,300);
		f.setLayout(new FlowLayout());
		b=new Button("按钮");
		b2=new Button("按钮2");
		l=new Label("标签");
		tf=new TextField(20);

		//添加监听器方法
		myEvent();

		//将组件添加到窗体
		
		f.add(b);
		f.add(b2);
		f.add(l);
		f.add(tf);
		
		f.setVisible(true);
	}

	private void myEvent()
	{
		//为窗口添加了一个对应事件
		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
			public void windowOpened(WindowEvent e)
			{
				System.out.println("window is open");
				f.requestFocus();
			}
		});

		//为按钮添加共性事件--鼠标事件
		b.addMouseListener(new MouseAdapter(){
			private int enterCount=1;
			private int clickCount=1;
			public void mouseEntered(MouseEvent e)
			{
				System.out.println("鼠标进入:"+enterCount++);
			}
			public void mouseClicked(MouseEvent e)
			{
				System.out.println("鼠标点击:"+clickCount++);
			}
		});
		
		//鼠标移动事件
		b.addMouseMotionListener(new MouseMotionAdapter(){
			public void mouseDragged(MouseEvent e)//点击并拖动时触发
			{
				//得到鼠标的绝对坐标(相对屏幕左上角的坐标)减去窗体相对屏幕左上角的坐标
				//就是鼠标相对窗体的坐标
				b.setLocation(e.getXOnScreen()-f.getX(),e.getYOnScreen()-f.getY());
			}
			public void mouseMoved(MouseEvent e)
			{
				
			}
		});

		//鼠标滚轮事件
		b.addMouseWheelListener(new MouseWheelListener(){
			private int count=1;
			public void mouseWheelMoved(MouseWheelEvent e)
			{
				count+=e.getWheelRotation();
				b.setLabel(count+"");
			}
		});

		//为按钮和Frame添加键盘事件,观察事件冒泡
		
		b.addKeyListener(new KeyAdapter(){
			public void keyPressed(KeyEvent e)
			{
				System.out.println("Button:"+e.getKeyChar()+".."+e.getKeyCode()+".."+e.getKeyText(e.getKeyCode())+
					".."+e.getKeyLocation());
				//alt+enter就关闭程序
				if(e.getKeyCode()==KeyEvent.VK_ENTER&&e.isAltDown())
					System.exit(0);
			}
		});
		//窗口无法在有其他组件时获得焦点,因此无法响应动作
		f.addKeyListener(new KeyAdapter(){
			public void keyPressed(KeyEvent e)
			{
				System.out.println("Frame:"+e.getKeyChar()+".."+e.getKeyCode()+".."+e.getKeyText(e.getKeyCode())+
					".."+e.getKeyLocation());
			}
		});


		//为TestField添加键盘事件
		tf.addKeyListener(new KeyAdapter(){
			public void keyPressed(KeyEvent e)
			{
				int code=e.getKeyCode();
				//这种写法无法作用于小键盘上的数字
				//if(!(code>=KeyEvent.VK_0&&code<=KeyEvent.VK_9))
				if(!((code>=KeyEvent.VK_0&&code<=KeyEvent.VK_9)||(code>=96&&code<=107)))
				{
					l.setText("非法字符");
					e.consume();//这个是继承与InputEvent类,阻止事件的默认行为
				}
				else
					l.setText("标签");
			}
		});
	}



	public static void main(String[] args) 
	{
		new FrameDemo().init();
	}
}
运行图:


/*
创建窗口:
	1.创建Frame对象
	2.设置其大小,位置,布局等。
	3.使用add添加组件
	4.setVisible使其可见
事件处理机制:
	1.事件源
	2.事件
	3.监听器
	4.事件处理
	1,2,3均为java定义好的。
	4为我们处理的内容。
*/
import java.awt.*;
import java.awt.event.*;//跟事件有关的awt子包
class MyBut extends Button
{
	private int count=0;
	MyBut(String label)
	{
		super(label);
	}
	public int getCount()
	{
		return count++;
	}
}
class GUIDemo 
{
	public static void main(String[] args) 
	{
		Frame f=new Frame("第一个java窗体");

		f.setSize(300,300);//设置大小
		f.setLocation(200,150);//设置位置,距离屏幕左边框和上边框的距离
		f.setLayout(new GridLayout());//设置为流式布局

		//向窗体中添加组件
		/*
		Button b=new Button("按钮");
		b.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				System.out.println("点击按钮咯");
				b.setLabel("点击");
			}
		});
		f.add(b);
		*/
		//使用自定义button
		MyBut b=new MyBut("按钮");
		b.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				System.out.println("点击按钮咯");
				b.setLabel("点击:"+b.getCount());
			}
		});
		f.add(b);
		f.add(new Label("标签"));
		f.add(new TextArea());

		//将事件源中添加监听器
		//该方法需要传递一个实现了WindowListener接口的类对象
		//但是该接口有7个方法,我们不是都想去实现,因此我们
		//继承于WindowAdapter类,该类实现了7个方法,方法为空,
		//我们只需覆盖该类中我们真正需要的方法即可
		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e)
			{
				System.out.println("窗口正在关闭。。。。");
				System.exit(0);
			}
			public void windowActivated(WindowEvent e)
			{
				System.out.println("窗口被激活。。。");
			}
			public void windowOpened(WindowEvent e)
			{
				System.out.println("窗口被打开。");
			}
		});

		f.setVisible(true);//设置可见
	}
}
运行图:




//GUI练习
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class WindowTest 
{
	private Frame f;
	private Button but;
	private TextField tf;
	private TextArea ta;

	private Dialog dig;
	private Label digLab;
	private Button digBtn;

	WindowTest(){}

	public void init()
	{
		f=new Frame("列出指定目录内容");
		f.setBounds(200,100,400,400);
		f.setLayout(new FlowLayout());
		
		tf=new TextField(20);
		but=new Button("搜索");
		ta=new TextArea(20,30);

		f.add(tf);
		f.add(but);
		f.add(ta);
		
		myEvent();
		f.setVisible(true);
	}

	private void myEvent()
	{
		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		tf.addKeyListener(new KeyAdapter(){
			public void keyPressed(KeyEvent e)
			{
				if(e.getKeyCode()==KeyEvent.VK_ENTER)
				{
					//用代码触发btn的被点击事件达到搜索效果,实现代码复用
					but.click();
				}
			}
		});
		//按钮事件处理
		//之所以使用动作监听器而不是鼠标监听器是因为我们使用键盘一样可以按下按钮
		//因此使用动作监听器ActionListener
		but.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				String dir=tf.getText();
				File files=new File(dir);
				if(files.isDirectory())
				{
					StringBuilder result=new StringBuilder();
					for(String temp:files.list())
					{
						result.append(temp).append("\r\n");
					}
					//ta.setText(ta.getText()+result.toString());
					ta.setText(result.toString());
				}
				else
				{
					dig=new Dialog(f,"路径错误",true);//true表示这是个模态对话框
					digLab=new Label("路径错误:"+tf.getText());
					digBtn=new Button("知道啦");
					digBtn.addActionListener(new ActionListener(){
						public void actionPerformed(ActionEvent e)
						{
							dig.setVisible(false);
						}
					});
					dig.add(digLab);
					dig.add(digBtn);
					dig.setBounds(300,300,150,100);
					dig.setLayout(new FlowLayout());
					dig.addWindowListener(new WindowAdapter(){
						public void windowClosing(WindowEvent e)
						{
							dig.setVisible(false);
						}
					});
					dig.setVisible(true);
					tf.setText("");
				}
			}
		});
	}


	public static void main(String[] args) 
	{
		new WindowTest().init();
	}
}
运行图:


这里有个小问题:

为什么可以这样写?
fileDialog.setVisible(true);
String name=fielDialog.getFile();
我们知道,窗体运行于独立线程,那么当我们显示窗体后,立马就使用它的getFile方法此时能获取到该窗体的返回值吗?
如果是普通窗口,那是不可以的,但是对于模态窗口,它可以理解成阻塞式窗口,只要打开了它,必须操作完毕才能操作其他内容。


//测试菜单栏,菜单,菜单项的使用
//文件的打开和保存,另存为
//jar包双击执行
package mymenu;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class MenuDemo 
{
	private Frame f;
	private MenuBar mb;
	private TextArea ta;
	private Menu file,edit;
	private MenuItem open,save,saveAs,exit,cut,copy;

	private Dialog dig,saveDig;
	private Label digLab,saveLab;
	private Button digBtn,sureBtn,cancelBtn;
	private File tempFile;

	private FileDialog openDia,saveAsDia;

	MenuDemo()
	{
		init();
	}

	private void init()
	{
		f=new Frame("测试菜单");

		mb=new MenuBar();
		file=new Menu("file");
		edit=new Menu("edit");
		open=new MenuItem("open");
		save=new MenuItem("save");
		saveAs=new MenuItem("save as");
		exit=new MenuItem("exit");
		cut=new MenuItem("cut");
		copy=new MenuItem("copy");
		ta=new TextArea();

		file.add(open);
		file.add(save);
		file.add(saveAs);
		file.add(exit);
		edit.add(cut);
		edit.add(copy);
		mb.add(file);
		mb.add(edit);

		f.setMenuBar(mb);
		f.add(ta);
		f.setBounds(200,20,900,700);
		//f.setLayout(new FlowLayout());
		//有文本区域设置为流式布局不合适,我们设为默认边界布局,让组件随着窗体大小而变化

		myEvent();

		f.setVisible(true);
	}

	private void myEvent()
	{
		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		exit.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});
		cut.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				showDig("cut","are you sure to cut?");
			}
		});
		copy.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{				
				showDig("copy","are you sure to copy?");
			}
		});
		open.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				if(openDia==null)openDia=new FileDialog(f,"my open file",FileDialog.LOAD);//默认就是打开模式
				openDia.setVisible(true);
				//因为FileDialog为模态对话框,因此是阻塞式的,要想执行它后面的语句它肯定运行结束了。
				String dir=openDia.getDirectory();
				String fileName=openDia.getFile();
				if(dir==null || fileName==null)return;
				tempFile=new File(dir,fileName);
				try
				{
					BufferedReader br=new BufferedReader(new FileReader(tempFile));
					ta.setText("");
					for(String line=br.readLine();line!=null;line=br.readLine())
					{
						ta.append(line);
						ta.append("\r\n");
					}
					br.close();
				}
				catch (IOException ioe)
				{
					ioe.printStackTrace();
				}
			}
		});
		save.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				if(tempFile==null)return;
				if(saveDig==null)
				{
					saveDig=new Dialog(f,"是否保存",true);
					saveDig.addWindowListener(new WindowAdapter(){
						public void windowClosing(WindowEvent e)
						{
							saveDig.setVisible(false);
						}
					});
					saveLab=new Label("are you sure to save this file?");
					sureBtn=new Button("sure");
					sureBtn.addActionListener(new ActionListener(){
						public void actionPerformed(ActionEvent e)
						{
							//点击确定按钮
							try
							{
								BufferedWriter bw=new BufferedWriter(new FileWriter(tempFile));		
								bw.write(ta.getText());
								bw.close();
							}
							catch (IOException ioe)
							{
								ioe.printStackTrace();
							}
							saveDig.setVisible(false);
						}
					});
					cancelBtn=new Button("cancel");
					cancelBtn.addActionListener(new ActionListener(){
						public void actionPerformed(ActionEvent e)
						{
							//点击取消按钮
							saveDig.setVisible(false);
						}
					});
					saveDig.add(saveLab);
					saveDig.add(sureBtn);
					saveDig.add(cancelBtn);
					saveDig.setBounds(350,300,200,100);
					saveDig.setLayout(new FlowLayout());
				}
				saveDig.setVisible(true);
			}
		});
		saveAs.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				if(saveAsDia==null)saveAsDia=new FileDialog(f,"my save file",FileDialog.SAVE);//模式为保存
				saveAsDia.setVisible(true);
				String dir=saveAsDia.getDirectory();
				String fileName=saveAsDia.getFile();
				if(dir==null || fileName==null)return;
				System.out.println(dir+"..."+fileName);
				tempFile=new File(dir,fileName);
				try
				{
					BufferedWriter bw=new BufferedWriter(new FileWriter(tempFile));		
					bw.write(ta.getText());
					bw.close();
				}
				catch (IOException ioe)
				{
					ioe.printStackTrace();
				}
			}
		});
	}
	private void showDig(String title,String labText)
	{
		if(dig==null)
		{
			dig=new Dialog(f,title);
			dig.setBounds(300,200,150,100);
			dig.setLayout(new FlowLayout());
			dig.addWindowListener(new WindowAdapter(){
				public void windowClosing(WindowEvent e)
				{
					dig.setVisible(false);
				}
			});
		}
		else
			dig.setTitle(title);
		if(digLab==null)
		{
			digLab=new Label(labText);
			dig.add(digLab);
		}
		else
			digLab.setText(labText);
		if(digBtn==null)
		{
			digBtn=new Button("知道啦");
			digBtn.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e)
				{
					dig.setVisible(false);
				}
			});
			dig.add(digBtn);
		}
		dig.setVisible(true);
	}


	public static void main(String[] args) 
	{
		new MenuDemo();
	}
}<strong>
</strong>
运行图:








6.GUI总结及心得

编程图形界面的程序确实是一个非常有趣的事情,其中最重要的就是事件处理那一部分,否则整个程序都是死的,因此需要重点掌握事件处理。



------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

微型16/32位嵌入式GUI,自主开发,历时四年左右,拥有全部版权. http://www.ecgui.com 体积小巧 大小在 100KB~180KB! 特性: 多窗口支持| 完全中文输入/显示| 多数常用GUI控件| 99.9% ANSI C 编写| 已成功移植 DOS,Linux,uc/OS-II| 组件式 API(易用,高效) GUI SDK-Green for DOS Beta 开发包下载 305 KB 火热下载中 http://ecurb2006.googlepages.com/sdk-green-4dos.zip 演示程序下载 264 KB http://ecurb2006.googlepages.com/demo.zip 微型嵌入式GUI编程指南 PDF 下载 349 KB http://ecurb2006.googlepages.com/embeddedguiprogrammingguide.pdf GUI SDK For Windows Beta 开发包下载 583 KB http://ecurb2006.googlepages.com/sdk4win.zip 包含详细使用说明 部分应用程序 截图 记事本 http://ecurb2006.googlepages.com/edit.jpg 计算器 http://ecurb2006.googlepages.com/calc.jpg 画笔 http://ecurb2006.googlepages.com/painter.zip 支持控件 MAINWINDOW 主窗口 DLGWINDOW 对话框窗口,从属于主窗 BUTTON 按钮 MAINMENU 下拉式菜单 POPMENU 弹出式菜单 HSCROLLBAR 横向滚动条 VSCROLLBAR 竖向滚动条 TEXTBOX 单行文本编辑框 EDITBOX 多行文本编辑框 COMBOBOX 组合框 LISTBOX 列表框 CHECKBOX 多项选择框 CHOICEBOX 单项选择框 LABEL 文字标签 PAGEVIEW 标签页 SPEEDBAR 进度条 商业使用,将提供 GUI 全部源代码,低价授权策略,并提供 GUI 移植技术支持! 请联系 sales@ecurb2006.com 更多信息请访问 http://www.ecurb2006.com 针对 不少网友开发免费 DOS 软件的想法,现在提供 DOS 下的开发库,个人或者组织可以开发公共使用的免费软件,借这个机会,也希望能更好的推广这个 GUI.会在程序显示区域头部显示 GUI 的介绍性信息(无其他无关信息)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值