java 图形程序设计(GUI)

来源:互联网 发布:知识付费行业数据 编辑:程序博客网 时间:2024/05/20 09:23
GUI(Graphical User Interface) 图形用户界面    
在java刚出现的时候,包含了一个用于基本GUI程序设计的类库。Sun将他称为抽象窗口工具箱(Abstract Window ToolKit,awt)。基本awt库采用将处理用户界面元素的任务委派给每个目标平台(Window,Solaris,Macintosh等)的本地GUI工具箱的方式,由本地GUI工具箱负责用户界面元素的创建和动作。例如,如果使用最初的AWT在Java窗口中放置一个文本框,就会有一个低层的对等体文本框,用来真正的处理文本输入。从理论上来说,结果程序可以运行在任何平台上,但是观感(look and feel)的效果却依赖于目标平台,因此,Sun公司的口号是:一次编写,随处使用对于简单的应用程序来说,基于对等体方法的效果还是不错的,但是要想编写依赖于本地用户界面元素的高质量、可移植可图形库就会暴露出一些缺陷。例如:菜单,滚动条和文本域这些用户界面元素,在不同的平台上,操作行为存在一些微妙的区别,因此,有些图形环境(如X11/Motif)并没有像Windows或者Macintosh这样丰富的用户界面组件集合。这也就将基于对等体的可移植库限制在了“最小公分母”的范围内。其结果使AWT构建的GUI应用程序看起来没有Windows或者Macintosh那么漂亮,也没有提供哪些平台用户所认知的功能。更糟糕的是,在不同平台上的AWT用户界面库中存在不同的bug。研发人员必须在每一个平台上测试应用程序。后来,Netscape创建了一种称为IFC(Internet Foundation Class)的GUI库,它采用了与AWT完全不同的工作方式,他将按钮,菜单这样的用户界面元素绘制在空白窗口上,而对等体制需要创建和绘制窗口。因此,Netscape的IFC组件在程序运行的所有平台上的外观和动作都一样。Sun与Netscape合作创建了一个名为Swing的用户界面库Swing没有完全代替AWT,而是基于AWT的架构之上。Swing仅仅提供了能力更强大的用户界面组件。尤其在采用Swing编写的程序中,还需要使用基本的AWT处理时间。从现在开始,Swing是指被绘制的用户界面类,AWT是指向事件处理这样的窗口工具箱的底层机制创建框架—-在java中,顶层窗口(就是没有包含在其他窗口中的窗口)被称为框架(frame)在AWT库中,有一个称为Frame的类,用于描述顶层窗口,这个类的Swing版本名为JFrame,他扩展于Frame类,JFrame是极少数几个不绘制在画布上的Swing组建之一。因此,他的修士部件)如按钮,标题栏,图标等)由用户的窗口系统绘制,而不是由Swing绘制。绝大多数Swing组件类都以J开头,例如JButton,JFrame等。在Java中,有Button和Frame这样的类,但是他们属于AWT组件。如果偶然的忘记了书写J,程序仍然可以进行编译和运行,但是将Swing和AWT组件混合在一起使用将会导致视觉和行为的不一致以下将介绍有关Swing的JFrame常用方法。
java.awtClass EventQueuejava.lang.Objectjava.awt.EventQueuepublic class EventQueueextends ObjectEventQueue是一个独立于平台的类,用于从底层对等类和可信应用程序类排队事件。它封装了从队列中提取事件,并通过调用调度它们异步事件指派机制dispatchEvent(AWTEvent)这种方法EventQueue与该事件被分派作为参数。 这种机器的特殊行为是依赖于实现的。 唯一的要求是实际排队到这个队列的事件(注意,发布到EventQueue事件可以合并)被调度:
package NEW_DATE_SEQUENCE_PACKAGE;import java.awt.*;import javax.swing.*;/** * * @author cmx */public class J_9_1_6_swing {    public static void main(String [] args)    {        EventQueue.invokeLater(()->        {            SimpleFrame3 a=new SimpleFrame3();            a.setVisible(true);            a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        });    }}class SimpleFrame3 extends JFrame{    private static final int DEFAULT_WIDTH=300;    private static final int DEFAULT_HIGHT=200;    public SimpleFrame3()    {        setSize(DEFAULT_WIDTH,DEFAULT_HIGHT);    }}
运行结果:一个空白的窗口框架定位—-JFrame类本身只包含若干个改变框架外观的方法。当然,通过继承,从JFrame的超类中继承了很多用于处理框架大小和位置的方法。其中最重要的有下面几个:setLocation和setBounds方法用于设置框架的位置
setLocationpublic void setLocation(int x,                        int y)将组件移到新位置。通过此组件父级坐标空间中的 x 和 y 参数来指定新位置的左上角。参数:x - 父级坐标空间中新位置左上角的 x 坐标y - 父级坐标空间中新位置左上角的 y 坐标从以下版本开始:JDK1.1=============setBoundspublic void setBounds(int x,                      int y,                      int width,                      int height)移动组件并调整其大小。由 x 和 y 指定左上角的新位置,由 width 和 height 指定新的大小。参数:x - 组件的新 x 坐标y - 组件的新 y 坐标width - 组件的新 widthheight - 组件的新 height从以下版本开始:JDK1.1
setIconImage用于告诉窗口系统在标题栏、任务切换窗口等位置显示那个图标
setIconImagepublic void setIconImage(Image image)设置要作为此窗口图标显示的图像。将单个图像指定为窗口的图标时,可以使用此方法代替 setIconImages()。以下语句:     setIconImage(image);等价于:     ArrayList imageList = new ArrayList();     imageList.add(image);     setIconImages(imageList);注:根据上下文的不同(例如,窗口装饰、窗口列表、任务栏等),本机窗口系统可以使用不同尺寸的不同图像表示一个窗口。也可以对所有上下文使用一个图像,或者根本不用图像。覆盖:类 Frame 中的 setIconImage参数:image - 要显示的图标图像。
setTitle 用于改变标题栏的文字
setTitlepublic void setTitle(String title)将此窗体的标题设置为指定的字符串。参数:title - 要显示在窗体边框中的标题。 null 值视为空字符串 ""
setResizable 利用一个boolean值确定框架的大小是否允许用户改变
setResizablepublic void setResizable(boolean resizable)设置此窗体是否可由用户调整大小。参数:resizable - 如果此窗体是可调整大小的,则为 true;否则为 false
JFrame继承框架:
javax.swing 类 JFramejava.lang.Object  继承者 java.awt.Component      继承者 java.awt.Container          继承者 java.awt.Window              继承者 java.awt.Frame                  继承者 javax.swing.JFrame
JPanel继承框架
javax.swing 类 JPaneljava.lang.Object  继承者 java.awt.Component      继承者 java.awt.Container          继承者 javax.swing.JComponent              继承者 javax.swing.JPanel
对于Component类和window类(是Frame的超类)要仔细研究,从中找到缩放和改变框架的方法。例如:在Component类中的setLocation方法是重定位组建的一个方法。如果调用setLocation(x,y)则将窗口放置在左上角水平x像素,垂直y像素的位置。坐标(0,0)位于屏幕的左上角。同样的,Component中的setBounds方法可以实现一步重定位组件,
setBounds(x,y,width,height)
可以让窗口系统控制窗口的位置,如果在显示串口之前调用
setLocationByPlatform (true);
窗口系统会选用窗口的位置(而不是大小),通常是距离最后一个显示窗口最小偏移量的位置。对于框架来说,setLocation和setBounds中的坐标均相对于整个屏幕。在容器中包含的组件所指的坐标均相对于容器。**框架属性**组件类的很多方法是以获取/设置方法对形式出现的,例如:Frame类的下列方法:
public String getTitle();public void setTitle(String title);
这样的一个获取/设置方法对就被称为一种属性。属性中包含属性名和类型。将get或者set之后的第一个字母改为小写字母就可以得到相应的属性名。例如:Frame类有一个名为title且类型为String的属性。从概念上讲,title是框架的一个属性,当设置这个属性的时候,我们不关心如何实现这个属性。针对get/set约定由一个例外:对于类型为boolean的属性,获取方法由is开头。例如:下面两个方法定义了locationByPlatform属性:
public boolean isLocationByPlatform();public void setLocationByPlatform();=======================isLocationByPlatformpublic boolean isLocationByPlatform()如果此窗口下次可见时,出现在本机窗口操作系统的默认位置,则返回 true。如果窗口显示在屏幕上,则此方法始终返回 false。返回:此窗口是否将出现在默认位置==========================setLocationByPlatformpublic void setLocationByPlatform(boolean locationByPlatform)设置窗口下次可见时应该出现的位置:本机窗口系统的默认位置,还是当前位置(由 getLocation 返回)。此行为模拟显示的本机窗口,而不是以编程方式设置其位置。如果未显式设置窗口的位置,那么大多数窗口操作系统将重叠显示窗口。一旦窗口显示在屏幕上,其实际位置就被确定
确定合适的框架大小———要记住:如果没有明确的指定框架的大小,所有框架的默认值为0*0像素,为了让示例程序尽可能的简单,这里将框架的大小重置为大多数情况下都可以接受的显式尺寸。然而,对于专业应用程序来说,应该检查屏幕的分辨率,并根据其分辨率编写代码重置框架的大小,如在微型电脑的屏幕上,正常显示的窗口在高分辨率屏幕上可能变为一张邮票的大小。为了得到屏幕的大小,需要按照下列步骤操作。调用Toolkit类的静态方法getDefaultToolkit得到一个Toolkit对象(Toolkit类包含许多与本地窗口系统打交道的方法)。然后,调用getScreenSize方法,这个方法以Dimension对象的形式返回屏幕的大小,Dimension对象同时用公有实例变量width和height保存着屏幕的宽度和高度。下面是相关的代码:
package NEW_DATE_SEQUENCE_PACKAGE;import java.awt.*;import javax.swing.*;/** * * @author cmx */public class J_9_1_6_swing {    public static void main(String [] args)    {        EventQueue.invokeLater(()->        {            SimpleFrame3 a=new SimpleFrame3();            a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            Toolkit kit= Toolkit.getDefaultToolkit();            Dimension screenSize=kit.getScreenSize();            int screenWidth=screenSize.width;            int screenHeight=screenSize.height;            /**             * 下面,将框架大小设置为上面取值得50%,然后,告知窗口系统定位框架             */            a.setSize(screenWidth/2,screenHeight/2);            a.setLocationByPlatform((true));            a.setVisible(true);        });    }}class SimpleFrame3 extends JFrame{    private static final int DEFAULT_WIDTH=300;    private static final int DEFAULT_HIGHT=200;    public SimpleFrame3()    {        setSize(DEFAULT_WIDTH,DEFAULT_HIGHT);    }}
另外,还提供了一个图标,由于图像的描述与系统有关,所以需要再次使用工具箱加载图像。然后,将这个图像设置为框架的图标:
public abstract class Image      extends       Object抽象类 Image 是表示图形图像的所有类的超类。必须以特定于平台的方式获取图像。
对于不同的操作系统,所看到的图标显示位置可能不同。例如:在Windows中,图标显示在窗口的左上角,按下ALT+TAB,可以在活动任务的里表中看到相应程序的图标。下面是为了处理框架给予的一些提示:如果框架中只包含标准的组件,如按钮和文本框,那么通过调用pack方法设置框架大小。
packpublic void pack()调整此窗口的大小,以适合其子组件的首选大小和布局。如果该窗口和/或其所有者还不可显示,则在计算首选大小之前都将变得可显示。在计算首选大小之后,将会验证该窗口。
框架将被设置为刚好能放下所有组件的大小。在通常情况下,将程序的主框架尺寸设置为最大,可以通过调用下面方法将框设置的最大。
frame.setExtendedState(Frame.MAXIMIZED_BOTH);//setExtendedStatepublic void setExtendedState(int state)设置此窗体的状态。该状态表示为逐位掩码。MAXIMIZED_BOTHpublic static final int MAXIMIZED_BOTH此状态位掩码指示将窗体完全最大化(水平和垂直方向)。它只是 MAXIMIZED_VERT | MAXIMIZED_HORIZ 的一种便捷别名。
牢记用户定位应用程序的框架位置、重置框架大小,并且在应用程序再次启动时恢复这些内容是一个不错的想法。
GraphicsDevice类还允许以全屏模式执行应用。//isFullScreenSupportedpublic boolean isFullScreenSupported()如果此 GraphicsDevice 支持全屏独占模式,则返回 true。如果安装了 SecurityManager,则将使用 AWTPermission("fullScreenExclusive") 调用它的 checkPermission 方法。只有授权时 isFullScreenSupported 才会返回 true
ImageIconpublic ImageIcon(String filename)根据指定的文件创建一个 ImageIcon。使用 MediaTracker 预载图像以监视图像的加载状态。指定 String 可以是一个文件名或是一条文件路径。在指定一条路径时,可使用 Internet 标准正斜杠 ("/") 作为分隔符。(该字符串被转换成一个 URL,而正斜杠适用于所有系统。)例如,指定:    new ImageIcon("images/myImage.gif") ================    getImagepublic Image getImage()返回此图标的 Image。================setIconImagepublic void setIconImage(Image image)设置要作为此窗口图标显示的图像。将单个图像指定为窗口的图标时,可以使用此方法代替 setIconImages()。以下语句:     setIconImage(image);等价于:     ArrayList imageList = new ArrayList();     imageList.add(image);     setIconImages(imageList);注:根据上下文的不同(例如,窗口装饰、窗口列表、任务栏等),本机窗口系统可以使用不同尺寸的不同图像表示一个窗口。也可以对所有上下文使用一个图像,或者根本不用图像。覆盖:类 Frame 中的 setIconImage参数:image - 要显示的图标图像。

 

