Java GUI设计概述

之前本科课程学习Java,大半个学期在讲前五章的类和面向对象的概念,之后就是第六章Java GUI设计。加之当时第一个接触程序设计语言实现GUI(之前的C语言没有这些),就晕菜了,而后又是java非常重要的几个概念和应用:流和文件,多线程,网络编程,数据库编程,servlet技术和JSP技术。因为中间的GUI设计已经让我失去上课的兴趣,之后的这些重要概念和技术到大四的时候才开始捡起来再学,都堪称Java必备经典 ----  两年后我才在《Java核心技术卷 I》上看到“如果只想用Java编写服务器端的应用程序,对GUI编程不感兴趣,可以跳过这几章(图形程序设计,事件处理,Swing用户界面组件)”。 悲催。。。

吐槽完毕。

一:简单的图形程序设计(不涉及事件处理)

一般来说就是设计一个扩展了 JFrame 的类( class SimpleFrame extends JFrame),在这个类的实例化方法中用setTitle、setBounds、setSize等方法设置框架的标题位置大小等信息,具体可以到JFrame类中。

      JFrame的结构画图来说确实有点复杂(详见《Java核心技术卷 I》P250),但是可以简单的把JFrame就当做一个框架,上面的标题栏,下面的大片空白区域就是内容窗格,这也是程序员最关心的部分。通过 frame.add() 方法可以加入很多元素,button, panel等。 可以有层层叠加,JButton添加到JPanel中,然后再将JPanel添加到JFrame中等。另外对需要将一个绘制消息的组件添加大框架中的话,绘制一个组件,这个组件是一个扩展了JComponent的类,并且覆盖了JComponent类中的paintComponent方法。 这个方法中有一个 Graphics 类型的参数,保存了用语绘制图像和文本的设置(字体颜色等)。 在java中,所有的绘制都必须使用 Graphics 对象。

class DrawFrame extends JFrame
{
	private static final int DEFAULT_WIDTH = 400;
	private static final int DEFAULT_HEIGHT = 400;
	
	public DrawFrame()
	{
		setTitle("DrawTest");
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
	
		DrawComponent component = new DrawComponent();
		add(component);
	}
	
}

class DrawComponent extends JComponent
{
	public void paintComponent(Graphics g)
	{
		Graphics2D g2 = (Graphics2D)g;
		
		double leftx = 100;
		double topy = 100;
		double width = 200;
		double height = 150;
		
		Rectangle2D rect = new Rectangle2D.Double(leftx, topy, width, height);
		g2.draw(rect);
		
		Ellipse2D ellipse = new Ellipse2D.Double();
		ellipse.setFrame(rect);
		g2.draw(ellipse);
		
		g2.draw(new Line2D.Double(leftx, topy, leftx+width, topy+height));
		
		
		double centerx = rect.getCenterX();
		double centery = rect.getCenterY();
		double radius = 150;
		
		Ellipse2D circle = new Ellipse2D.Double();
		circle.setFrameFromCenter(centerx, centery, centerx+radius, centery+radius);
		g2.draw(circle);
		
		
		
	}
	
}

二、事件处理

这也是Java GUI设计的核心,java事件处理采用的是事件委托模型。关键是理解三个对象: 事件对象,监听器对象,事件源(对象)。

事件对象: java是将事件的相关信息封装在一个事件对象中,所有的事件对象都派生于java.util.EventObject类,当然每个事件类型还有子类,如ActionEvent和WindowEvent,类的继承关系如下图


ActionEvent:指示发生了组件定义的动作的语义事件。当特定于组件的动作(比如被按下)发生时,由组件(比如 Button)生成此高级别事件。事件被传递给每一个 ActionListener 对象,这些对象是使用组件的 addActionListener 方法注册的,用以接收这类事件。 

WindowEvent:指示窗口状态改变的低级别事件。当打开、关闭、激活、停用、图标化或取消图标化 Window 对象时,或者焦点转移到 Window 内或移出 Window 时,由 Window 对象生成此低级别事件。 该事件被传递给每一个使用窗口的 addWindowListener 方法注册以接收这种事件的 WindowListener 或 WindowAdapter 对象。


       监听器对象:是一个实现了特定接听器接口的类的实例; //类定义:class ColorAction implements ActionListener{},必须实现接听接口ActionListener中的public void actionPerformed(ActionEvent event)方法;  事件处理的核心就是把监听器类写好。

     事件源对象:是一个能够注册监听器对象并发送事件对象的对象。// 前面事件源如果是一个button, 用button.addActionListener(new ColorAction)即可完成监听器对象在事件源中的注册;

    那么上面三个对象之间的关系就组成了java AWT事件处理的机制:

  • 监听器对象是一个实现了特定监听器接口的类的实例;
  • 事件源是一个能够注册监听器对象并发送事件对象的对象;
  • 当事件发生时,事件源将事件对象传递给所有注册的监听器;
  • 监听器对象将利用事件对象中的信息决定如何对事件作出响应;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class ButtonTest {
	public static void main(String[] args)
	{
		ButtonFrame frame = new ButtonFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}

}

