图形程序设计

  • swing概述
    AWT从一次编写,到处运行到一次编写,到处调试;AWT采用将处理用户界面元素的任务交给目标平台(window等),通过调用目标平台的GUI库实现界面显示,虽然这样做似乎可以实现一次编写,到处执行,但是不同平台的GUI库不同,能实现的功能也不同,导致同一套代码在不同的平台上显示有差异,并由于平台本身存在的bug导致到处调试.因此出现了一种完全不同于AWT工作模式的IFC出现了,将按钮,菜单等用户界面元素直接绘制在空白的窗口上,而对等体只需要创建和绘制窗口就十分方便且绘制的外观和动作在任何平台上运行的都是一致的.swing就包含在IFC中,同时IFC中还存在2D的API和一个可拖拽的API.

注意:swing没有完全替代AWT,只是建立在其之上
awt.PNG
swing的优势:
1.拥有丰富,便捷的用户界面元素集合
2.对低层平台依赖很少,与平台相关的bug很少
3.给予不同平台的用户一致的感官效果

  • 创建框架
public class Menu {
public static void main(String[] args) {
    JFrame j = new JFrame("学生成绩管理系统");//创建一个带有标题的框架
    j.setSize(400, 300);//设置框架的大小,如果没有setSize,那么框架的大小就只能显示标题栏
    j.setLocation(100,100);//设置框架左上角的位置
    j.setVisible(true);//显示框架
    j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//指定框架关闭时的操作0,1,2,3.不使用这条语句就会造成关闭框架后程序并不会结束
    
    j.setLocationRelativeTo(null);//设置和特定组件相关的框架的位置,如果该组件为空,那么框架在屏幕中居中,居中后setLocation就会失效
    //应该在调用setSize之后调用setLocationRelativeTo(null)实现居中
    JButton button = new JButton("OK");
    j.add(button);
    //j.pack();//自定设置框架大小以在框架中放置组件
    
}
}

Swing类位于javax.swing包中,是对java的扩展包,是对java1.1扩展,尽可能将swing类加载到java1.1兼容的浏览器中(浏览器的安全管理器不允许添加任何以java.开头的包).在java2平台上,swing是核心层的一部分,任何与java2兼容的java实现都必须提供swing类.
注意:不赞成使用window.show方法显示框架.swing负责绘制框架内的所有内容,对框架的装饰是不负责的。在jdk1.4中可以调用frame.setUndecorated(true)关闭所有框架装饰.

  • 框架定位
    处理框架大小和位置的方法
1.dispose:用于关闭窗口,并回收创建窗口所使用的全部系统资源
2.setIconImage:用于将窗口极小化时的图标设置为Image对象(图标化)
3.setTitle:设置标题栏中的文本
4.setResizable(boolean):设置框架大小是否可以改变
要注意的一点是setResizable(true)(不可改变)要设置在setVisible之前才有效,setVisible最好是放置在最后执行
5.setLocation(x,y):重定位组件(在component祖先类中)与setBounds(x,y,width,height)使用方式一致
注意:是相对于整个屏幕的,在没有明确指定框架大小时,所有的框架的默认值为0.应该检查用户分辨率再根据分辨率编写代码重置框架大小
为了得到屏幕的大小
   1)调用Toolkit类的静态方法getDefaultToolkit得到Toolkit对象(Toolkit类中包含很多与本地窗口系统进行交互的方法)
   2)调用getScreenSize();返回屏幕的大小,以Dimension对象的形式
public class CenterFrame extends JFrame{
public CenterFrame(){
    Toolkit kit = Toolkit.getDefaultToolkit();
    //获取屏幕的长宽
    Dimension dimension = kit.getScreenSize();
    int screenWidth = dimension.width;
    int screenHeight = dimension.height;
    int x = screenWidth/4;
    int y = screenHeight/4;
    int width = x*2;
    int height = y*2;
    setBounds(x, y, width, height);
    //设置图标
    URL url = CenterFrame.class.getClassLoader().getResource("xiaozhi.png");
    if(url!=null){
    Image image = kit.createImage(url);//创建一个image对象
    setIconImage(image);
    }
    setTitle("center");
    
}
}

6.提供图标:kit.getImage("xxx");//返回一个Image对象 setIconImage(img);
7.frame.setExtendedState(Frame.MAXMIZED_BOTH);//将程序的主框架设置为最大尺寸
注意:
如果编写一个利用多个显示屏幕的应用程序,就应该使用GrapicsEnvironment和GraphicsDevice类获得显示屏幕的大小。在jdk4中GrapicsDevice类允许在全屏幕模式下运行应用程序

