Java基础知识:图形程序设计

  • 大纲:比那些使用图形用户界面(GUI)的Java程序。
    • 定义屏幕上的窗口大小和位置的程序。
    • 窗口中采用多种字体显示文本。
    • 如何显示图像。
  • Swing概述:
    • AWT
      • Abstract Window Toolkit (AWT)。早期基本GUI程序设计的类库。基本AWT库采用 将处理用户界面元素的任务委派给每个目标平台本地GUI工具箱的方式(观感依赖于目标平台)。(“一次编写,随处使用”)
      • 不同平台,用户界面元素的操作行为存在差别
      • 某些平台的用户界面组件集合并不丰富
      • 不同平台上的AWT用户界面库中存在不同的bug。(“一次编写,随处调试”)
    • Swing
      • 已是Java基础类库(Java Foundation Class, JFC)的一部分。包含的内容远大于Swing GUI工具箱。
      • JFC不仅包含Swing组件,而且还包含了一个可访问性API,一个2D API 和一个 可拖放API。
      • Swing并没有完全替代AWT,而是基于AWT架构上。仅提供了能力更强大的用户界面组件
      • Swing是指“被绘制的”用户界面类,AWT是指像 事件处理 这样的窗口工具箱的底层机制
  • 创建框架:
    •   在Java中,顶层窗口(没有包含在其他窗口的窗口)被称为 框架。JFrame类,扩展于Frame类。
    • 绝大多数Swing组件类都以“J”开头,如:JButton,JFrame。切忌Swing和AWT组件混用。
    • Swing位于 javax.swing包 中。包名javax 表示 这是Java的扩展包,而不是核心包。
    • 两个技术问题需强调:
      • 所有的Swing组件必须由 事件分派线程 进行配置,线程将鼠标点击和按键控制转移到用户接口组件。Event.invokeLater() 。
      • 定义一个关闭这个框架的响应动作。
    • 在默认情况下,用户关闭窗口时只是将框架隐藏起来,而程序并没有终止。
    • 退出main方法并没有终止程序,终止的只是主线程。事件分派线程保持程序处于激活状态,知道关闭框架或调用System.exit方法终止程序。
    • 示例程序:(创建一个最简单的框架)
package simpleFrame;

import java.awt.*;
import javax.swing.*;

public class SimpleFrameTest {
	public static void main( String[] args ) {
		EventQueue.invokeLater(()->{
			SimpleFrame frame = new SimpleFrame();
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			frame.setVisible(true);
		});
	}
}

class SimpleFrame extends JFrame{
	private static final int DEFAULT_WIDTH = 300;
	private static final int DEFAULT_HEIGHT = 200;
	
	public SimpleFrame() {
        //默认情况下,框架的大小为 0 * 0 。
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT );
	}
}
  • 框架定位:
    • 处理框架大小和定位的重要的方法:
      • setLocation 和 setBounds方法 用于设置框架的位置
      • setIconImage 用于告诉窗口系统在标题栏,切换任务窗口等位置显示哪个图标
      • setTitle 标题。
      • setResizable 利用一个boolean值确定框架的大小是否允许用户改变
    • 框架属性:
      • 组件类的很多方法都是以 获取/设置方法对 形式出现的。这样的一个 获取/设置方法对 被称为一种属性
      • 属性包含 属性名类型
      • 对于类型为 boolean 的属性,获取的方法由 “is”开头
    • 确定合适的框架大小:
      • 对于专业应用程序来说,应该检查屏幕的分辨率,并根据其分辨率编写代码重置框架的大小
      • Toolkit类的 静态方法getDefaultToolkit 得到一个 Toolkit对象(Toolkit类包含很多与本地窗口系统打交道的方法)。 然后,调用 getScreenSize方法,获得一个 Dimension对象,同时用公有实例变量widthheight保存屏幕的宽度和高度。
      • 如果框架中包含标准的组件,可以调用pack方法设置框架大小。框架将被设置为刚好能够放置所有组件的大小。
      • 牢记用户定位应用程序的框架位置、重置框架大小,并且在应用程序再次启动时恢复,是一个不错的想法。
      • GraphicsDevice类还允许以全屏模式执行应用。  
    • java.awt.Component
      • boolean isVisible()
      • void setVisible( boolean b )
      • void setSize( int width, int height )
      • void setLocation( int x, int y )
      • void setBounds( int x, int y, int width, int height )
      • Dimension getSize()
      • void setSize( Dimension d )
    • java.awt.Window
      • void toFront() //将窗口显示在其他窗口前面
      • void toBack() //将窗口移到 桌面窗口栈后面,并相应地重新排列所有的可见窗口。
      • boolean isLocationByPlatform()
      • void setLocationByPlatform( boolean b ) //由平台选择一个合适的位置。
    • java.awt.Frame
      • boolean isResizable()
      • void setResizable( boolean b )
      • String getTitle()
      • void setTitle( String s )
      • Image getIconImage()
      • void setIconImage( Image image )
      • boolean isUndecorated()
      • void setUndecorated( boolean b )
      • int getExtendedState()
      • void setExtendedState( int state )
        • Frame.NORMAL
        • Frame.ICONIFIED
        • Frame.MAXIMIZED_HORIZ
        • Frame.MAXIMIZED_VERT
        • Frame.MAXIMIZED_BOTH
  • 示例程序:(构建一个框架,带标题,宽高设为系统分辨率的一半)