class ButtonFrame extends JFrame
{
	private JPanel buttonPanel;
	public static final int DEFAULT_WIDTH = 300;
	public static final int DEFAULT_HEIGHT = 200;
	
	public ButtonFrame()
	{
		setTitle("ButtonTest");
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
		buttonPanel = new JPanel();
		
		//makeButton("red", Color.RED);
		
		
		JButton  yellowButton = new JButton("YellowButton"); 
		JButton  blueButton = new JButton("Blue");
		JButton  redButton = new JButton("Red");
		
		buttonPanel = new JPanel();
		
		buttonPanel.add(yellowButton);
		buttonPanel.add(blueButton);
		buttonPanel.add(redButton);
		
		add(buttonPanel);
		
		ColorAction yellowAction = new ColorAction(Color.YELLOW);
		ColorAction blueAction = new ColorAction(Color.BLUE);
		ColorAction redAction = new ColorAction(Color.RED);
		
		yellowButton.addActionListener(yellowAction);
		blueButton.addActionListener(blueAction);
		redButton.addActionListener(redAction);
		
		
	}
	
	
	
	private class ColorAction implements ActionListener
	{
		private Color backgroudColor;
		
		public ColorAction(Color c)
		{
			backgroudColor = c;			
		}
		
		public void actionPerformed(ActionEvent event)
		{
			buttonPanel.setBackground(backgroudColor);
		}
		
	}
	
	
	
	public void makeButton(String name, final Color backgroundColor)
	{
		JButton button = new JButton(name);
		buttonPanel.add(button);
		
		button.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				buttonPanel.setBackground(backgroundColor);
			}
		
		});
		
	}
	

三:Swing用户界面组件

这个主要是掌握在类的设计时一种设计模式思想:MVC即模型-视图-控制器模式。另外理解不同布局管理器的特点。各个界面组件(文本输入、单复选按钮/框、菜单、对话框等)可以参考《java核心技术卷 I》都有详细的例子。

      下面贴一个简单计算器的实现,主要是布局管理器的练习:

import java.awt.BorderLayout;
import java.awt.DisplayMode;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

//Demo 主要是练习java GUI设计几种布局管理器的使用

public class Calculator {
	public static void main(String[] args)
	{
		CalculatorFrame frame = new CalculatorFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		
	}

}

class CalculatorFrame extends JFrame
{
	public CalculatorFrame()
	{
		setTitle("Calculator");
		CalculatorJPanel panel = new CalculatorJPanel();
		add(panel);
		pack(); // 调整此窗口的大小,以适合其子组件的首选大小和布局。
	}
}

class CalculatorJPanel extends JPanel
{
	private JButton display;
	private JPanel panel;
	private double result;
	private String lastcommand;
	private boolean start;
	
	public CalculatorJPanel()
	{
		setLayout(new BorderLayout());
		
		result = 0;
		lastcommand = "=";
		start = true;
		
		//add display
		display = new JButton("0");
		display.setEnabled(false);  //
		add(display, BorderLayout.NORTH);
		
		ActionListener insert = new insertAction();
		ActionListener command = new commandAction();
		
		//add the button in a 4*4 grid
		
		panel = new JPanel();  
		panel.setLayout(new GridLayout(4, 4));
		
		addButton("1", insert);
		addButton("2", insert);
		addButton("3", insert);
		addButton("4", insert);
		addButton("5", insert);
		addButton("6", insert);
		addButton("7", insert);
		addButton("8", insert);
		addButton("9", insert);
		addButton("0", insert);
		addButton("+", command);
		addButton("-", command);
		addButton("*", command);
		addButton("/", command);
		addButton("=", command);
		addButton(".", insert);
		
		add(panel, BorderLayout.CENTER);		
		
	}
	
	private void addButton(String lable, ActionListener listener)
	{
		JButton button = new JButton(lable);
		button.addActionListener(listener);
		panel.add(button);
	}
	
	
	private class insertAction implements ActionListener //定义监听器类,监听输入数字和小数点
	{
		public void actionPerformed(ActionEvent event)
		{
			String input = event.getActionCommand();
			if(start)
			{
				display.setText("");
				start = false;				
			}
			display.setText(display.getText() + input);
		}
	}
	
	private class commandAction implements ActionListener //定义监听器类,监听输入运算符和负号
	{
		public void actionPerformed(ActionEvent event)
		{
			String command = event.getActionCommand();
			if(start)
			{
				if(command.equals("-"))  //  负号
				{
					display.setText(command);
					start = false;
				}
				else {
					lastcommand = command;
				}
			}
			else 
			{
				calculate(Double.parseDouble(display.getText()));
				lastcommand = command;
				start = true;
			}
		}
	}
	
	public void calculate(double x)
	{
		if(lastcommand.equals("+"))
			result += x;
		else if (lastcommand.equals("-")) {
			result -= x;
		}
		else if (lastcommand.equals("*")) {
			result *= x;
		}
		else if (lastcommand.equals("/")) {
			result /= x;
		}
		else if (lastcommand.equals("=")) {
			result = x;
		}
		
		display.setText("" + result);
		
	}
}

    

      

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值