java.awt.Component
1.boolean isVisible:检查组件是否设置为可见。组件最初是可见,但JFrame这样的顶层组件除外;true为显示
2.boolean isShowing():检查该组件是否显示在屏幕中。如果true,必须是可见的,且包含在一个正在显示的容器中
3.boolean isEnabled():检查组件是否被激活。被激活的组件可以接收键盘输入,最初为true
4.setEnabled(boolean):设置是否激活
5.Point getLocation():返回该组件左上角的位置,相对于外围容器左上角的位置point.x;point.y
6.Point getLocationOnScreen():返回该组件左上角的位置,用屏幕坐标表示
7.void setBounds(int x,int y,int width,int height)
8.setLocation(int x,int y) or setLocation(Point p):将组件移动到一个新的位置,如果不是顶层组件,x,y坐标是容器坐标,否则该组件x,y是屏幕坐标
9.void repaint():尽可能块地重新绘制组件
10.void repaint(int x,int y,int width,int height):尽可能快地重新绘制组件的一部分
java.awt.Window
1.void toFront():将该窗口显示在其他窗口前面
2.void toBack():显示在其他窗口后面
java.awt.Frame
1.void setResizable(boolean):设置是否可以重置框架大小
2.void setTitle(string):设置框架标题栏中的文字
3.void setIconImage(Image):设置图标
4.setUndecrated(boolean):true取消装饰框架
5.int getExtendedState():获取窗口状态
java.awt.Tookit
1.static Tookit getDefaultToolkit():返回默认的工具箱
2.Dimension getScreenSize():返回用户屏幕尺寸
3.Image getImage(String filename):加载文件明为filename的图像

  • 在面板中显示信息
    在通常情况下,应该在一个称为面板的组件上绘制信息,并将这个面板添加到框架中.jframe有四层面板,根面板、层级面板、玻璃面板(前三个是用来组织菜单栏和内容窗格以及实现观感的)和内容面板,我们只关心内容面板。要将所有的组件添加到内容窗格中去(ContentPane(jFrame.getContentPane()))但是在jdk5后可以直接调用jframe.add(Component),jdk1.4会报错抛出异常.面板用JPanel来实现(包含一个可以绘图的表面,本身也是个容器)

JComponent是所有非窗口Swing组件的超类,所有绘图都必须通过Graphics对象,其中包含绘制图案、图像、和文本的方法

//创建一个能够进行绘图的面板
package cn.wj.view;

import java.awt.Graphics;

import javax.swing.JPanel;

public class MyPanel extends JPanel {

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    }
}
只要窗口需要重新绘图,事件处理器就会通告组件,从而引发执行所有组件的paintComponent方法,一定不要自己调用paintComponent方法,在应用程序需要重新绘图时会自动调用,不要人为地干扰这个自动的处理过程.扩大或缩小或极小化窗口,然后又恢复窗口的大小会引发,弹出另外窗口并覆盖了一个已存在的窗口,使覆盖的窗口不可见,这时被覆盖的应用程序窗口被破坏,需要重新绘制
注意:如果需要强制刷新屏幕,就需要调用repaint方法,而不是paintComponent方法,它将引发采用相应配置的Graphics对象调用所有组件的paintComponent方法

javax.swing.JFrame
1.Container getContentPane():返回该JFrame的内容窗格对象
2.void add(Component c):将一个给定的组件添加到该框架的内容窗格中
javax.swing.JComponent
1.void painComponent(Graphics g)

  • 2D图形
    实现了一组功能强大的图形操作.要想使用java 2D库绘制图形,需要获得一个Graphics2D类对象。这个类是Graphics类的子类,如果使用的是一个支持java 2D的jdk版本,paintComponent方法就会自动地获得一个Graphics2D类对象,只需要类型转换就可以了

注意:在java 2D库出现之前,使用Graphics类中的drawRectangle方法绘制图形,2D库可以绘制更复杂的图形.但是会增加一点复杂度,java 2D中采用的是浮点坐标,都采用float单精度计算。但是也提供了double类型的坐标

package cn.wj.view;

import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class GraphicsDemo extends JPanel {
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
    }
}

Rectangle2D类
这是一个拥有两个具体子类的抽象类,这两个具体子类也是静态内部类
Rectangle2D.Float
Rectangle2D.Double
由于Float和Double都扩展于Rectangle2D,子类只覆盖了Rectangle2D中的方法,所以没必要记住图形类型,直接使用Rectangle2D类变量保存矩形的引用。

Rectangle2D floatRectangle = new Rectangle2D.Float(1.0f, 2.0f, 3.0f, 4.0f);

