770 likes | 930 Views
面向对象的程序设计- Java. 第六章 GUI 设计和事件处理. 6.1 概述 6.2 GUI 设计 6.3 Java 的事件处理模型 6.4 常见事件处理 6.5 响应用户输入 6.6 小结. 输入. 事件. 事件处理. 用户. 输出. 处理. 6.1 概述. 一、与用户的交互. 6.1 概述. 二、 GUI 的元素: Top-Level Containers. 6.1 概述. 二、 GUI 的元素: General-Purpose Containers. 6.1 概述.
E N D
第六章 GUI设计和事件处理 6.1 概述 6.2 GUI设计 6.3 Java的事件处理模型 6.4 常见事件处理 6.5 响应用户输入 6.6 小结
输入 事件 事件处理 用户 输出 处理 6.1 概述 一、与用户的交互
6.1 概述 二、GUI的元素:Top-Level Containers
6.1 概述 二、GUI的元素:General-Purpose Containers
6.1 概述 二、GUI的元素:Special-Purpose Containers
6.1 概述 二、GUI的元素:Basic Controls
6.1 概述 二、GUI的元素:Uneditable Information Displays
6.1 概述 二、GUI的元素:Editable Displays of Formatted Information
事件是代表另一对象抽象状态下变化的对象。事件本身就是抽象。生成事件的过程是无法从对象外部直接观察的。事件是代表另一对象抽象状态下变化的对象。事件本身就是抽象。生成事件的过程是无法从对象外部直接观察的。 6.1 概述 本地事件是使用单一Java虚拟且运行于单一平台上的应用程序生成的事件。 分布事件就是由远程目标生成的事件,运行于不同的平台使用不同的JVM。 三、什么是事件?
java.awt • java.awt.event • javax.swing(JFC1.1) • javax.swing.event 6.1 什么是事件 四、与GUI和事件处理有关的包 • 推荐使用swing组件
容器 组件 容器 组件 组件 组件 组件 组件 6.2 GUI设计 一、容器与组件
6.2 GUI设计 容器是可以放置其他组件的组件,主要有 Panel、Frame和Window 容器是java.awt.Container的子类。 Swing组件都是抽象类 java.awt.Container.Jcomponent的子类。
Container JComponent JWindow Window Frame JFrame Dialog JDialog Panel …… FileDialog …… 6.2 GUI设计 二、Swing组件的类结构
6.2 GUI设计 AbstractButton, BasicInternalFrameTitlePane, Box, Box.Filler, JColorChooser, JComboBox, JFileChooser, JInternalFrame, JInternalFrame.JDesktopIcon, JLabel, JLayeredPane, JList, JMenuBar, JOptionPane, JPanel, JPopupMenu, JProgressBar, JRootPane, JScrollBar, JScrollPane, JSeparator, JSlider, JSpinner, JSplitPane, JTabbedPane, JTable, JTableHeader, JTextComponent, JToolBar, JToolTip, JTree, JViewport JComponent的直接子类(JDK1.4)
要创建Swing应用程序,首先要创建一个表示图形用户界面的类,这个类的对象将被用作容器,用于放置要显示的其他组件。要创建Swing应用程序,首先要创建一个表示图形用户界面的类,这个类的对象将被用作容器,用于放置要显示的其他组件。 • 大部分应用程序的主界面是一个简单窗口(Jwindow)或是一个框架窗口(JFrame)。 6.2 GUI设计 三、创建主界面
import javax.swing.*; public class HelloWorldSwing { public static void main(String[] args) { JFrame frame = new JFrame("HelloWorldSwing"); final JLabel label = new JLabel("Hello World"); frame.getContentPane().add(label); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); }} 6.2 GUI设计 一个最简单的Swing应用程序
创建组件其实就是生成一个满足外观要求的某个某个组件对象。创建组件其实就是生成一个满足外观要求的某个某个组件对象。 JLabel label = new JLabel("Hello World"); JButton okButton=new JButton(“Ok"); • 将组件加入到简单容器(JPanel)中,只要调用容器的add(Component)方法,参数是该组件。 • 对于大多数其他容器(框架、窗口、JApplet和对话框)则采用其他方法。 6.2 GUI设计 四、创建并添加组件
6.2 GUI设计 这些非简单容器实际上被划分为窗格(Pane),后者是一种容器中的容器。通常情况下组件被加入容器的内容窗格(ContentPane)中。 组件加入容器的内容窗格的步骤是: 1)创建一个面板。 2)使用面板的add(Component)方法将组件加入到面板中。 3)调用setContentPane(Container)方法,将面板作为参数,将面板加入到内容窗格中。
Java通过布局管理器来排列组件。 6.2 GUI设计 五、布局管理
6.2 GUI设计 布局管理器决定了组件被加入到容器中时被如何排列。 Java中布局管理器包括FlowLayout、GridLayout、BorderLayout、CardLayout和GridBagLayout类。 在将组件加入到容器之前,必须建立容器的布局管理器。 FlowLayout flo=new FlowLayout(); 面板的缺省输出管理器是FlowLayout;框架和窗口的是BorderLayout。 创建完布局管理器后,需要用容器的setLayout()方法将它与容器关联。
组件按照加入的先后顺序从从左到右排列,一行排满之后转到下一行继续从左到右排列。组件按照加入的先后顺序从从左到右排列,一行排满之后转到下一行继续从左到右排列。 • 要想让每一行中的组件向左、向右和居中排列,需要在构造时加参数:FlowLayout.LEFT、FlowLayout.RIGHT和 FlowLayout.CENTER。居中是其缺省排列。 • 构造函数FlowLayout(int, int, int)有三个参数分别表示对齐方式、组件水平间距和组件垂直间距。 6.2 GUI设计 1、FlowLayout
组件按照加入的先后顺序从从左到右依次填满单元格,一行排满之后转到下一行继续。组件按照加入的先后顺序从从左到右依次填满单元格,一行排满之后转到下一行继续。 • 构造函数有四个参数: GridLayout glo = new GridLayout(3,2,0,0) 分别是行单元格数、列单元格数、单元水平间距和单元垂直间距。 6.2 GUI设计 2、GridLayout
容器分成北、南、东、西和中央五个区。 • 在加入组件时,需要指明加入到哪个区中。 add("West", new Button ("西")); add("Center",new Button("中")); 6.2 GUI设计 3、BorderLayout
GridBagLayout是功能最为强大的布局管理器。 • 它与GridLayout的区别在于: 组件可以占据网格中多个单元格; 不同行和列的比例不必相等; 单元格中的组件可以以不同的方式排列。 6.2 GUI设计 4、GridBagLayout
事件监听器 事件源 委托(注册) • Swing界面要成为Java程序,必须能够处理用户事件。 • Swing用一组称之为事件监听器(Event Listener)来处理事件。 • 如果没有委托(注册)监听器,事件将不被处理。 6.3 Java的事件处理模型 一、Java事件处理的委托模型
ActionListener:行为事件 • AdjustmentListener:调整事件 • FocusListener:焦点事件 • KeyListener:键盘事件 • ItemListener:选项事件 • MouseListener:鼠标事件 • MouseMotionListener:鼠标移动事件 • WindowListener:窗口事件 6.3 Java的事件处理模型 二、Java中,事件监听器是实现了相应接口的类。
addActionListener:JButton,JCheckBox,JCombobox,JTextfield和JRadioButtonaddActionListener:JButton,JCheckBox,JCombobox,JTextfield和JRadioButton • addAdjustmentListener:JScrollBar • addFocusListener:所有的Swing组件 • addKeyListener:所有的Swing组件 • addItemListener:JCheckBox,JCombobox和JRadioButton • addMouseListener:所有的Swing组件 • addMouseMotionListener:所有的Swing组件 • addWindowListener:所有的JWindow和JFrame组件 6.3 Java的事件处理模型 三、委托(注册)事件监听器
6.3 Java的事件处理模型 注意:将组件加入到容器之前,必须将监听器与组件关联起来,并完成相应其他配置工作,否则,程序运行时,这些设置将被忽略。
实现监听器接口的类必须处理接口中所有的方法。实现监听器接口的类必须处理接口中所有的方法。 ActionListener : actionPerformed(ActionEvent) KeyListener: keyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent) MouseListener: mouseClicked(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) • 为了方便,Java提供了相应接口的适配器(Adapter)。 6.3 Java的事件处理模型 四、事件处理方法
1)新建一个组件(如JButton)。 2)将该组件添加到相应的面板(如JPanel)。 3)注册监听器以监听事件源产生的事件(如通过ActionListener来响应用户点击按钮)。 4)定义处理事件的方法(如在ActionListener中的actionPerformed中定义相应方法)。 6.3 Java的事件处理模型 五、Swing中处理各组件事件的一般步骤
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Simple1 { private static JFrame frame; // 定义为静态变量以便main使用 private static JPanel myPanel; // 该面板用来放置按钮组件 private JButton button1; // 这里定义按钮组件 private JButton button2; // 以便让ActionListener使用 6.3 Java的事件处理模型 六、例
6.3 Java的事件处理模型 public Simple1() { // 构造器, 建立图形界面 myPanel = new JPanel(); // 新建面板 button1 = new JButton("按钮1"); // 新建按钮1 button2 = new JButton("按钮2"); // 新建按钮1 SimpleListener ourListener = new SimpleListener(); // 建立一个actionlistener让两个按钮共享 button1.addActionListener(ourListener); button2.addActionListener(ourListener); myPanel.add(button1); // 添加按钮到面板 myPanel.add(button2); }
6.3 Java的事件处理模型 private class SimpleListener implements ActionListener { public void actionPerformed(ActionEvent e){ // 利用getActionCommand获得按钮名称 // 也可以利用getSource()来实现 // if (e.getSource() ==button1) String buttonName = e.getActionCommand(); if (buttonName.equals("按钮1")) JOptionPane.showMessageDialog(frame, "按钮1 被点击"); else if (buttonName.equals("按钮2")) JOptionPane.showMessageDialog(frame, "按钮2 被点击"); else JOptionPane.showMessageDialog(frame, "Unknown event" ); } }
6.3 Java的事件处理模型 public static void main(String s[]){ Simple1 gui = new Simple1(); // 新建Simple1组件 frame = new JFrame("Simple1"); // 新建JFrame // 处理关闭事件的通常方法 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); frame.getContentPane().add(myPanel); frame.pack(); frame.setVisible(true); } }
6.3 Java的事件处理模型 程序运行结果:
接口:ActionListener • 注册:addActionListener(ActionListener) • 处理:actionPerformed(ActionEvent evt) • 判断事件源:getSource()和getActionCommand() • 判断是否同时按下其他键:getModifiers() • 动作命令(action command)是与按钮、菜单等相关联的文本,如它们的标签。通过组件的setActionCommand(String)方法,可以设置不同的动作命令。多用于多个组件可激发同样事件时。 6.4 常见事件处理 一、行为事件
依赖平台和键盘布局 • 接口:KeyListener • 注册:add KeyListener(KeyListener) • 处理:keyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent) 6.4 常见事件处理 二、键盘事件 仅响应Unicode字符键 • 判断按下Unicode字符:键盘事件的getKeyChar()方法 • 判断按下虚拟键码:键盘事件的getKeyCode()方法 • 修改输入键码:setKeyChar(char)与setKeyCode(int)
6.4 常见事件处理 import javax.swing.*; import java.awt.event.*; import java.awt.*; public class KeyEventDemo extends JApplet implements KeyListener, ActionListener { JTextArea displayArea; JTextField typingArea; static final String newline = "\n"; public void init() { JButton button = new JButton("Clear"); button.addActionListener(this); typingArea = new JTextField(20); typingArea.addKeyListener(this);
6.4 常见事件处理 displayArea = new JTextArea(); displayArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(displayArea); scrollPane.setPreferredSize(new Dimension(375, 125)); JPanel contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); contentPane.add(typingArea, BorderLayout.NORTH); contentPane.add(scrollPane, BorderLayout.CENTER); contentPane.add(button, BorderLayout.SOUTH); setContentPane(contentPane); }
6.4 常见事件处理 /** Handle the key typed event from the text field. */ public void keyTyped(KeyEvent e) { displayInfo(e, "KEY TYPED: "); } /** Handle the key pressed event from the text field. */ public void keyPressed(KeyEvent e) { displayInfo(e, "KEY PRESSED: "); } /** Handle the key released event from the text field. */ public void keyReleased(KeyEvent e) { displayInfo(e, "KEY RELEASED: "); }
6.4 常见事件处理 /** Handle the button click. */ public void actionPerformed(ActionEvent e) { //Clear the text components. displayArea.setText(""); typingArea.setText(""); //Return the focus to the typing area. typingArea.requestFocus(); }
6.4 常见事件处理 protected void displayInfo(KeyEvent e, String s){ String charString, keyCodeString, modString, tmpString; char c = e.getKeyChar(); int keyCode = e.getKeyCode(); int modifiers = e.getModifiers(); if (Character.isISOControl(c)) { charString = "key character = " + "(an unprintable control character)"; } else { charString = "key character = ’" + c + "’"; } keyCodeString = "key code = " + keyCode + " (" + KeyEvent.getKeyText(keyCode) + ")";
6.4 常见事件处理 modString = "modifiers = " + modifiers; tmpString = KeyEvent.getKeyModifiersText(modifiers); if (tmpString.length() > 0) { modString += " (" + tmpString + ")"; } else { modString += " (no modifiers)"; } displayArea.append(s + newline + " " + charString + newline + " " + keyCodeString + newline + " " + modString + newline); } }
6.4 常见事件处理 程序运行结果:
接口:MouseListener • 注册:addMouseListener(MouseListener) • 处理:mouseClicked(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) 6.4 常见事件处理 三、鼠标事件
6.4 常见事件处理 鼠标事件的主要方法: getClickCount(),getPoint(),getX(),getY() 判断是否按下其他键: boolean isAltDown()boolean isControlDown()boolean isMetaDown()boolean isShiftDown() getModifiersEx()-jdk1.4 String getMouseModifiersText(int modifiers)
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class PasswordDemo { public static void main(String[] argv) { final JFrame f = new JFrame("PasswordDemo"); JLabel label = new JLabel("Enter the password: "); JPasswordField passwordField = new JPasswordField(10); passwordField.setEchoChar('#'); 6.5 响应用户输入 例1:
6.5 响应用户输入 passwordField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JPasswordField input = (JPasswordField)e.getSource(); char[] password = input.getPassword(); if (isPasswordCorrect(password)) { JOptionPane.showMessageDialog(f, "Success! You typed the right password."); } else { JOptionPane.showMessageDialog(f, "Invalid password. Try again.", "Error Message", JOptionPane.ERROR_MESSAGE); } } });
6.5 响应用户输入 JPanel contentPane = new JPanel(new BorderLayout()); contentPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); contentPane.add(label, BorderLayout.WEST); contentPane.add(passwordField, BorderLayout.CENTER); f.setContentPane(contentPane); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.pack(); f.setVisible(true); }