• 1. 学习导读 首先,我们学习一些基本的图形编程知识,包括窗口的显示及外观设置、在窗口中显示文字和图像等; 接下来,介绍Java的事件处理机制,例如如何在程序中接收并处理如键盘按键和鼠标点击等“事件”; 最后,系统地介绍图形用户界面中常用组件的用法,如布局管理器、文本框、复选框、菜单、对话框等。 第七章 图形用户界面的设计与实现
  • 2. 教学重点与难点:框架的组成及外观 在框架中显示文本和图形 字体和颜色的设置 Java的事件处理机制 窗口事件、焦点事件、键盘事件、鼠标事件的处理 Swing各种组件的用法
  • 3. 7.1 图形用户界面概述 Java1.0的出现带来了抽象窗口工具箱(AWT)。设计目标是希望构建一个通用的GUI,使得利用它编写的程序能够运行在所有的平台上,以实现Sun公司提出的口号“一次编写,随处运行”。 在Java1.2中,Sun公司推出了新的用户界面库:Swing。相对AWT来说,Swing功能更强大、使用更方便,它的出现使得Java的图形用户界面上了一个台阶。 但是,Swing并没有代替AWT。在Java1.1中,AWT事件处理模型有了根本改变。Swing使用的仍然是Java1.1的事件处理模型。
  • 4. 7.2 简单图形用户界面 7.2.1 第一个图形用户界面 在Java中,顶层窗口称为框架。在AWT库中,对应于框架的类是Frame,在Swing库中,相应的类是JFrame。JFrame类扩展了Frame类。大部分AWT组件在Swing中都有等价的组件,它们在表示形式上差一个“J”。 框架是一个容器,我们可以在这个容器中放入其他一些图形用户界面组件,如按钮、菜单等,从而组成一个功能完善的程序。
  • 5. 【例7.1】 显示一个空框架 import javax.swing.*;  public class FirstFrame { public static void main(String[] args) { SimpleFrame frame = new SimpleFrame(); //设置用户关闭框架时的响应动作 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //显示该框架 frame.show(); } }  class SimpleFrame extends JFrame { public SimpleFrame() { //设置框架大小 setSize(WIDTH, HEIGHT); } public static final int WIDTH = 300; public static final int HEIGHT = 200; } 运行结果
  • 6. 7.2.2 框架外观 JFrame类的继承层次图
  • 7. Component类是所有GUI对象的祖先,Window类是Frame类的父类,JFrame类直接从Frame继承而来。对于框架外观的操作比较重要的方法如下: setIconImage——窗口最小化(在Java中称为图标化)时,把一个Image对象用作图标。 setTitle——设置窗口中标题栏的文字。 setResizable——设置用户是否可以改变框架大小。 dispose方法——关闭窗口,并回收该窗口的所有资源。 setLocation——设置组件的位置。 setBounds——重新设置组件的大小和位置。
  • 8. 【例7.2】 框架外观的设置 设置具有以下特征的框架: 它的高度和宽度为整个屏幕的1/3; 自定义窗口的标题和图标; 窗口的大小不可变。 程序代码见FrameSizeSet.java。运行结果如下: 图标标题最大化按钮失效
  • 9. 7.2.3 在框架中显示信息 JFrame包含了四个窗格:RootPane、LayeredPane、GlassPane和ContentPane。如果需要将一些图形用户界面元素加入到框架中,我们需要在面板组件(JPanel)中进行绘制,然后将该面板组件加入到框架的内容窗格(ContentPane)中。相应的代码如下: //得到JFrame的内容窗格对象 Container contentPane = getContentPane(); Component c = ...; //将组件加入到内容窗格中 contentPane.add(c); 面板JPanel类本身是容器,它可以容纳其他图形用户界面元素,如按钮、菜单等。
  • 10. 为了在面板中进行绘制,需要重载JComponent类的paintComponent方法。 class MyPanel extends Jpanel { public void paintComponent(Graphics g) { super.paintComponent(g); ...//相关的绘制代码 } } paintComponent方法是自动执行的,当窗口需要被重新绘制时,如用户缩放窗口,或还原已最小化的窗口时,系统就会自动调用该方法。 在框架中显示文本信息的方法: g.drawString(text, x, y)
  • 11. 【例7.3】 在框架中显示信息 程序代码见HelloWorld .java。运行结果如下:
  • 12. 7.2.4 文本和字体 通过Font类对象设置字体。 Font StringFont = new Font (“宋体”, Font.ITALIC, 20 ); 字体风格有以下几种选项: Font.PLAIN //常规 Font.BOLD //加粗 Font.ITALIC //倾斜 不同的系统中安装了不同的字体,为了得到本系统中所有已安装的字体,我们可以通过GraphicsEnvironment类的getAvailableFontFamilyNames方法来实现。该方法返回一个字符串数组,数组内包含所有可用的字体名。 【例7.4】显示系统中所有字体名。程序见ListFonts.java
  • 13. 【例7.5】字体设置 采用“宋体”显示字符串“你好,Java!”,字体风格为加粗、倾斜,大小为20点。 程序代码见FontSet.java。运行结果如下:
  • 14. 7.2.5 绘制简单图形 利用Graphics类提供的一些方法进行简单图形的绘制。如:drawLine、drawPolyLine、drawPolygon、drawArc。 drawLine用来画线,调用格式: void drawLine(int x1, int y1, int x2, int y2) (x1, y1)和(x2, y2)为线的两个端点。 drawPolygon用来绘制多边形,调用格式: void drawPolygon(Polygon p) 参数是多边形对象Polygon ,先定义Polygon对象,然后将点加入到该对象中,然后利用drawPolygon进行多边形的绘制: Polygon p = new Polygon; p.addPoint(x1, y1); p.addPoint(x2, y2); ... g.drawPolygon(p);
  • 15. 【例7.6】简单图形的绘制 直线,弧,多边形的绘制。 程序代码见SimpleDraw.java。运行结果如下:
  • 16. Java提供了矩形、圆角矩形、椭圆等基本形状的绘制方法: 矩形: void drawRect(int x, int y, int width, int height) 圆角矩形: void drawRoundRect(int x, int y, int width, int height, int arcWidth,int arcHeight) 椭圆: void drawOval(int x, int y, int width, int height) Java还提供了方便的填充封闭图形的方法,只需要将前面介绍的方法中的draw改为fill即可。如: void fillRect(int x, int y, int width, int height) void fillRoundRect(int x, int y, int width, int height, int arcWidth,int arcHeight) void fillOval(int x, int y, int width, int height)
  • 17. 7.2.6 颜色 Graphics类提供了与颜色相关的方法: getColor——返回当前颜色设置。 setColor——设置当前颜色。 setColor方法的调用格式为: void setColor(Color c) 我们可以选用Color类提供的13种标准颜色的预定义常数,也可以采用Color构建器来创建Color对象: Color(int redness, int greenness, int blueness) 参数redness,greenness,blueness分别表示红、绿、蓝的值,它们的值在0至255范围内。以下是颜色使用的例子: g.setColor(Color.green); g.drawString(“你好!”, 100, 100); g.setColor(new Color(128, 0, 128); //自定义颜色 g.drawString(“你好!”, 100, 200);
  • 18. JFrame类的超类Component类提供的颜色操作的相关方法: setBackground——设置背景色。 setForeground——设置在组件上进行绘制的默认颜色。 【例7.7】 颜色设置 设置图形颜色,将框架背景颜色设置为桌面的颜色。 程序代码见ColorRect.java。运行结果如下:
  • 19. 7.2.7 图像 通过Graphics类提供的drawImage方法实现图像的显示: public void paintComponent(Graphics g) { ... g.drawImage(image, x, y, null); } 参数image封装了要显示的图像文件。通过Toolkit类的静态getDefaultToolkit方法,可以读取GIF文件和JPEG文件: String name = “test.gif”; Image image = Toolkit.getDefaultToolkit().getImage(name); 通过以上代码,可以得到一个本地图像文件,如果要在网络上得到一个图像文件,必须使用URL类。相应的代码如下: URL url = new URL(“http://www.sun.com/im/sun_logo.gif”); Image image = Toolkit.getDefaultToolkit().getImage(url);
  • 20. 【例7.8】显示图像 从本地加载一幅图像,并在窗口的中间显示。 程序代码见ImageShow.java。运行结果如下:
  • 21. 7.3 事件处理 7.3.1 事件处理原理 如果用户在用户界面执行了一个动作,这将导致一个事件的发生。事件是描述发生了什么的对象。在Java中,定义了各种不同类型的事件类,用来描述各种类型的用户操作。 事件是由事件源产生的,事件的产生者称为事件源。例如,在Button组件上点击鼠标会产生以这个Button为源的一个事件:ActionEvent。 事件源拥有自己的方法,我们通过它向其注册事件监听器。事件监听器是一个类的实例,这个类实现了一个特殊的接口,称为Lintener interface。当事件源产生了一个事件以后,事件源就会发送通知给相应的事件监听器,监听器对象根据事件对象内封装的信息,决定如何响应这个事件。
  • 22. 我们可以通过以下方法来注册监听器对象: eventSourceObject.addEventListener(eventListenerObject); 以按钮类对例: MyActionListener listener = ...; JButton button = new JButton(”提交”); button.addActionListener(listener); 监听器对象listener所属的类MyActionListener必须实现相应的接口,以响应事件: public class MyActionListener implements ActionListener { ... public void actionPerformed(ActionEvent event) { //相应的响应操作 } }
  • 23. 7.3.2 处理按钮点击事件 创建按钮: JButton MyButton = new JButton(“Java”); 通过Container类的Add方法,将组件加入到该容器中。 class MyPanel extends JPanel { public MyPanel() { JButton MyButton = new JButton(“Java”); add(MyButton); } } 为按钮设置监听器。指定的监听器必须实现ActionListener接口的actionPerformed方法: public void actionPerformed(ActionEvent event)
  • 24. 【例7.9】点击按钮 采用内部类ButtonAction充当事件监听器。 在面板中放置两个按钮,当用户点击其中一个按钮时,面板中显示对应的操作。例如,如果点击“按钮一”,显示“您点击的是:按钮一” 。 程序代码见ButtonClick.java。运行结果如下:
  • 25. 7.3.3 捕获窗口事件 JFrame对象是窗口事件(WindowEvent)的事件源,我们要指定一个监听器对象: MyWindowListener listener = ...; frame.addWindowListener(listener); 监听器对象要实现WindowListener接口。WindowListener接口中共有七个方法,它们分别对应七个窗口事件: public interface WindowListener { void windowOpened(WindowEvent e); void windowClosing(WindowEvent e); void windowClosed(WindowEvent e); void windowIconified(WindowEvent e); void windowDeiconified(WindowEvent e); void windowActivated(WindowEvent e); void windowDeactivated(WindowEvent e); }
  • 26. WindowListener接口实现方法一: 定义一个类来实现WindowListener接口,在感兴趣的方法中添加我们需要的代码,然后让其他方法为空即可。 class QuitWindow implements WindowListener { public void windowClosing(WindowEvent e) { System.exit(0); }   void windowOpened(WindowEvent e) {} void windowClosed(WindowEvent e) {} void windowIconified(WindowEvent e) {} void windowDeiconified(WindowEvent e) {} void windowActivated(WindowEvent e) {} void windowDeactivated(WindowEvent e) {} }
  • 27. WindowListener接口实现方法二: Java为每个具有多个方法的AWT监听器接口提供了一个适配器类。适配器类实现了监听器接口的所有方法,但是却不做任何实际工作。与WindowListener接口对应的WindowAdapter类实现了以上七个空方法,我们只需要通过扩展适配器类来实现我们感兴趣的方法。 class QuitWindow extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } 【例7.11】捕获窗口事件 捕获窗口的关闭事件。 程序代码见WindowClosing.java。
  • 28. 7.3.4 AWT事件层次结构图 AWT事件类的继承关系图
  • 29. AWT将事件分为两类: 语义(Semantic)事件 ActionEvent:对应按钮点击、菜单选择、列表框选择、在文本域中按回车键等。 AdjustmentEvent:用户调整滚动条。 ItemEvent:用户从一组选择框或者列表项中进行选择。 TextEvent:文本域或者文本框中的内容发生改变。 低级(Low-Level)事件 ComponentEvent:组件大小改变、移动、显示或者隐藏。 KeyEvent:键盘上的一个键被按下或者释放。 MouseEvent:鼠标按键被按下、释放、鼠标移动或者拖动。 FocusEvent:组件获得焦点或者失去焦点。 WindowEvent:窗口被激活、屏蔽、最小化、最大化或关闭。 ContainerEvent:添加或者删除一个组件。
  • 30. 7.3.5 焦点事件 如果某个组件能够接收用户按键,那么该组件就拥有焦点。拥有焦点的组件在显示形式上与其他组件有一些差别:文本域内会显示光标;按钮四周会显示一个由虚线组成的矩形框。 可以捕获丢失的焦点事件来进行输入的合法性检查。如果输入不合法,通过调用requestFocus方法把焦点重新移回到该文本域,提示用户重新输入: public void focusLost(FocusEvent event) { //passText为需要进行合法性检查的文本域 if(event.getComponent()==passText&&!event.isTemporary()) { // isFormatValid为自定义方法,用户检查合法性 if(!isFormatValid(passText.getText())) passText.requestFocus(); } }
  • 31. 7.3.6 键盘事件 KeyListener接口中有三个方法: public void keyPressed(KeyEvent e) public void keyReleased(KeyEvent e) public void keyTyped(KeyEvent e) Java对于用户按键的处理过程: 当前键盘状态为小写状态,要输入一个大写字母“A”,我们的操作过程为:先按住Shift键不放,再按下A键,然后松开。整个过程Java会产生五个事件: 按下Shift键:为VK_SHIFT调用keyPressed方法; 按下A键:为VK_A调用keyPressed方法; 键入字符“A”:为字符“A”调用keyTyped方法; 松开A键:为VK_A调用keyReleased方法; 松开Shift键:为VK_SHIFT调用keyReleased方法。
  • 32. 【例7.12】捕获键盘事件 用户每次按下键盘上的某个键,程序捕获键盘输入,并显示在面板中,内容包括:虚拟键码、键的名称和字符。例如:当前键盘状态为小写状态,用户按下“A”键,显示的值依次为:65,A,a。 程序代码见KeyPress.java。运行结果如下:
  • 33. 7.3.7 鼠标事件 MouseListener接口 : mousePressed:鼠标键被按下时调用; mouseReleased:鼠标键被释放时调用; mouseClicked:合并上述两个事件为一次鼠标点击事件。 这三个方法的参数是MouseEvent,通过getX和getY方法,能够得到鼠标点击时的鼠标指针的x和y坐标。通过getClickCount方法,可以区别是单击操作,还是双击操作。 MouseMotionListener接口 : mouseMoved:鼠标移动; mouseMoved :用户拖动鼠标。 鼠标指针形状的设置: setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
  • 34. 【例7.13】利用鼠标进行绘图 点击窗口中的空白处,得到一张“笑脸”的图像; 点击已存在的图像,图像在“笑脸”和“哭脸”之间切换; 用鼠标可以对图像进行拖动操作; 在窗口左上角,显示当前鼠标光标的位置。 程序代码见MouseDraw.java。运行结果如下:
  • 35. 7.4 Swing组件 7.4.1 Swing组件 的类继承关系
  • 36. 7.4.2布局管理器 在Java中,提供了布局工具以支持用户界面元素的自动定位。容器中的所有组件都由一个布局管理器进行动态管理。 流布局管理器 在一行上水平排列组件,直到该行没有足够的空间为止,然后另起一行继续排列。当用户缩放容器时,布局管理器将进行自动控制,重新排列。我们可以指定流布局管理器的组件排列方式,如居中(默认)、左对齐、右对齐等。如: setLayout(new FlowLayout(FlowLayout.LEFT)); //左对齐 setLayout(new FlowLayout(FlowLayout.RIGHT)); //右对齐 setLayout(new FlowLayout(FlowLayout.CENTER)); //居中
  • 37. 边界布局管理器 边界布局管理器的布局分为五个位置:CENTER、EAST、WEST、NORTH、SOUTH,我们可以把组件放在这五个位置的任意一个,如果未指定位置,则缺省的位置是CENTER。 采用边界管理器进行布局时,四周的组件先被放置,剩余的空间由位于中间的组件占用;当容器的大小改变时,四周组件的厚度不会被改变,而中间组件的大小需要改变。
  • 38. 【例7.14】 流布局管理器示例 程序代码见FlowLayoutTest.java。运行结果如下: java FlowLayoutTest 10 java FlowLayoutTest 15
  • 39. 【例7.15】边界布局管理器示例 将三个按钮置于南区,而两个文本置于北区。 程序代码见BorderLayoutTest.java。运行结果如下:
  • 40. 7.4.3 文本组件 Java提供的文本组件:用于单行文本输入的文本域(JTextField)和用于多行输入的文本区(JTextArea)。 获得文本域的内容 add1 = Integer.parseInt(originText.getText().trim()); 跟踪文本域内容的修改 //新建文档监听器 DocumentListener resultListener = new ResultListener(); ... //为第一个文本域安装一个文档监听器 originText.getDocument().addDocumentListener(resultListener); 当文本发生改变后,下面三个方法之一会被调用: void insertUpdate(DocumentEvent e) void removeUpdate(DocumentEvent e) void changedUpdate(DocumentEvent e)
  • 41. 重新设置文本域的内容 resultText.setText(s); 【例7.16】获取两个文本域的输入并求和,然后显示在第三个文本域中。 程序代码见TextFieldTest.java。运行结果如下:初始状态改变输入
  • 42. 密码域JPassworkField 特殊的文本域,在密码域中输入时,用户的输入并不会真正显示出来,而是显示回显符,如“*”,以防止被他人看见用户输入的密码。 【例7.17】将密码域的输入显示在文本域中 程序代码见PasswordFieldTest.java。运行结果如下:
  • 43. 文本区组件 在一个文本区里,用户可以输入多行文本,多行文本之间的换行可以采用三种方式: 1)手动换行。即输入ENTER键,这将在文本中插入换行符“\n”。 2)通过设置换行属性来避免手动换行,由文本区组件自动处理。 textArea.setLineWrap(true); 但是这样的设置并没有真正在文本中插入换行符“\n”。 3)给文本区增加滚动条,这可以通过把文本区插入到一个滚动窗格中来实现。这也是给其他组件添加滚动条的方法。 JScrollPane scrollPane = new JScrollPane(textArea);
  • 44. 【例7.18】文本区的三种显示方式 程序代码见TextAreaTest.java。运行结果如下:
  • 45. 7.4.4 标签 让我们回头看看前面的示例结果,我们必须记住组件的位置,否则无法分辨出各个组件。对于程序编制者,这还可以解决,但是对于一般用户,就相当困难了。因此,为了在运行时能够识别组件,我们需要标签组件。 JLable label = new JLabel(“NoWrapArea”, JLabel.LEFT); 通过上面的代码我们建立了一个标签对象,其显示的文本是“NoWrapArea”,对齐方式为左对齐。
  • 46. 7.4.5 按钮 为在按钮上显示相应的信息,可以提供初始的文本和图标。 loginButton = new JButton("登录", new ImageIcon("login.gif")); 当希望按钮对单击动作有所反应时,我们需要为按钮注册一个事件监听器,并且实现这个事件监听器,就可以完成所需要的按钮功能。 //注册事件监听器 loginButton.addActionListener(new LoginAction()); //实现事件监听器 private class LoginAction implements ActionListener
  • 47. 【例7.19】密码验证示例 当用户输入密码后,按下“登录”按钮,然后我们将密码输入是否正确的结果显示在文本域中。 程序代码见Login.java。运行结果如下:
  • 48. 7.4.6 Swing常用的选择类组件 单选按钮组件 单选按钮组件是一组互斥按钮,即我们一次只能选择其中的一个选项,选项的选取只需要单击即可。 ButtonGroup group = new ButtonGroup(); JRadioButton button1 = new JRadioButton(“EAST”, true); ... JRadioButton button4 = new JRadioButton(“NORTH”, false); 为指定单选按钮的初始选项,我们在新建JRadioButton对象时,将其构造器的第二个参数设置为“true”;同时,其他按钮对象的第二个参数被设置为“false”。
  • 49. 【例7.20】单选按钮组件示例 通过选择单选按钮中的选项来设置标签组件的内容,由标签组件显示我们的选择。 程序代码见RadioButtonExample.java。运行结果如下:
  • 50. 复选框组件 复选框组件可以进行多重选择,即我们能够选择其中的多个选项,如果要取消或选取某选项,可以单击此选项。 和单选按钮不同,复选框允许用户选择多个选项。我们通过单击复选框来选取该选项,再单击一下,则取消选取。建立复选框组件对象需要使用标签来表明该复选框的含义,标签在复选框构造器里进行设置;对复选框是否被选取可以通过isSelected方法进行状态判断。 boldCheck = new JCheckBox(“Bold”); //新建复选框。 italicCheck = new JCheckBox(“Italic”); //新建复选框。 boldCheck.isSelected(); //判断“mathCheck”复选框是否被选定。
  • 51. 【例7.21】复选框组件示例 选择字体风格。 程序代码见CheckBoxExample.java。运行结果如下:
  • 52. 列表框组件 列表框组件允许用户从一个列表中选择一个或多个条目。用户可以从列表框中选择一个或多个条目。 建立列表框前,需要指定所显示的列表条目: String[] courses = {“Math”, “English”, “Physics”, “Chemic”, “Biology”, “Politics”}; JList courseList = new JList(courses); 如果列表框比较长,而显示屏幕比较小,可以设置列表中显示的行数,同时使用滚动条: courseList.setVisibleRowCount(4); JScrollPane listScrollPane = new JScrollPane(courseList); 选择列表框中的多个条目有两种方式: 连续条目选择和间断条目选择。
  • 53. 用户选择列表框条目时,列表框就会产生选择事件。将列表选择监听器ListSelectionListener添加给列表组件,并在该监听器中实现valueChanged方法: courseList.addListSelectionListener(new courseListener()); ... private class courseListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent event) {...} } 获得用户所选择的列表框条目以及条目所在的索引号需要使用getSelectedValues方法和getSelectedIndices方法: Object[] selectedCourses = courseList.getSelectedValues(); int[]selectedIndexCourses=courseList.getSelectedIndices();
  • 54. 【例7.22】列表框组件示例 在给定的科目中选择多门课程。 程序代码见ListExample.java。运行结果如下:
  • 55. 组合框组件 组合框将编辑框和下拉列表框结合起来,使得用户可以在一组预定义的选项中选择一个条目,而且能够修改选项内容。 新建一个有内容的组合框既可以象列表框那样指定数组,也可以采用向组合框对象里加入条目的方法。对组合框是否能够被编辑也可以进行设置。 //新建组合框。 jobsBox = new JComboBox(); jobsBox.setEditable(true); //设置组合框是否能够被编辑。 jobsBox.addItem("job1"); jobsBox.addItem("job2");
  • 56. 组合框的内容是可以动态变化的: addItem方法能够把条目添加到列表的末尾; insertItermAt方法将把新条目添加到列表的任何位置; removeItem方法和removeItemAt方法将能够删除指定条目; removeAllItems方法将删除所有条目: jobsBox.insertItermAt(“job7”, 6); //在第7个位置增加“job7”条目。 jobsBox.removeItem(“job7”); //删除“job7”条目。 jobsBox.removeItemAt(5); //删除第6个条目,即“job6”。 jobsBox.removeAllItems(); //删除所有条目。
  • 57. 当选择一个条目时,组合框就产生一个事件,对事件的监听需要添加事件监听器,并实现actionPerformed方法: //增加事件监听器。 jobsBox.addActionListener(new jobsListener()); ... private class jobsListener implements ActionListener { public void actionPerformed(ActionEvent event) { ... } } 当组合框的选择事件发生时,可以通过getSelectedItem方法来获取当前被选择的条目: Object selectedJob = jobsBox.getSelectedItem();
  • 58. 【例7.23】组合框组件示例 应用组合框来进行选择职业。 程序代码见ComboBoxExample.java。运行结果如下:
  • 59. 滑块组件 滑块组件一般有一个连续区间和可拖动的滑块,用户可以通过拖动滑块在一个区间范围里进行选择。 JSlider ageSlider = new JSlider(); ageSlider = new JSlider(SwingConstants.VERTICAL,0,120,20); 当滑块被拖动时,滑块的值将发生变化,触发ChangeEvent事件。滑块组件的事件监听器要实现ChangeListener接口,并实现此接口中的stateChanged方法: AgeListener myAgeListener = new AgeListener(); ageSlider.addChangeListener(myAgeListener); private class AgeListener implements ChangeListener { public void stateChanged(ChangeEvent event) { ... } } 滑块值发生变化时,使用getValue方法来获得滑块值: myTextField.setText("" + sourceSlider.getValue());
  • 60. 【例7.24】滑块组件示例 在进行年龄输入时,使用滑块进行直观的选择。 程序代码见SliderExample.java。运行结果如下:
  • 61. 7.4.7 边界当界面中的组件比较多时,需要从视觉上将组件分隔。通用的办法是为面板设置边界,并将需要分隔的组件添加到该面板中。 可选的边界风格包括:低斜面、凸斜面、蚀刻、直线、不光滑、空。 创建边界需要调用BorderFactory的静态方法。当需要给边界增加标题以提示时,可以使用BorderFactory的createTitledBorder方法: //初始化带标题的空边界。 Border border = BorderFactory.createEmptyBorder(); Border titled = BorderFactory.createTitledBorder (border, "Border types"); 当创建好需要的边界后,就可以把边界对象添加到组件中: buttonPanel.setBorder(titled);
  • 62. 【例7.25】边界示例 各种边界的不同效果。 程序代码见BorderExample.java。运行结果如下:
  • 63. 7.4.8菜单以及弹出式菜单 典型的菜单:
  • 64. 创建菜单 四个步骤:创建菜单栏、创建菜单以及子菜单、创建菜单项,并将菜单项加入到子菜单或菜单中,将子菜单加入到菜单中,将菜单加入到菜单栏中。 //(a)创建菜单栏,并将菜单栏加入到框架中。 JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); //(b)创建“File”菜单、“Edit”菜单和“View”菜单。 JMenu fileMenu = new JMenu("File"); JMenu editMenu = new JMenu("Edit"); JMenu viewMenu = new JMenu("View"); //(b)创建子菜单。 JMenu optionMenu = new JMenu("Option");
  • 65. //(c)通过Action对象新建“New”菜单项,并添加事件监听器。 newItem = fileMenu.add(new ShowAction("New")); //(c)通过指定菜单项对象新建“Paste”菜单项。 pasteItem = new JMenuItem("Paste", 'P'); //(d)将菜单项加入到子菜单或菜单中,将子菜单加入到菜单中,将菜单加入到菜单栏中。 fileMenu.add(newItem); editMenu.add(pasteItem); viewMenu.add(optionMenu); menuBar.add(fileMenu); menuBar.add(editMenu); menuBar.add(viewMenu);
  • 66. 创建复选框和单选按钮菜单项 和创建一般的菜单项几乎一样,只需要注意一下复选框和单选按钮的不同构造函数以及单选按钮组的构建: //创建单选按钮菜单项“Forward”,并将“Forward”菜单项加入到“Search”菜单中。 ButtonGroup group = new ButtonGroup(); forwardItem = new JRadioButtonMenuItem("Forward"); group.add(forwardItem); searchMenu.add(forwardItem); //创建复选框菜单项“ToolBar”,并加入到子菜单中。 JCheckBoxMenuItem toolItem = new JCheckBoxMenuItem("ToolBar"); optionMenu.add(toolItem);
  • 67. 菜单项的使用状态 菜单项能够被选取取决于菜单项的启用和禁用状态: //初始设置“Save”菜单项为禁用状态。 saveItem.setEnabled(false); 快捷键和加速器 快捷键显示为带有下划线的字母,加速器则显示为菜单项旁边的组合键。: //设置菜单的快捷键。 fileMenu.setMnemonic('F'); //设置“Exit”菜单项的快捷键为“T”。 JMenuItem exitItem = new JMenuItem("Exit", 'T'); //设置“Exit”菜单项的加速器为“Ctrl+T”。 exitItem.setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_T, InputEvent.CTRL_MASK));
  • 68. 弹出式菜单 弹出式菜单的创建和菜单的创建基本相同,也需要新建一个弹出式菜单后再加入菜单项。 //弹出式菜单。 popup = new JPopupMenu(); //新建弹出式菜单中的“Cut”菜单项和监听器。 cutItemPop = new JMenuItem("Cut", 'C'); popup.add(cutItemPop);
  • 69. 【例7.26】菜单示例 菜单的用法。 程序代码见MenuExample.java。运行结果如下:
  • 70. 7.4.9 对话框对话框分为模式对话框和无模式对话框。 模式对话框必须在用户处理完后才允许用户与主窗口继续进行交互。无模式对话框允许用户同时在对话框和程序剩余部分中输入信息。 在Swing中,提供了四种简单的对话框: showMessageDialog:显示一条消息等待用户点击OK; showConfirmDialog:显示一条消息并等待确认; showOptionDialog:显示一条消息并等待用户在一组自定义选项中的选择; showInputDialog:显示一条消息并等待用户的输入。
  • 71. 以showConfirmDialog为例: int selection = JOptionPane.showConfirmDialog( DialogFrame.this, //父窗口 "Are you sure?", "Logout", //消息以及对话框标题 JOptionPane.OK_CANCEL_OPTION, //底部按钮类型 JOptionPane.WARNING_MESSAGE); //消息类型 底部按钮的类型和对话框有密切的关系,对于showMessageDialog和showInputDialog对话框来说,只能有一组标准按钮,分别是OK和OK/CANCEL。对于showConfirmDialog,按钮可以包括四种: DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION, OK_CANCEL__OPTION。
  • 72. 【例7.27】对话框示例 对话框的使用:当单击“退出”按钮时,将弹出对话框,同时原先的框架窗口将不能被激活,必须选择对话框中的一个选项才能够退出对话框。 程序代码见DialogExample.java。运行结果如下:
  • 73. 本章小结 通过本章的学习,我们了解了Java的基本图形绘制、事件处理模型和常用的Swing组件的用法。 在基本图形绘制中,框架的概念非常重要。我们可以设置框架的外观,输出文本,设置字体和颜色,绘制如矩形等基本图形,显示图像等。 事件是描述发生了什么的对象;事件是由事件源产生的,事件的产生者称为事件源;事件源拥有自己的方法,我们通过它向其注册事件监听器。事件监听器是一个类的实例,这个类实现了一个特殊的接口:Lintener interface。当事件源产生了一个事件以后,事件源就会发送通知给相应的事件监听器,监听器对象根据事件对象内封装的信息,决定如何响应这个事件。 Swing提供了一整套的GUI组件,包括:布局管理器、文本组件、标签、选择类组件、边界、菜单、对话框等。