也就是说需要创建图形对象时需要使用内部类
注意:Rectangle2D.Float类包含了一个不是有Rectangle2D类继承而来的附加方法setRect(float x,float y,float height,float width).如果将Rectangle2D.Float的引用存储在Rectangle2D中就会失去这个方法。但是在Rectangle2D中有一个参数为double类型的setRect方法,直接使用Double图形类可以避免处理float类型的值。如果图形对象太多还是要考虑float类可以节省存储空间。同样这种特点也使用于其他图形类
Ellipse2D椭圆类继承和矩形类的公共超类RectangularShape
java.awt.geom.RectanglularShape
1.double getCenterX():返回中心x
2.getMinx():返回最小x的坐标值
3.getMaxX():返回最大x的坐标值
java.awt.geom.Rectangle2D.Double
1.Eectangle2D.Double(double x,double y,double w,double h)
java.awt.geom.Line2D.Double
1.Line2D.Double(Point2D start,Point2D end)
2.Line2D.Double(int start_X,int start_Y,int end_x,int end_y)

  • 颜色
    Graphics2D类的setPaint方法可以为图形环境上所有后续的绘制操作选择颜色

按照流程:选择颜色,绘制图形,再选择颜色,再绘制图形

                Graphics2D g2 = (Graphics2D) g;
        Rectangle2D rectangle = new Rectangle2D.Double(12, 12, 300, 300);
        Ellipse2D ellipse = new Ellipse2D.Double(12, 12, 300, 300);
        g2.setPaint(Color.RED);
        g2.draw(rectangle);
        g2.setPaint(Color.BLUE);
        g2.draw(ellipse);

如果使用Graphics就需要使用gsetColor方法设置颜色.要设置背景颜色就需要使用Component类中的setBackground方法
还有一个setForeground方法,用来设定再组件上绘制时使用的默认颜色
setBackground(SystemColor.desktop);
java.awt.Color
1.Color(int r,int g,int b):rgb彩色,0~255
java.awt.Graphics
1.void setPaint(Paint p):设置这个图形环境的绘制属性,color类实现了paint接口
填充图形
g2.fill(Shape)

  • 为文本设定特殊字体
    人们可以通过字体名指定一种字体。要想直到某台特定计算机上所允许使用的字体,就需要调用GraphicsEnvironment类(描述了用户系统的图形环境,为得到这个类需要调用静态方法getLocalGraphicsEnvironment)中的getAvailableFontFamilyNames方法。该方法返回一致字符型数组,其中包含了所有可用的字体名
    public void ListFonts() {
String[] names = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String string : names) {
    System.out.println(string);
        }
    }

要想使用某种字体绘制字符,必须先利用执行的字体名,字体风格和字体大小来创建一个Font类对象
java.awt.Font
1.getFamily():返回字体家族名
2.getFontName():返回字体名
3.getName():如果采用逻辑字体名创建字体,就返回逻辑名,否则返回字体名
4.getStringBounds(String s,FontRenderContext context):返回包围该字符串的矩阵。矩阵顶端的y坐标等于上坡度的负值,高度等于上坡度,下坡度,和行间距之和.宽度等于字符串宽度

  • 图像
    java.swing.imageIO

1.static BufferedImage read(File f)
2.static BufferedImage read(URL u)
java.awt.Image
1.Graphics getGraphics()
2.void flush():释放该图像缓冲区保存的所有资源
java.awt.Graphics
1.boolean drawIamge(Image img,int x,int y,ImageObserver observer):绘制一幅非比例图像
注意:这个调用可能会在图像还没有绘制完毕就返回
img:要绘制的图像
x:左上角的x坐标
y:左上角的y坐标
observer:绘制进程中以通告为目的的对象(可能为null)
2.boolean drawImage(Image img,int x,int y,int width,int height,ImageObserver observer):绘制一幅比例图像,系统按照比例将图像放入给定狂傲的区域,注意这个调用可能还没绘制完毕就返回
3.void copyArea(int x,int y,int width,int height,int dx,int dy):拷贝屏幕的一块区域
java.awt.Component
1.Image createImage(int width,int height):创建一个用于双缓冲的脱屏图像缓冲区
java.awt.MediaTracker
1.MediaTracker(Component c):跟踪在给定组件中的显示的图像
2.addImage(Image image,int id):将一个图像添加到被跟踪的图像列表中。当图像添加完毕后,图像加载进程将启动image:被跟踪的图像,id稍后引用改图像的标识符
3.void waitForID(int id):等待指定ID的图像加载完毕
4.void waitFonrAll():等待所有被跟踪的图像都加载完毕