package sizedFrame;

import java.awt.*;
import javax.swing.*;
public class SizedFrameTest {
	public static void main( String[] args ) {
		EventQueue.invokeLater(()->{
			SizedFrame frame = new SizedFrame();
			frame.setTitle("SizedFrame");
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			frame.setVisible(true);
		});
	}
}

class SizedFrame extends JFrame{
	
	public SizedFrame() {
		Toolkit kit = Toolkit.getDefaultToolkit();
		Dimension screenSize = kit.getScreenSize();
		
		setSize( screenSize.width/2, screenSize.height/2);
		setLocationByPlatform(true);
		
		Image img = new ImageIcon("icon.gif").getImage();
		setIconImage(img);
	}
	
}

 

 

  • 在组件中显示信息:(在框架显示信息)
    • 可以将消息字符串直接绘制在框架中,但这并是一种好的编程习惯。
    • 在Java中,框架被设计为放置组件的容器,可以将菜单栏或其他用户组件放置其中。
    • JFrame有四层面板,包括:根面板、层级面板、玻璃面板 和 内容窗格
      • Container contentPane = frame.getContentPane(); contentPane.add(c)
      • 可以直接调用frame.add(c)
    • 绘制一个组件,需要定义一个扩展JComponent的类,并覆盖其中的 paintComponent方法,该方法有一个Graphics类型的参数。
    • 在Java中,所有的绘制都必须使用Graphics对象,其中包含了绘制图案、图像和文本的方法。
    • 只要窗口需要重新绘图,事件处理器就会通告组件,从而引发执行所有组件的paintComponent方法。一定不要自己调用paintComponent方法(会自动被调用:恢复窗口、窗口被覆盖、窗口第一次显示)。
    • 如果需要强制刷新屏幕,就需要调用 repaint方法,而不是paintComponent方法。repaint方法会引发采用相应配置的Graphics对象调用所有组件的paintComponent方法。
    • java.awt.Component
      • void repaint() // "尽可能快地"重新绘制组件
      • Dimension getPreferredSize() //要覆盖这个方法,返回这个组件的首选大小
    • 实例程序:(框架内显示消息)
package notHelloWorld;

import java.awt.*;
import javax.swing.*;
public class NotHelloWorld {
	public static void main( String[] args ) {
		EventQueue.invokeLater(()->{
			NotHelloWorldFrame frame = new NotHelloWorldFrame();
			frame.setTitle("NotHelloWorldFrame");
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			frame.setVisible(true);
		});
	}
}


class NotHelloWorldFrame extends JFrame{
	public NotHelloWorldFrame() {
		add( new NotHelloWorldComponent() );
		pack();
	}
}

class NotHelloWorldComponent extends JComponent{
	private static final int MESSAGE_X = 75;
	private static final int MESSAGE_Y = 100;
	
	private static final int DEFAULT_WIDTH = 300;
	private static final int DEFAULT_HEIGHT = 200;
	
	public void paintComponent( Graphics g ) {
		g.drawString("Not a Hello World program", MESSAGE_X, MESSAGE_Y);
	}
	
	public Dimension getPreferredSize() { return new Dimension( DEFAULT_WIDTH, DEFAULT_HEIGHT); }
}

 

  • 处理2D图形
    • Graphics类包含绘制直线、矩形和椭圆等方法。但是对绘制图形的操作能力十分有限。
    • Java SE 1.2引入了Java 2D库,这个库实现了一组功能强大的图形操作
    • 要想使用Java 2D库绘制图形,需要获得一个 Graphics2D 对象。这个类是 Graphics类的子类
    • 自Java SE 2版本以来,paintComponent方法就会自动获得一个Graphics2D类对象,只进行一次类型转换即可。
    • 想要绘制图形,首先要创建一个实现了 Shape接口 的类的对象,然后调用 Graphics2D的 draw方法
    • java.awt.geom.RectangularShape
      • double getCenterX()
      • double getCenterY()
      • double getMinX()
      • double getMinY()
      • double getWidth()
      • double getHeight()
      • double getX() //矩形左上角的坐标
      • double getY() 
    • java.awt.geom.Rectangle2D.Double
      • Rectangle2D.Double( double x, double y, double w, double h )
    • java.awt.geom.Point2D.Double
      • Point2D.Double( double x, double y)
    • java.awt.geom.Line2D.Double
      • Line2D.Double( Point2D start, Point2D end )
      • Line2D.Double( double startX, double startY, double endX, double endY )
    • 示例程序:(绘制一个图形)
package draw;

import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Ellipse2D.Double;

