【教学课件】第四章图形编程.ppt
第四章第四章 图形编程图形编程DrawingShap.javaDrawingShap.java4.1AWT与Swing简介一一.AWT.AWT工具包工具包javajava的抽象窗口工具包(的抽象窗口工具包(AWT:Abstract AWT:Abstract window Interface)window Interface)包含在包含在java.awtjava.awt包中,包中,它提供了许多用来设计它提供了许多用来设计GUIGUI的的组件类和容组件类和容器类器类基本基本AWTAWT库处理用户界面元素的方法是把库处理用户界面元素的方法是把这些元素的创建和行为委托给每个目标平台这些元素的创建和行为委托给每个目标平台上的本地上的本地GUIGUI工具箱进行处理工具箱进行处理AWT的层次关系EventComponentGraphicsMenuComponButtonScrollBarContainerCanvasListCheckBoxLabelTextFieldTextAreaWindowFrameDialogFontAppletPanel二二.Java Swing.Java Swing SwingSwing:非基于对等体的:非基于对等体的GUIGUI工具箱工具箱SwingSwing具有更丰富并且更方便的用户具有更丰富并且更方便的用户界面元素集合界面元素集合SwingSwing对底层平台的依赖更少对底层平台的依赖更少SwingSwing会带来交叉平台上的统一视觉会带来交叉平台上的统一视觉体验体验SwingSwing类被放在类被放在javax.Swingjavax.Swing包上包上Swing 组件层次关系ComponemtContainerWindowFrameDialogJFrameJDialogJComponentJPanelJLabelJScrollerJMenuBarJButtonJtext.三三.AWT.AWT与与SwingSwing的关系的关系对于使用过对于使用过JavaJava早期版本的人来说,大早期版本的人来说,大部分部分AWTAWT组件都有其组件都有其SwingSwing等价物等价物后者的名字一般是在前面后者的名字一般是在前面添加一个字母添加一个字母“J”“J”,如:,如:JButton,JFrame,JPanelJButton,JFrame,JPanel等等4.2组件和容器组件和容器一一.组件组件Java把由把由Component类的子类或间接子类类的子类或间接子类创建的对象称为一个组件创建的对象称为一个组件例:例:Button button1=new Button();例:例:TextField textfield=new TextField();例:例:Label label=new Label();二二.容器容器JavaJava把由把由containercontainer类的子类或间接子类创建类的子类或间接子类创建的对象称为一个容器的对象称为一个容器例:例:Frame fra=new Frame(“Frame fra=new Frame(“这是一个窗口这是一个窗口”)”);AppletApplet是是PanelPanel的子类,是的子类,是ContainerContainer的间接的间接子类子类AppletApplet本身也是一个容器本身也是一个容器三三.添加组件添加组件ComponentComponent类提供了一个方法:类提供了一个方法:add();add();例:例:fra.add(button);fra.add(button);例:例:fra.add(TextField);fra.add(TextField);容器本身也可以看作是一个组件,因此容器本身也可以看作是一个组件,因此可以把一个容器添加到另一个容器里,可以把一个容器添加到另一个容器里,实现容器嵌套实现容器嵌套例:例:add(fra);add(fra);四。布局管理器四。布局管理器Java Java 采用非常优秀的概念来进行布局采用非常优秀的概念来进行布局一个容器内的所有组件都由一个布局管一个容器内的所有组件都由一个布局管理器来进行管理理器来进行管理JavaJava支持以下四种布局管理器支持以下四种布局管理器 FlowLayout FlowLayout BorderLayout BorderLayout CardLayout CardLayout GridBagLayout GridBagLayout在在JavaJava中,顶层窗口(没有包含在另一中,顶层窗口(没有包含在另一个窗口内的窗口)称为框架个窗口内的窗口)称为框架1.1.框架框架AWTAWT库中有一个基于对等体的库中有一个基于对等体的FrameFrame类对类对应着顶层应着顶层该类的该类的SwingSwing版本为版本为JFrame,JFrameJFrame,JFrame是是Frame Frame 子类子类例:框架是容器的例子例:框架是容器的例子 SimpleFrameTest.java SimpleFrameTest.java五五.常用容器常用容器 import javax.swing.*;public class SimpleFrameTest public static void main(String args)SimpleFrame myframe=new SimpleFrame();myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);myframe.show();class SimpleFrame extends JFrame public SimpleFrame()setSize(WIDTH,HEIGHT);public static final int WIDTH=300;public static final int HEIGHT=200;2.2.定义相对框架定义相对框架通过调用通过调用toolkittoolkit来得到系统相关信息来得到系统相关信息例:CenteredFrameTest.java例:获得屏幕尺寸例:获得屏幕尺寸Toolkit kit=Toolkit kit=Toolkit.getDefaultToolkit();Toolkit.getDefaultToolkit();Dimension screenSize=Dimension screenSize=kit.getScreenSize();kit.getScreenSize();int screenHeight=screenSize.height;int screenHeight=screenSize.height;int screenWidth=screenSize.width;int screenWidth=screenSize.width;class CenteredFrame extends JFrame public CenteredFrame()/get screen dimensions Toolkit kit=Toolkit.getDefaultToolkit();Toolkit kit=Toolkit.getDefaultToolkit();Dimension screenSize=kit.getScreenSize();Dimension screenSize=kit.getScreenSize();int screenHeight=screenSize.height;int screenHeight=screenSize.height;int screenWidth=screenSize.width;int screenWidth=screenSize.width;/center frame in screen/center frame in screen setSize(screenWidth/2,screenHeight/2);setSize(screenWidth/2,screenHeight/2);setLocation(screenWidth/4,screenHeight/4)setLocation(screenWidth/4,screenHeight/4)/set frame icon and title /set frame icon and title Image img=kit.getImage(icon.gif);Image img=kit.getImage(icon.gif);setIconImage(img);setIconImage(img);setTitle(CenteredFrame);setTitle(CenteredFrame);3.3.常见类及方法常见类及方法APIAPIboolean isVisible()boolean isVisible()检查组件是否可见检查组件是否可见void setVisible(boolean b)void setVisible(boolean b)设置组件可见设置组件可见void setBounds(int x,int y,int void setBounds(int x,int y,int width,int height)width,int height)移动并缩放组件移动并缩放组件Dimension getSize()Dimension getSize()得到组件的大小得到组件的大小void setSize(int width,int height)void setSize(int width,int height)void setSize(Dimension d)void setSize(Dimension d)把组件缩放到指定调度和宽度把组件缩放到指定调度和宽度 void toFrond()void toFrond()放在其它窗口前面放在其它窗口前面void toBack()void toBack()放在其它窗口后面放在其它窗口后面void void setResizable(booleansetResizable(boolean b)b)缩放框架缩放框架void void setTitle(StringsetTitle(String s)s)设置标题设置标题void void setIconImage(ImagesetIconImage(Image image)image)将将ImageImage用作图标用作图标 Dimension Dimension getScreenSizegetScreenSize()()得到用户屏幕大小得到用户屏幕大小内容窗格是用来添加组件的,获得内容内容窗格是用来添加组件的,获得内容窗格的代码如下:窗格的代码如下:在在AWTAWT中可调用中可调用add()add()把组件直接添加把组件直接添加到到AWT FrameAWT Frame中中 ,但在但在SwingSwing中组件只中组件只能添加到内容窗格里能添加到内容窗格里六六.显示信息显示信息前面的例子中前面的例子中 ,信息都显示在控制台窗信息都显示在控制台窗口口,现在我们试着把信息显示到现在我们试着把信息显示到JFrameJFrame中中 JFrameJFrame的结构有点复杂,它包括:根窗格、的结构有点复杂,它包括:根窗格、布局窗格、透明窗格和布局窗格、透明窗格和内容窗格内容窗格 用户也可以创建一个画板,然后在画板上进用户也可以创建一个画板,然后在画板上进行绘制,最后将画板添加到内容窗格里,此行绘制,最后将画板添加到内容窗格里,此时需要重写时需要重写paintComponentpaintComponent()()paintComponent(GraphicspaintComponent(Graphics g)g)是定义在是定义在JComponentJComponent中,每当该方法被调用时,系统就中,每当该方法被调用时,系统就自动产生一个自动产生一个GraphicsGraphics类型的参数,传递给类型的参数,传递给paintComponentpaintComponent方法中的参数方法中的参数g gContainer cp=getContentPane();Container cp=getContentPane();Component c=;Component c=;cp.add(c);cp.add(c);GraphicsGraphics类提供绘制图像和输出文本的方法类提供绘制图像和输出文本的方法创建一个画板创建一个画板class MyPanel extends JPanel public void paintComponent(Graphics g)super.paintComponent(Graphics g)g.drawString(“Hello!world”).MyPanel扩展了扩展了JPanel,但面板的背景颜色等工但面板的背景颜色等工作要由作要由Jpanel来完成,来完成,super.paintComponent确保父类也参预绘制确保父类也参预绘制只要窗口重新绘制,只要窗口重新绘制,paintComponent()paintComponent()就被自动调用(在就被自动调用(在AWTAWT中是中是paint()paint()例例.在画板上输出信息在画板上输出信息NotHelloWorld.javaNotHelloWorld.javaclass NotHelloWorldFrame extends JFrameclass NotHelloWorldFrame extends JFrame public NotHelloWorldFrame()public NotHelloWorldFrame()setTitle(NotHelloWorld);setTitle(NotHelloWorld);setSize(WIDTH,HEIGHT);setSize(WIDTH,HEIGHT);/add panel to frame /add panel to frame NotHelloWorldPanel panel=new NotHelloWorldPanel panel=new NotHelloWorldPanel();NotHelloWorldPanel();Container contentPane=getContentPane();Container contentPane=getContentPane();contentPane.add(panel);contentPane.add(panel);class NotHelloWorldPanel extends JPanelclass NotHelloWorldPanel extends JPanel public void paintComponent(Graphics g)public void paintComponent(Graphics g)super.paintComponent(g);super.paintComponent(g);g.drawString(Not a Hello,World program,g.drawString(Not a Hello,World program,MESSAGE_X,MESSAGE_Y);MESSAGE_X,MESSAGE_Y);public static final int MESSAGE_X=75;public static final int MESSAGE_X=75;public public static final int MESSAGE_Y=100;static final int MESSAGE_Y=100;常用常用APIAPIContainer Container getContentPanegetContentPane()()返回返回JFrameJFrame的内容窗格的内容窗格 void void repainrepain()()重新绘制组件重新绘制组件void void repaint(intrepaint(int x,x,intint y,intwidth,inty,intwidth,int height)height)重新绘制组件的一部分重新绘制组件的一部分void paintComponent(Graphics g)void paintComponent(Graphics g)需要重写该方法来说明你的组件应如何绘制需要重写该方法来说明你的组件应如何绘制5.3图形编程图形编程一一.2D.2D图形图形 1.2D1.2D对象对象 随着随着SDK2.0SDK2.0版的到来,版的到来,J2SEJ2SE包含了一包含了一个个Java 2DJava 2D库,该库实现了一个非常强大库,该库实现了一个非常强大的图形操作集的图形操作集如何获得如何获得Graphics 2DGraphics 2D类对象类对象该类是该类是GraphicsGraphics类的子类,通常可用类的子类,通常可用GraphicsGraphics对象转换而来对象转换而来.例:例:public void paintComponent(Graphics g)public void paintComponent(Graphics g)graphics2D g2=(graphics 2D)g;graphics2D g2=(graphics 2D)g;.2.2.坐标坐标 JDK 1.0JDK 1.0版中使用整数像素坐标系版中使用整数像素坐标系java 2Djava 2D形体使用浮点数坐标系,这样可为形体使用浮点数坐标系,这样可为坐标指定单位。坐标指定单位。存在的问题存在的问题:Retangle2D r=.;:Retangle2D r=.;float f=float f=r.getWidthr.getWidth();/*Error*/();/*Error*/getWidth()getWidth()返回返回doubledouble值,应进行转换:值,应进行转换:float f=(float)r.getWidth();float f=(float)r.getWidth();例:DrwaTest.java因此,因此,2D2D库的形体类有两种版本:库的形体类有两种版本:Retangle2D.FloatRetangle2D.Float Retangle2D.Double Retangle2D.Doubleclass DrawPanel extends JPanel public void paintComponent(Graphics g)super.paintComponent(g);Graphics2D g2=(Graphics2D)g;/draw a rectangle double leftX=100;double topY=100;double width=200;double height=150;Rectangle2D rect=new Rectangle2D.Double(leftX,topY,width,height);g2.draw(rect);/draw the enclosed ellipse Ellipse2D ellipse=new Ellipse2D.Double();ellipse.setFrame(rect);g2.draw(ellipse);/draw a diagonal line g2.draw(new Line2D.Double(leftX,topY,leftX+width,topY+height);/draw a circle with the same center 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);3.常用APIRetangle2D.Float(float x,float y,float width,float height)Ellipse2D.Double(double x,double y,double width,double height)Retangle2D.Double(double x,double y,double width,double height)Line2D.double(Point2D start,Point2D end)Line2D.double(double startx,double starty,double endx,double endy)Point2D.Double(double x,double y)fill(Graphics2D rec)填充颜色drawGraphics2D rec)绘制图形rec二二.颜色颜色Graphics2DGraphics2D类的类的setPaintsetPaint方法方法(Graphics(Graphics类为类为setColorsetColor方法方法)用来设置颜色。例:用来设置颜色。例:g2.setPaint(Color.red);g2.setPaint(Color.red);g2.drawString(“Set g2.drawString(“Set Color”,100,100)Color”,100,100)1.1.标准颜色标准颜色blackblack、blueblue、cyancyan、darkgraydarkgray、graygray、greengreen、lightgraylightgray、magentamagenta、orangeorange、pinkpink、redred、whitewhite、yellowyellow2.2.复合色复合色通过指定红绿蓝三色比例,用通过指定红绿蓝三色比例,用ColorColor对象来复对象来复合成一种新的颜色。合成一种新的颜色。ColorColor构造器如下:构造器如下:Color(int redness,int greenness,int blueness)Color(int redness,int greenness,int blueness)其中参数取值为其中参数取值为0-2550-2553.3.常用常用APIAPIvoid void Color(intColor(int r,intr,int g,intg,int b)b)例例:g.setPaint(newg.setPaint(new Color(0,128,128);Color(0,128,128);void setcolor(Color c)void setPaint(paint p)void setBackground(Color c)void setForeground(Color c)例:填充颜色的例子FillTest.javaclass FillPanel extends JPanelclass FillPanel extends JPanel public void paintComponent(Graphics g)public void paintComponent(Graphics g)super.paintComponent(g);super.paintComponent(g);Graphics2D g2=(Graphics2D)g;Graphics2D g2=(Graphics2D)g;/draw a rectangle /draw a rectangle double leftX=100;double leftX=100;double topY=100;double topY=100;double width=200;double width=200;double height=150;double height=150;Rectangle2D rect=new Rectangle2D.Double Rectangle2D rect=new Rectangle2D.Double (leftX,topY,width,height);(leftX,topY,width,height);g2.g2.setPaint(Color.red)setPaint(Color.red);g2.g2.fillfill(rect);(rect);/draw the enclosed ellipse /draw the enclosed ellipse Ellipse2D ellipse=new Ellipse2D.Double();Ellipse2D ellipse=new Ellipse2D.Double();ellipse.setFrame(rect);ellipse.setFrame(rect);g2.g2.setPaint(new Color(0,128,128);setPaint(new Color(0,128,128);/a dull blue-green/a dull blue-green g2.g2.fillfill(ellipse);(ellipse);例:将字符串显示在画板中央的例子 FontTest.java三三.文本和字体文本和字体1.1.五个逻辑字体名五个逻辑字体名SanaSerifSanaSerifSerifSerifMonospacedMonospacedDialogDialogDialogInputDialogInput2.2.字体风格字体风格Font.PLAIN Font.PLAIN Font.BOLDFont.BOLDFond.ITALIC Fond.ITALIC Fond.BOLD+Font.ITALIC Fond.BOLD+Font.ITALIC 3.3.设置字体设置字体Font serif=new Font serif=new Font(“Serif”,Font.BOLD,14);Font(“Serif”,Font.BOLD,14);g2.setFont(serif);g2.setFont(serif);4.4.编程控制字体编程控制字体字符输出的效果取决于下面三个因素:字符输出的效果取决于下面三个因素:使用的字体使用的字体 字符串字符串 绘制字体的设备绘制字体的设备几个基本术语:上坡度下坡度空行 基线基线高度调用调用Graphics2DGraphics2D类中的类中的getFontRenderContextgetFontRenderContext方法,可获得一个方法,可获得一个FontRenderContextFontRenderContext类的对象类的对象,把这把这个对象传给个对象传给FondFond类的类的getStringBoundsgetStringBounds方法方法,该方法返该方法返回一个包围字符串的矩形回一个包围字符串的矩形.代码如下代码如下:String message=“Hello,World!”;Font f=new Foun(“serif”,Font.BOLD,14);FontRenderContext context=g2.getFontRenderContext();Retangle2D bounds=f.getStringBounds(message,context);获得字符串宽度、高度、上坡度、下坡获得字符串宽度、高度、上坡度、下坡度的方法如下:度的方法如下:double stringwidth=double stringwidth=bounds.getWidth();bounds.getWidth();double stringheigth=double stringheigth=bounds.getHeigth();bounds.getHeigth();double ascent=-bounds.getY();double ascent=-bounds.getY();double descent=bounds.getHeigth()double descent=bounds.getHeigth()+bounds.getY();+bounds.getY();基点将字符串显示在面板中央的代码如下:将字符串显示在面板中央的代码如下:String message=“Hello,World!”;Font f=new Foun(“serif”,Font.BOLD,14);FontRenderContext context=g2.getFontRenderContext();Retangle2D bounds=f.getStringBounds(message,context);double x=(getWidth()-double x=(getWidth()-bounds.getWidth()/2;bounds.getWidth()/2;double y=(getHeigth()-double y=(getHeigth()-bounds.getWidth()/2;bounds.getWidth()/2;double ascent=-bounds.getY();double ascent=-bounds.getY();double basey=y+ascent;double basey=y+ascent;g2.drawString(message,g2.drawString(message,(int)x,(int)basey);(int)x,(int)basey);例:将字符串显示在画板中央的例子例:将字符串显示在画板中央的例子 FontTest.java FontTest.javaAPI:Font(String name,int style,int Size)String getFontName()String getFamily()String getName()Retangle2D getStringBounds(String s,FountRenderContext context)float getAscent()float getDecent()float getHeight()float getWeight()void setFont(Font font)void DrawString(String str,int x,int y)四.图象ImageTest.java在在JavaJava应用程序应用程序中须通过使用中须通过使用ToolkitToolkit对对象,调用象,调用getDefaultToolkit()getDefaultToolkit(),完成将一,完成将一个图象文件加载到程序中,再调用个图象文件加载到程序中,再调用GraphicsGraphics类提供的类提供的DrawImage()DrawImage()显示它。显示它。目前只能读取目前只能读取gifgif和和JPEGJPEG格式的文件格式的文件下面一段代码用来在本地机上加载一个名下面一段代码用来在本地机上加载一个名为为 msn.jpgmsn.jpg的文件:的文件:Image Image imgimg=Toolkit.getDefaultToolkitToolkit.getDefaultToolkit().().getImage(“msn.jpggetImage(“msn.jpg”)”)若从网络上加载,必须提供URL例:例:URL u=new URL(“http:/”);Image img=Toolkit.getDefaultToolkit().Image img=Toolkit.getDefaultToolkit().getImage(u)getImage(u)显示代码:显示代码:public void paintComponent(Graphics g).g.drawImage(img,x,y,null);图象的跟踪加载使用MediaTracker类中的方法addImage()可以将一个图象的加载过程放入媒体跟踪器,从而实现对图象加载过程的跟踪MediaTracker tracker=new MediaTracker();Image img=ToolkitgetDefaultToolkit().getImage(name);Int id=1;tracker.addImage(img,id);Trytracker.waitForID(id);Catch(InterruptedException e)APIToolkit getDefaultToolkit()Image getImage(String filename)Boolean drawImage(Image img,int x,int y,ImageObserver observer)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)void dispose()Java awt.MediaTrackerVoid addImage(Image image,int id)Void waitForId(int id)Void waitForAll()/acquire the image image=Toolkit.getDefaultToolkit().getImage(msn.jpg);MediaTracker tracker=new MediaTracker(this);tracker.addImage(image,0);try tracker.waitForID(0);catch(InterruptedException exception)public void paintComponent(Graphics g)super.paintComponent(g);int imageWidth=image.getWidth(this);int imageHeight=image.getHeight(this);g.drawImage(image,0,0,null);for(int i=0;i*imageWidth=getWidth();i+)for(int j=0;j*imageHeight 0)g.copyArea(0,0,imageWidth,imageHeight,i*imageWidth,j*imageHeight);private Image image;