一、问题

ImageIcon icon = new ImageIcon(“a.gif”);

执行结果是icon无法显示

 

二、解决

 

类中有如下调用:

ImageIcon icon = new ImageIcon(“a.gif”);

 

很自然地认为当前类文件和图片在同一路径下即可。

其实所谓的相对路径起点是工程的根目录,即project

这行代码执行时在project目录下查找名为a.gif的文件,结果当然是找不到。

要得到工程的相对路径可通过System.getProperty(“user.dir”)得到。

对图片和对文件的查找应该是一致的,如new File()

假如你的工程根目录为:project1

你的图片文件放在:project1/src/images/a.gif

 

所以正确的调用是:

ImageIcon icon = new ImageIcon(“src//images//a.gif”);

这行代码执行时在project/test目录下查找到了文件

 

总结起来就是一句话:所谓相对路径就是相对于工程根目录的位置^_^

 

三、其他

查看了一下ImageIcon的构造函数。

Public ImageIcon(String filename)//参数可以是绝对路径也可以是相对路径

Public ImageIcon(URL url)

 

第一种构造不在赘述。

第二种通过URL来得到图片

URL url = getClass().getResource(“a.gif”); //当前编译后class文件所在目录查找

ImageIcon icon = new ImageIcon(url);

 

ImageIcon支持GIFJPGPNG等格式。

java.awt.Component    boolean isVisible()    void setVisible(boolean b)    获取或者设置visible属性,组件最初是可见的,但是JFrame这样的顶层组件例外    void setSize(int width, int height)    使用给定的宽度和高度,重新设置组建的大小;    void setLocation(int x ,int y)    将组件移到一个新的位置上,如果这个组件不是顶层组件,x和y坐标(或者p.x和p.y)是容器坐标;否则是屏幕坐标    void setBounds(int x,int y, int width, int height)    移动并重新设置组件的大小    Dimension getSize()    void setSize(Dimension d)    获取或者设置当前组件的size属性
java.awt.Window    void toFront()    将这个窗口显示的到其他窗口的前面    void toBack()    将这个窗口移到桌面窗口栈的后面,并相应的重新排列所有的可见窗口。    boolean isLocationByPlatform()    void setLocationByPlatform(boolean b);    获取或者设置locationByPlatform属性。这个属性在窗口显示之前被设置,由平台选择一个合适的位置;
java.awt.Frame    boolean isResizable()    void setResizable(boolean b)    获取或者设置resizable属性,这个属性设置后,用户可以重新设置框架的大小    String getTitle()    void setTitle(String s)    获取或者设置title属性,这个属性确定框架标题栏中的文字    Image getIconImage()    void setIconImage(Image image)    获取或者设置iconImage属性,这个属性确定框架的图标,窗口系统可能会将图表作为框架装饰或者其他部位的一部分显式。    boolean isUndecorated()    void setUndecorated(boolean b)    获取或者设置undecorated属性,这个属性设置后,框架显式中将没有标题栏或关闭按钮这样的装饰。在框架显式之前,必须调用这个方法    int getExtendedState()    void setExtendedState(int state)    获取或者设置窗口状态
java.awt.Toolkit    static Toolkit getDefaultToolkit()    返回默认的工具箱    Dimension getScreenSize()    返回用户屏幕的尺寸
java.swing.ImageIcon    ImageIcon(String filename)        构造一个图标,其图像存储在一个文件中    Image getImage()    获得该图标的图像。

在组件中显示信息

接下来将讨论如何在框架内显示信息。例如,我们不再像以前那样,采用文本方式在控制台窗口中显示信息。而是在框架中显示这个信息。
可以将消息字符串直接绘制在框架中,但这并不一定是一种很好的编程习惯。在Java中,框架被设计为放置组件的容器,可以将菜单栏和其他的用户界面元素放置在其中。在通常情况下,应该在另一组件上绘制信息,并将这个组件添加到框架中。
JFrame的结构相当复杂。在图中给出了JFrame的结构。可以看到,在JFrame中有四层面板,其中的根面板,层级面板,和玻璃面板我们不太关心,他们是用来组织菜单栏和内容窗格以及实现观感的。swing程序员最关心的是内容窗格(content pane)在设计框架的时候,要使用以下代码将所有的组件添加到内容窗格中:

                    getContentPanejavax.swing 类 JFramejava.lang.Object  继承者 java.awt.Component      继承者 java.awt.Container          继承者 java.awt.Window              继承者 java.awt.Frame                  继承者 javax.swing.JFramegetContentPanepublic Container getContentPane()返回此窗体的 contentPane 对象指定者:接口 RootPaneContainer 中的 getContentPane返回:contentPane 属性
                        Containerpublic class Container extends       Component一般的 Abstract Window Toolkit(AWT) 容器对象是一个可包含其他 AWT 组件的组件。添加到容器中的组件放在一个列表中。列表的顺序将定义组件在容器内的正向堆栈顺序。如果将组件添加到容器中时未指定索引,则该索引将被添加到列表尾部(此后它位于堆栈顺序的底部)。java.awtContainerjava.lang.Object  继承者 java.awt.Component      继承者 java.awt.Container=================                        getPreferredSizepublic Dimension getPreferredSize()返回此容器的首选大小。如果尚未通过 Component.setPreferredSize(Dimension) 显式设置首选大小,并且此 Container 有一个 non-null LayoutManager,则使用 LayoutManager.preferredLayoutSize(Container) 来计算首选大小。注:一些实现可能缓存从 LayoutManager 返回的值。每次调用此方法时,这些缓存实现不需要在 LayoutManager 上调用 preferredLayoutSize,而是只在 Container 变得无效之后查询 LayoutManager。覆盖:类 Component 中的 getPreferredSize//代码Container contentPane=frame.getContentPane();Component c=...;contentPane.add(c);

在java SE 中,JFrame类中的add方法抛出了一个异常信息“Do not use JFrame.add. Use JFrame.getContentPane().add instead.如今,JFrame.add方法不再显示这些提示信息,只是简单的调用内容窗格的add
因此,可以直接调用
frame.add(c);
在这里,打算将一个绘制消息的组件添加到框架中。绘制一个组件,需要定义一个扩展JComponent类,并覆盖其中的paintComponent方法
paintComponent方法有一个Graphics类型的参数,这个参数保存着用于绘制图像和文本的设置,例如,设置字体或者当前的颜色。在Java中,所有的绘制都必须使用Graphics对象,其中包含了绘制图案,图像和文本的方法。
Graphics参数与Windows中的设备环境或者X11程序设计中的图形环境基本相似.
有些程序员更喜欢扩展JPanel,而不是JComponent。JPanel是一个可以包含其他组建的容器(container),但同样可以在器上面绘制。有一点不同之处是,面板不透明,意味着需要在面板的边界绘制所有的像素。最容易实现的方法是:在每个面板子类的paintComponent方法中调用super.paintComponent来用背景色绘制面板

class Not extends JPane;{    public void paintComponent(Graphics g)    {        super.paintComonent(g);        ...    }
class component3 extends JPanel{   private int Width1=75;   private int Height1=100;   public void paintComponent(Graphics g)   {     //  super.paintComponent(g);       g.drawString("wel0001212..........", Width1, Height1);   }}//对比class component3 extends JPanel{   private int Width1=75;   private int Height1=100;   public void paintComponent(Graphics g)   {       super.paintComponent(g);       g.drawString("wel0001212..........", Width1, Height1);   }}//显示是一样的
javax.swing.JFrame    Container getContentPane()    返回这个JFrame的内容窗格对象    Component add(Component c)    讲一个给定的组件添加到该框架的内容窗格中    (在框架类中add,不需要隐式对象)    //如    class NotHello extends JFrame    {        public NotHello()        {            add(new NotComponent);            pack();        }    }
总结:定义一个框架class XFrame extends JFrame{    public XFrame()    {        ...    }}//中间可以为setSize();add(组件);
//总结:定义一个组件class NotHello extends JComponent{    public void  paintComponent(Graphics g)    {        ...    //Graphics 操作    }    public Dimension getPreferredSize()  //组件必须有一个首选大小,或者是默认大小    {        return new Dimension(width, height);    }}//或者class Not extends JPane{    public void paintComponent(Graphics g)    {        super.paintComponent(g);        ...    }}
//总结:添加JFrame(Component在JFrame类中添加,不在这里添加,层次分明)public static void main(String[] args){    EventQueue.invokeLater(()->    {        JFrame f=new NotHello();  //引入一个框架就是创建一个框架类        f.setTitle();        f.setDefaultCloseOperation(Frame.EXIT_ON_CLOSE);        f.setVisible(true);    }}
java.awt.Component    void repaint()    尽可能快的重新绘制组件    Dimension getPreferredSize()    要覆盖这个方法,返回这个组建的首选大小 //组件都应该有一个首选大小javax.swing.JComponent    void paintComponent(Graphics g)    覆盖这个方法来描述如何绘制自己的组件java.awt.Window    void pack()    调整窗口的大小,当有多个组件,只想使用它们的首选大小,可以调用pack()