import javax.swing.*;
public class Draw {
	public static void main( String[] args ) {
		EventQueue.invokeLater(()->{
			DrawFrame frame = new DrawFrame();
			frame.setTitle("Draw some simple shapes");
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			frame.setVisible(true);
		});
	}
}

class DrawFrame extends JFrame{
	public DrawFrame() {
		add(new DrawComponent() );
		pack();
	}
}

class DrawComponent extends JComponent{
	private static final int DEFAULT_WIDTH = 400;
	private static final int DEFAULT_HEIGHT = 400;
	
	public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT ); }
	
	public void paintComponent( Graphics g ) {
		Graphics2D graph = (Graphics2D) g;
		
		
		double leftX = 100;
		double topY = 100;
		double width = 200;
		double height = 150;
		
		//画长方形
		Rectangle2D.Double rect = new Rectangle2D.Double(leftX, topY, width, height );
		graph.draw(rect);
		
		//画椭圆
		Ellipse2D.Double ellip = new Ellipse2D.Double();
		ellip.setFrame(rect);
		graph.draw(ellip);
		
		//画斜线
		Line2D.Double line = new Line2D.Double(leftX, topY, leftX + rect.getWidth(), topY + rect.getHeight());
		graph.draw(line);
		
		//画圆(椭圆的特殊情况)
		double radius = 150;
		double centerX = ellip.getCenterX();
		double centerY = ellip.getCenterY();
		
		Ellipse2D.Double circle = new Ellipse2D.Double();
		circle.setFrameFromCenter( centerX, centerY, centerX + radius, centerY + radius );
		graph.draw(circle);
	}
} 

 

  • 使用颜色:
    • 使用Graphics类的 setPaint方法,可以为图形环境上的所有后续的绘制操作选择颜色。
    • java.awt.Color类 中提供了13个预定义的常量,分别表示13种标准颜色
    • 可以通过红绿蓝三色成分来创建一个Color对象,以达到定制颜色的目的。
    • Color( int redness, int greenness, int blueness )。(参数范围0-255)
    • 如果使用 Graphics对象 而不是Graphics2D对象,就需要使用 setColor方法 来设置颜色。
    • 设置背景颜色:Component类的setBackground方法setForeground方法,组件绘制默认颜色。
    • Java在 SystemColor类中,封装了用户系统的各个元素的颜色。(P427 10th)
    • java.awt.Graphics2D
      • Paint getPaint()
      • void setPaint( Paint p )  //如:g2.setPaint(Color.RED)
      • void fill( Shape s )

 

  • 文本使用特殊字体:
    • 要知道某台特定计算机上允许使用的字体,就需要调用GraphicsEnvironment类中的getAvailableFontFamilyNames方法。
    • GraphicsEnvironment类描述了用户系统的图形环境,为了得到这个类对象,需要调用 静态的 getLocalGraphicsEnvironment方法
    • AWT定义了5个逻辑字体名:映射到客户机的实际字体
      • SansSerif
      • Serif
      • Monospaced
      • Dialog
      • DialogInput
    • Font( String name, int style, int size )

 

  • 显示图像:
    • java.awt.Graphics
      • boolean drawImage( Image img, int x, int y, ImageObserver observer ) // img绘制的图像,x y左上角的坐标,observer 绘制进程中以通告为目的的对象(可能为null)
      • boolean drawImage( Image img, int x, int y, int width, int height, ImageObserver observer ) //绘制一幅比例图像(注意:这个调用可能会在图像还没有绘制完毕就返回)
      • void copyArea( int x, int y, int width, int height, int dx, int dy )
    • 示例程序:(以一幅图像为基准,绘制相对应的平铺图像)
package image;

import java.awt.*;
import javax.swing.*;
public class ImageTest {
	public static void main( String[] args ) {
		EventQueue.invokeLater(()->{
			ImageFrame frame = new ImageFrame();
			frame.setTitle("Image Frame");
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			frame.setVisible(true);
		});
	}
}

class ImageFrame extends JFrame{
	public ImageFrame() {
		add( new ImageComponent() );
		pack();
	}
}

class ImageComponent extends JComponent{
	private static final int DEFAULT_WIDTH = 640;
	private static final int DEFAULT_HEIGHT = 640;
	
	private static final int IMAGE_WIDTH = DEFAULT_WIDTH/10;
	private static final int IMAGE_HEIGHT = DEFAULT_HEIGHT/10; 
	private Image image;
	
	public ImageComponent() {
		image = new ImageIcon("kilua.jpg").getImage();
	}
	
	public void paintComponent( Graphics g ) {
		if( image == null ) return;
		g.drawImage(image, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null);
		
		for( int i = 0; i < 10; i++ ) {
			for( int j = 0; j < 10; j++ ) {
				if( i + j > 0 ) {
					g.copyArea(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, i*IMAGE_WIDTH, j*IMAGE_HEIGHT );
				}
			}
		}
	}
	
	public Dimension getPreferredSize() { return new Dimension( DEFAULT_WIDTH, DEFAULT_HEIGHT ); }
}
  • 运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值