1.06k likes | 1.26k Views
西南科技大学网络教育系列课程 高级语程序设计 (Java). 第十章 基于 Swing 的图形用户界面设计. Java 程序. Java AWT. 本地窗口系统 Peers. 显示. AWT 组件与 SWING 组件概述. Java 在初期借助一种窗口开发类库,叫作 AWT(Abstract Windows Toolkit ,抽象窗口工具箱 ) 来达到在图形接口上平台独立性。. AWT 处理用户界面元素的方法
E N D
西南科技大学网络教育系列课程 高级语程序设计(Java) 第十章基于Swing的图形用户界面设计
Java程序 Java AWT 本地窗口系统 Peers 显示 AWT组件与SWING组件概述 • Java在初期借助一种窗口开发类库,叫作AWT(Abstract Windows Toolkit,抽象窗口工具箱)来达到在图形接口上平台独立性。 • AWT处理用户界面元素的方法 • 把用户界面元素的创建和行为委托给目标平台(Windows、Macintosh、Linux等)上的本地GUI工具(Peers,对等组件)进行处理。 • Peers是本地GUI组件,由AWT来操控,Peers对程序开发者是隐而不见的,各平台所产生的peers与各平台有关 。
重量组件和轻量组件 • 与本地对等组件相关联的组件(AWT组件)就被称为重量组件。 • 不依赖本地对等组件的组件(Swing组件)就被称为轻量组件。 • 重量组件具有平台不一致性。 • 轻量组件在重量容器的窗口中绘制,背景可以是透明的。
AWT与Swing AWT • 粗糙、不美观 • 平台不一致,“一次编写,到处调试” • 运行效率较低,不适合复杂界面的程序 • 开发速度较快 Swing • 更丰富、更方便的用户界面元素集合 • 对底层平台的依赖更少,和平台有关的bug也就更少 • 给不同平台上的用户一致的感觉 • swing组件大部分是轻量组件,没有对等组件 • Swing并没有完全代替AWT
Component Container JComponent Window JTeatArea JButton JTable JTextField JTree JPanel Frame Dialog JDialog JFrame JComponent类的部分子类以及JFrame类和JDialog类 javax.swing包中JComponent(轻组件)类是java.awt包中Container类的一个直接子类、Componenet类的一个间接子类。javax.swing包中的JFame类和JDialog类分别是java.awt包中Frame类和Dialog类的直接子类、Window类的间接子类。
两个基本概念 • 组件(component):Java把由Component类的子类或间接子类创建的对象称为一个组件,是图形用户界面中的可见部分,如按钮、标签。 • 容器(container): Java把由Container的子类或间接子类创建的对象称为一个容器,是图形用户界面中容纳其它组件的部分,如窗体。 • 一个容器中可容纳一个或多个组件,也可容纳其他容器。
认识几个方法 • add( ):将组件添加到该容器中。 • removeAll() :移掉容器中的全部组件。 • remove(Component c)移掉容器中参数指定的组件。 • validate():每当容器添加新的组件或移掉组件时,调用该方法以保证容器中的组件能正确显示出来。
按钮状态 按钮外观 按钮观感 按钮行为 外部事件 • 组件的三要素 • 内容,如按钮的状态、文本框中的文本 • 外观显示,如组件的颜色、大小、可见性 • 行为,组建对外部刺激(事件)的反应 • 三要素之间的是相互关联的,如按钮组件
Swing的结构 • Swing采用MVC(模型 - 视图 - 控制)设计模式 • MVC的基本思想就是将一个GUI组件分成三个部分: 模型部分 — 存储内容(完整的)视图部分 — 显示内容(完整或不完整的)控制部分 — 处理用户事件 • 模型必须实现改变和发现内容的方法 • 模型是完全不可见的,显示存储在模型中的数据是视图的工作,控制决定是否把外界的事件转化成对模型或视图的改变
控制器调用模型中的“插入字符”命令 改变文本框组件的内容 按下字符键 模型通知视图进行更新 视图改变了 控制器通知视图进行滚动 改变文本框组件的外观 按下光标键 对文本不会有任何影响 模型不会有改变 • 例:用户在文本框中进行字符输入 • 例:用户在文本框中按下了光标键
每个组件都有一个包装类(如JButton),用来保存模型和视图。每个组件都有一个包装类(如JButton),用来保存模型和视图。 • 在javax.swing包中提供了超过250个类,而其中有接近50个组件类(以J打头)。 • javax.swing包中有四个最重要的类 • JApplet、JFrame、JDialog和JComponent。 • JFrame、JApplet、JDialog都是重组件 • swing包是属于Java基础类(Java Foundation Classes,JFC)的一部分。
JFrame窗体 • JFrame的特性 • JFrame类其子类创建的对象是窗体。 • JFrame类或子类创建的对象是重量容器。 • 不可以把组件直接添加到JFame窗体中,应当把组件添加到内容面板中。 • 不能为JFame窗体设置布局,应为JFame窗体的内容面板设置布局。 • JFame窗体通过调用getContentPane()方法得到它的内容面板。
JMnuBar ContentPane JFame窗体的基本结构
JFrame类常用方法: • 构造方法 • JFrame() :可以创建一个无标题的窗口。 • JFrame(String s) :创建一个标题为s的窗口。 • 常用方法 • public void setBounds(int a,int b,int width,int height) 窗口调用该方法可以设置出现在屏幕上时的初始位置是(a,b),即距屏幕左面a个像素、距屏幕上方b个像素;窗口的宽是width,高是height。
public void setSize(int width,int height):设置窗口的大小,窗口在屏幕出现是默认位置是(0,0)。 • public void setVisible(boolean b):设置窗口是可见还是不可见,窗口默认是不可见的。 • public void setResizable(boolean b):设置窗口是否可调整大小,窗口默认是可调整大小的。
public void setDefaultCloseOperation(int operation) :设置单击窗体右上角的关闭图标后,程序会做出怎样的处理。 • 其中的参数operation取下列有效值: • DO_NOTHING_ON_CLOSE:什么也不做。 • HIDE_ON_CLOSE:隐藏当前窗口。 • DISPOSE_ON_CLOSE:隐藏当前窗口,并释放窗体占有的其它资源。 • EXIT_ON_CLOSE:结束窗体所在的应用程序。
菜单组件 • Swing菜单由菜单条(JMenuBar)、菜单(JMenu)和菜单项(JMenuItem)构成。 • 菜单条是所有菜单和菜单项的根(容器)。 • JMenuBar菜单条 • JMenuBar是JComponent类的子类,负责创建菜单条。 • JMenuBar menuBar=new JMenuBar(); • 将菜单条放置到JFrame窗口中: • public void setJMenuBar(JMenuBar menubar); • 需要注意的是,只能向窗口添加一个菜单条
JMenu菜单 • JMenu是JComponent类的间接子类,负责创建菜单。 • pulbic JMenu():建立一个没有标题的菜单。 • pulbic JMenu(String s):建立一个指定标题菜单,标题由参数s确定。 • 例如: 创建一个名为“Edit”的菜单,并添加到菜单条中。 • JMenu editMenu=new JMenu(“Edit”); • menuBar.add(editMenu);
常用方法 • public void add(MenuItem item):向菜单增加由参数item指定的菜单选项对象。 • public void add(String s):向菜单增加指定的选项。 • public JMenuItem getItem(int n):得到指定索引处的菜单选项。 • public int getItemCount():得到菜单选项数目。
JMenuItem菜单项 • JMenu是JComponent类的间接子类,负责创建菜单项。 • public JMenuItem(String s):构造有标题的菜单项。 • public JMenuItem(String text, Icon icon):构造有标题和图标的菜单项。 • 创建图标对象 Icon icon=new ImageIcon(“图标文件名”); • 菜单项将被放在菜单里。例如:JMenuItem pasteItem=new JMenuItem(“Paste”);editMenu.add(pasteItem);
主要方法 • public void setEnabled(boolean b):设置当前菜单项是否可被选择 • public String getLabel():得到菜单选项的名字。 • public void setAccelerator(KeyStroke keystroke):为菜单项设置快捷键。 • public static KeyStroke getKeyStroke(int keyCode, int modifiers) :返回KeyStroke对象。 keyCode取值范围: KeyEvent.VK_A~ KeyEvent.VK_Z modifiers取值:InputEvent.ALT_MASKInputEvent .CTRL_MASKInputEvent .SHIFT_MASK
嵌入JMenu子菜单 • 菜单项本身还可以是一个菜单,称这样的菜单项为子菜单。 JMenu editMenu = new JMenu(“Edit”); JMenu optionsMenu = new JMenu(“Options”); editMenu.add(optionsMenu);
布局设计 • 作用 • 指定各个视图组件在窗口中的分布位置,实现动态布局。 • 有助于创建复合式的复杂界面,一个复合式界面由一些简单的基本界面组成。 • 优点 • 可重用性:基本界面可以被重用,组合成各种不同的复合式界面。 • 可扩展性:可以方便的扩展基本界面,从而创建更复杂的界面。 • 可维护性: 当复合式界面中的局部区域发生变化时,不会影响其它区域 。
使用布局管理器来实现布局设计 • 布局管理器是基于AWT的 • 布局管理器的类型 • 流布局管理器:FlowLayout • 边界布局管理器:BoderLayout • 卡片式布局管理器:CardLayout • 网格布局管理器:GridLayout • 盒式布局管理器:BoxLayout • 布局管理让容器使用方法setLayout(布局对象)来设计自己的布局。
BorderLayout • Window型容器的默认布局,比如Jframe类、JDialog类。 • 每个被BorderLayout管理的容器均被划分为五个区域:东(EAST) ,南(SOUTH),西(WEST),北(NORTH),中(CENTER)。 • 容器的每个区域,只能加入一个组件,如果试图加入多个组件,其中只有一个组件是可见的。 • 对于东南西北这四个边界区域,如果,其中的某个区域没有用,它的大小将变为0,CENTER区域将扩展并占用该区域
构造方法 • BorderLayout():构造一个间距为0的BorderLayout实例 • BorderLayout(int hgap,int vgap):构造一个指定间距的BorderLayout实例 • 在BorderLayout布局管理器的管理下,组建必须通过add()方法加入到容器的五个命名区域之一,否则它们是不可见的。 • 方法:add(组件,区域)
import java.awt.*; import javax.swing.*; public class BorderL{ public static void main(String[ ] args){ JFrame f; JButton be,bw,bn,bs,bc; BorderL that=new BorderL(); f=new JFrame(“窗体"); be=new JButton(“东”); bs=new JButton(“南"); bw=new JButton(“西”); bn=new JButton(“北"); bc=new JButton(“中心"); f.getContentPane().add(be,"East"); f.getContentPane().add(bs,"South"); f.getContentPane().add(bw,"West"); f.getContentPane().add(bn,"North"); f.getContentPane().add(bc,"Center"); f.setSize(350,200); f.setVisible(true); }}
FlowLayout • 将组件按照加入的顺序逐个地放在容器中的一行上,一行放满后再另起一个新行。 • 每一行中的组件按布局指定的方式对齐方,默认情况下是居中对齐。 • 三种构造方法: • FlowLayout() • FlowLayout(int align) • FlowLayout(int align,int hgap,int vgap) FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER(默认) hgap:垂直间距,vgap:水平间距,默认值是5个像素
FlowLayout布局管理器不强行设定组件的大小,而是允许组件拥有自己希望的大小。FlowLayout布局管理器不强行设定组件的大小,而是允许组件拥有自己希望的大小。 • 每个组件都有一个getPreferredSize()方法,容器布局管理器会调用此方法取得每个组件希望的大小。 • FlowLayout布局是JPanle容器的默认布局管理器。
当容器中组件数增加时,就显得高低参差不齐,采用容器嵌套的方式,即把一个容器当作一个组件加入另一个容器,使这个容器的布局达到应用的需求当容器中组件数增加时,就显得高低参差不齐,采用容器嵌套的方式,即把一个容器当作一个组件加入另一个容器,使这个容器的布局达到应用的需求
GridLayout • 网格式的布局管理器,它将容器空间划分成若干行乘若干列的网格,每个格放一个组件。 • 各组件按照从上到下,从左至右的顺序排列。 • 构造方法: • GridLayout():创建一个只有一行的网格,列数根据实际需要而定 • GridLayout(int rows,int cols):创建指定行、列的网格,rows和cols中的一个值可以为0 • GridLayout(int rows,int cols,int hgap,int vgap)
使用GridLayout布局设计的一般步骤: • 使用GridLayout的构造方法创建布局对象,指定划分网格的行数和列数 • 使用GridLayout布局容器调用方发add将组件加入容器。 • GridLayout布局中每个网格都是相同大小并且强制组件与网格相同大小
CardLayout • 卡式布局管理器,可以容纳多个组件,但是同一时刻容器只能从这些组件中选出一个来显示,被显示的组件占据容器的整个空间。 • 选项卡窗格(JTabbedPane)的默认布局是CardLayout。 • 在JTabbedPane中加入组件: • add(String text,Component c); • 指定和该组件c对应的选项卡的文本提示是text。
BoxLayout • 用BoxLayout类可以创建盒式布局。 • Box类创建的容器称作一个盒式容器,盒式容器的的默认布局是盒式布局,而且不允许更改盒式容器的布局。 • 行型盒式布局 • 容器中组件的上沿在同一水平线上。 • Box类的类方法createHorizontalBox()可以获得一个具有行型盒式布局的盒式容器 • 行型盒式容器中组件间的间距:Box类调用静态方法createHorizontalStrut(int width)可以得到一个不可见的水平Struct类型对象,称做水平支撑。
列型盒式布局 • 容器中组件的左沿在同一垂直线上。 • Box类的类方法createVerticalBox()可以获得一个具有列型盒式布局的盒式容器。 • 列型盒式容器中组件间的间距:Box类调用静态方法createVertialStrut(int height)可以得到一个不可见的垂直Struct类型对象,称做垂直支撑。
中间容器 • 用来添加组件的轻容器,称为中间容器。 • JPanel面板 • JPanel类用来创建一个面板对象,可以向这个面板添加组件(直接使用add方法)。 • 使用时需要把这个面板添加到底层容器或其他中间容器中。 • JPanel面板的默认布局是FlowLayout布局。 • 构造方法 • JPanel():构造一个面板容器对象
JScrollPane滚动窗格 • 把一个组件放到一个滚动窗格中,然后通过滚动条来观察这个组件。 • 例如,JTextArea不自带滚动条,可把文本区放到一个滚动窗格中。 • 构造方法 JScrollPane(component c):构造一个滚动窗格。
JSplitPane拆分窗格 • 被分成两部分的容器,拆分窗格有两种类型: • 水平拆分:用一条拆分线把容器分成左右两部分,左面放一个组件,右面放一个组件,拆分线可以水平移动 • 垂直拆分:用一条拆分线分成上下两部分,上面放一个组件,下面放一个组件,拆分线可以垂直移动。 • 构造方法 • JSplitPane(int a, Component b ,Component c): 构造一个拆分窗格 • setDividerLocation(double position):拆分窗格设置拆分线的位置。
JLayeredPane分层窗格 • 如果添加到容器中的组件经常需要处理重叠问题,就可以将组件添加到JLayeredPane容器。 • JLayeredPane将容器分成5个层,容器使用 add(Jcomponent com, int layer); 添加组件com,并指定com所在的层。 • layer取值: DEFAULT_LAYER:最底层 PALETTE_LAYER MODAL_LAYER POPUP_LAYER DRAG_LAYER:最上面的层
public void setLayer(Component c,int layer):重新设置组件c所在的层 • public int getLayer(Component c):获取组件c所在的层数。
文件组件 • JTextField文本框 • 用来建立文本框的,用户可以在文本框输入单行的文本。 • 构造方法 • JTextField(int x):创建文本框对象,可以在文本框中输入若干个字符,文本框的可见字符个数由参数x指定。 • JTextField(String s) :创建文本框对象,则文本框的初始字符串为s,可以在文本框中输入若干个字符。
主要方法 • public void setText(String s):设置文本框中的文本为参数s指定的文本。 • public String getText() :获取文本框中的文本。 • public void setEditable(boolean b) :指定文本框的可编辑性(默认为可编辑的)。 • public void setHorizontalAlignment(int alignment) :设文本在文本框中的对齐方式,其中alignment的有效值确定对齐方式,如:LEFT、CENTER、RIGHT。
JPasswordField • 建立一个密码框对象 • setEchoChar(char c):设置回显字符(默认的回显字符是‘*’)。 • char[ ] getPassword()方法获取密码框中的密码。
ActionEvent事件 • 基于委托的事件模型 • 事件的处理由事件的来源(source,对象) ,委托给一个或多个事件监听者(Event Listener)来处理(事件监听者就可视为一种处理事件的对象)。 • 组件激发事件,事件监听器监听并处理这一特定事件。 • 委托的方法是调用组件的注册监听器方法addxxxListener(Event Listener)
事件监听者 • 是一种处理事件的接口,定义于java.awt.event包中,在此包中也定义了各种事件类 • 当事件来源对象因用户的操作(鼠标、键盘等),系统会自动触发此事件类对象E,并通知所委托的事件监听者A(需要预先注册),然后事件监听者A中所定义的处理各种事件的方法便会处理此事件E的各种状况 。
事件监听者A 用户操作 事件处理者1 事件E 事件处理者2 产生 来源对象 事件处理者n 向事件监听者A注册
通知 发生XXX事件 事件源.addXXXListener(存放监视器引用的接口) 接口回调 实现XXXListener接口的监视器 接口方法(XXX e) 事件处理示意图
事件结构 • 所有的事件动作都开始于java.util包中的EventObject类,以及EventListener接口,它们构成了委托事件模型的基础。 • 在java.awt.event包中定义了各类事件类、事件监听接口、以及事件转接器(Adapter)。
ActionEvent事件的处理 • 注册监听器 • addActionListener(ActioListener listener); • 对事件的处理:实现ActionListener接口 • public voidactionPerformed(ActionEvent e) class MyListener extends ActionListener{ …….Mylistener listener = new Mylistener(); 组件对象.addActionListener(listener);……. public void actionPerformed(ActionEvent e){ // 实现方法体} }
以内部类方式实现 • 组件对象.addActionListener( new ActionListener(){ ……. public void actionPerformed(ActionEvent e){ // 实现方法体}); …… • public Object getSource():返回发生ActionEvent事件的对象的引用。