Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Programming in Java More about GUI 蔡文能 交通大學資訊工程學系 [email protected] http://www.csie.nctu.edu.tw/~tsaiwn/java/ 交通大學資訊工程學系 Java More-GUI Agenda GUI (Graphical User Interface) AWT Component (package java.awt ) Graphics and Events Event Model Listener interfaces and Adaptors Events and Listeners for standard AWT events Layout Manager? Swing Library 交通大學資訊工程學系 蔡文能 5-第2頁 Java More-GUI Java UI functionality Presenting a Graphical User Interface (GUI) Playing sounds Applications can play sounds as well as Applets since JDK1.2. Getting configuration information Users can specify configuration information to a program using commandline arguments (applications only) and parameters (applets only). Saving user preferences using properties For information that applications need to save even when they're not running, you can use properties. (not for Applets due to security problem.) Getting/displaying text using the standard input/output/error streams Standard input, output, and error are the old-fashioned way of presenting a user interface. They're still useful for testing and debugging programs. 交通大學資訊工程學系 蔡文能 5-第3頁 Java 交通大學資訊工程學系 蔡文能 http://java.sun.com/j2se/1.4.1/docs/api/ More-GUI 5-第4頁 Java More-GUI The AWT Components 交通大學資訊工程學系 蔡文能 5-第5頁 Java More-GUI Example using AWT Component 以下為 Java 的AWT 提供的Graphical UI (GUI) components ( 圖型元件). 交通大學資訊工程學系 蔡文能 5-第6頁 Java More-GUI JFC/Swing The Java Foundation Classes (JFC) API extends the original Abstract Window Toolkit (AWT) by adding a comprehensive set of graphical user interface class libraries. JFC/Swing components include: Pluggable Look and Feel Accessibility API Java 2DTM API (Java 2 only) Drag and Drop (Java 2 only) AWT Internationalization 交通大學資訊工程學系 蔡文能 5-第7頁 Java More-GUI Swing Library 交通大學資訊工程學系 蔡文能 5-第8頁 Java More-GUI Class javax.swing.JComponent java.lang.Object | +--java.awt.Component | +--java.awt.Container | +--javax.swing.JComponent 交通大學資訊工程學系 蔡文能 5-第9頁 Java JDK 1.0 8 packages 212 classes JDK 1.1 JDK 1.2 JDK 1.3 JDK 1.4 23 packages 504 classes 59 packages 1520 classes 77 packages 1595 classes 103 packages 2175 classes New Events JFC/Swing Inner class Object Serialization Jar Files Drag and Drop JNDI Java Sound Timer Java2D JDBC Regular Exp Logging Assertions NIO 131 packages 2656 classes javax.activity, javax.management java.nio, javax.imageio, javax.net, javax.print, javax.security, org.w3c CORBA International Reflection More-GUI JDK 1.5 javax.naming, javax.sound, javax.transaction RMI javax.accessibility, javax.swing, org.omg java.math, java.rmi, java.security, java.sql, java.text, java.beans 交通大學資訊工程學系 蔡文能 java.applet, java.awt, java.io, java.lang, java.net, java.util 5-第10頁 Java More-GUI What is MFC? (Microsoft Foundation Classes) C++ API for Microsoft Windows programming. Object-oriented framework over Win32. Provides a set of classes allowing an easy application creation process. It encapsulates most part of the Windows API. 交通大學資訊工程學系 蔡文能 5-第11頁 Java More-GUI MFC vs. JFC/Swing Java Foundation Classes (Swing) are a set of Java class libraries provided as part of the Java Platform to support building graphics user interface (GUI) and graphics functionality for client applications that will run on popular platforms such as Microsoft Windows, Linux, and Mac OSX. JFC is needed when multiplatform compatibility is wanted. Under Windows, MFC works better than JFC 交通大學資訊工程學系 蔡文能 5-第12頁 Java More-GUI Other Ways of Getting User Input Sliders, Scrollbars, and Text Areas The Scrollbar class is used for both slider and scrollbar functionality. The TextArea class simply provides an area to display or allow editing of several lines of text. Text areas automatically include scrollbars. 交通大學資訊工程學系 蔡文能 5-第13頁 Java More-GUI The Basic Controls and events 基本控制元件: Buttons, Checkboxes, Choices, Lists, Menus, and Text Fields When a user activates one of these controls, it posts an event. An object that contains the control can react to the event by implementing the action() method. (AWT1.0舊的 event處理 方式) Clicking a button. Pressing Return in a text field. 新的處理方式: (AWT1.1 event model) 該元件要先 addActionListener( 有處理能力的物件 ) 或向其他 Listener 註冊 (參看後面 slides) 交通大學資訊工程學系 蔡文能 5-第14頁 Java More-GUI Event driven (事件驅動) Event (事件) 使用者執行視窗程式時對視窗元件的動作,例如按一下按鈕 或鍵盤。 Event Handler (事件處理程式) 程式執行中若發生事件,可以由指定的事件處理程式進行處理。 Delegation Event Model (委託式的事件處理模型) Java AWT1.1的事件處理模型, 包括: 事件來源(Event Source) – 發出事件物件的來源, 如視窗元件的按 鈕。 監聽者物件(Listener) – 被委託處理指定事件的物件。 動作 事件 事件來源 交通大學資訊工程學系 蔡文能 監聽者物件 5-第15頁 Java More-GUI MVC design pattern Overview Model-View-Controller architecture decouples 3 aspects of a user-interface Model: the data being displayed View: how the data is displayed Controller: how the user interacts with the displayed data JFC/Swing variant of MVC: separable model architecture. Provides benefits of complete MV separation. Easier to use because it bundles view and controller together. 交通大學資訊工程學系 蔡文能 5-第16頁 Java More-GUI More AWT Components Creating Custom Components: Canvases The Canvas class lets you write custom Components. With your Canvas subclass, you can draw custom graphics to the screen. Labels A Label simply displays an unselectable line of text. Containers: Windows, Panels, and Scroll Panes The AWT provides three types of containers, all are subclasses of the Container class (which is a Component subclass). The Window subclasses -- Dialog, FileDialog, and Frame -- provide windows to contain components. A Panel groups components within an area of an existing window. A ScrollPane display a potentially large component in a limited amount of space, using scrollbars to control which part of the component is displayed. 交通大學資訊工程學系 蔡文能 5-第17頁 Java More-GUI Windows (1/2) Includes Dialog, FileDialog, and Frame. Frames (框窗) create normal, full-fledged windows. Dialogs(對話窗) create windows which depends on Frames and can be modal. Example: The FileDialog(檔案對話盒) window for files: 交通大學資訊工程學系 蔡文能 5-第18頁 Java More-GUI Windows (2/2) Dialog is a Window 交通大學資訊工程學系 蔡文能 Frame is a Window javax.swing.JFrame 5-第19頁 Java More-GUI Applet is a Panel 交通大學資訊工程學系 蔡文能 5-第20頁 Java More-GUI ScrollPane is NOT a Panel 交通大學資訊工程學系 蔡文能 5-第21頁 Java More-GUI ScrollPane Example The JDK 1.1 AWT introduced the ScrollPane class, which makes it easy for you to provide a scrolling area. The following picture shows an applet in which both the vertical and horizontal scrollbars are needed. 交通大學資訊工程學系 蔡文能 5-第22頁 Java More-GUI How to Use ScrollPane Creates a scroll pane and puts a child component in it: ScrollPane sp1 = new ScrollPane(); sp1.add(anotherComponent); You can also specify the scrollbar display policy in the ScrollPane: ScrollPane sp2 = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); SCROLLBARS_AS_NEEDED The default value. Show each scrollbar only when it's needed. SCROLLBARS_ALWAYS Other Constants Always show scrollbars. SCROLLBARS_NEVER Never show scrollbars. You might use this option if you don't want the user to directly control what part of the child component is shown. 交通大學資訊工程學系 蔡文能 5-第23頁 Java More-GUI Components to be put into a ScrollPane When implement a component to be put in a ScrollPane: Need to implement the child component's getPreferredSize method so that it returns the dimensions needed to fully display the component. Implement the child component so that it works well when its drawing area is larger than its preferred size. The component might draw itself in the center of its drawing area, filling the extra space with a solid color. When the component is being scrolled, you might notice flashing, or flickering, in the display area. 交通大學資訊工程學系 蔡文能 5-第24頁 Java More-GUI Scrolling-related code from the previous applet: //The component that will be scrolled. class ScrollableCanvas extends Canvas { ... Dimension preferredSize = new Dimension(600, 320); Dimension minimumSize = new Dimension(10, 10); public Dimension getMinimumSize() { return minimumSize; } public Dimension getPreferredSize() { return preferredSize; } public void paint(Graphics g) { g.drawImage(image, 0, 0, getBackground(), this); } } 交通大學資訊工程學系 蔡文能 5-第25頁 Java More-GUI Other AWT Classes The java.awt package supplies several classes to represent sizes and shapes. Dimension : specifies the size of a rectangular area. Insets : specify how much padding should exist between the outside edges of a container and the container's display area. Shape : include Point, Rectangle, and Polygon. The Color class is useful for representing and manipulating colors. The Image class provides a way to represent image data. Applets can get Image objects for GIF and JPEG images using the Applet getImage() methods. … 交通大學資訊工程學系 蔡文能 5-第26頁 Java More-GUI Graphics and Events The Graphics and Event classes are crucial to the AWT drawing and event handling system. A Graphics object (圖形元件)represents a drawing context -without a Graphics object, no program can draw to the screen. An Event (事件)object represents a user action, such as a mouse click. 交通大學資訊工程學系 蔡文能 5-第27頁 Java More-GUI Example: 英制公制轉換 (1/3) http://java.sun.com/docs/books/tutorial/uiswing/components /example-1dot4/Converter.java File lists: /* * A 1.4 application that requires the following files: * ConversionPanel.java * ConverterRangeModel.java * FollowerRangeModel.java * Unit.java */ 交通大學資訊工程學系 蔡文能 5-第28頁 Java More-GUI Example: 英制公制轉換 (2/3) 兩個主要 class: Converter ConversionPanel 交通大學資訊工程學系 蔡文能 5-第29頁 Java More-GUI Example: 英制公制轉換 (3/3) The Component Hierarchy 交通大學資訊工程學系 蔡文能 5-第30頁 Java More-GUI Drawing How Drawing Requests Occur Use the repaint( ) method to request to be scheduled for drawing. Invoke the Component's update( ) method. Call the Component's paint( ) method. (default) The Graphics Object The only argument to paint() and update() is a Graphics object. The Graphics class provides methods for the following: Drawing and filling rectangles, arcs, lines, ovals, polygons, text, and images. Getting or setting the current color, font, or clipping area. How to Draw The simplest way for a Component to draw itself is to put drawing code in its paint() method. public void paint(Graphics g) { Dimension d = size(); g.drawRect(0,0, d.width - 1, d.height - 1); } 交通大學資訊工程學系 蔡文能 5-第31頁 Java More-GUI AWT 1.0 Event Model 舊的方法 交通大學資訊工程學系 蔡文能 5-第32頁 Java More-GUI Default Methods for Each Component 舊的方法 action() (Event.ACTION_EVENT) mouseEnter() (Event.MOUSE_ENTER) mouseExit() (Event.MOUSE_EXIT) mouseMove() (Event.MOUSE_MOVE) mouseDown() (Event.MOUSE_DOWN) mouseDrag() (Event.MOUSE_DRAG) mouseUp() (Event.MOUSE_UP) keyDown() (Event.KEY_PRESS or Event.KEY_ACTION) keyUp() (Event.KEY_RELEASE or Event.KEY_ACTION_RELEASE) gotFocus() (Event.GOT_FOCUS) lostFocus() (Event.LOST_FOCUS) handleEvent() (all event types) 交通大學資訊工程學系 蔡文能 5-第33頁 Java More-GUI Example 舊的方法 public boolean action(Event e, Object arg) { if (e.target instanceof TextField) { setSliderValue(getValue()); controller.convert(this); return true; } if (e.target instanceof Choice) { . . . } return false; } public boolean handleEvent(Event e) { if (e.target instanceof Scrollbar) { textField.setText(String.valueOf(slider.getValue())); controller.convert(this); } return super.handleEvent(e); } 交通大學資訊工程學系 蔡文能 5-第34頁 Java 交通大學資訊工程學系 蔡文能 More-GUI 5-第35頁 Java More-GUI Another example (1/ 7) //eventHandler.java import java.awt.*; class eventCanvas extends Canvas { boolean hasFocus; 需要寫一個簡單的 HTML 把這 Applet 叫起來 eventCanvas( int width, int height ) { setBackground( Color.yellow ); resize( width, height ); hasFocus = false; } public boolean mouseUp( Event e, int x, int y ) { eventHandler.reportEvent( "mouseUp" ); return true; } 交通大學資訊工程學系 蔡文能 5-第36頁 Java More-GUI Another example (2/7 ) public boolean mouseDown( Event e, int x, int y ) { eventHandler.reportEvent( "mouseDown" ); return true; } public boolean mouseDrag( Event e, int x, int y ) { eventHandler.reportEvent( "mouseDrag" ); return true; } public boolean mouseEnter( Event e, int x, int y ) { eventHandler.reportEvent( "mouseEnter" ); return true; } public boolean mouseExit( Event e, int x, int y ) { eventHandler.reportEvent( "mouseExit" ); return true; } 交通大學資訊工程學系 蔡文能 5-第37頁 Java More-GUI Another example (3/7 ) public boolean keyDown( Event e, int key ) { String eventString = "keyDown: "; String keyName, modifierName; modifierName = getModifierName( e ); if ( modifierName != null ) eventString += modifierName; keyName = getKeyName( key ); if ( keyName != null ) eventString += keyName; else if (( key >= 32 ) && ( key <= 127 )) eventString += new Character( (char)key ).toString(); else eventString += key; eventHandler.reportEvent( eventString ); return true; } 交通大學資訊工程學系 蔡文能 5-第38頁 Java More-GUI Another example (4/7 ) public String getModifierName( Event e ) { if ( e.controlDown() ) return( "Control-" ); if ( e.metaDown() ) return( "Meta-" ); if ( e.shiftDown() ) return( "Shift-" ); case Event.F10: return "F10"; case Event.F11: return "F11"; case Event.F12: return "F12"; case Event.HOME: return "HOME"; case Event.END: return "END"; case Event.LEFT: return "Left Arrow"; case Event.RIGHT: return "Right Arrow"; case Event.UP: return "Up Arrow"; case Event.DOWN: return "DownArrow"; case Event.PGUP: return "Page Up"; case Event.PGDN: return "Page Down"; } //switch return null; } public String getKeyName( int key ) { switch ( key ) { case Event.F1: return "F1"; case Event.F2: return "F2"; case Event.F3: return "F3"; case Event.F4: return "F4"; case Event.F5: return "F5"; case Event.F6: return "F6"; case Event.F7: return "F7"; case Event.F8: return "F8"; case Event.F9: return "F9"; return null; } 交通大學資訊工程學系 蔡文能 5-第39頁 Java More-GUI Another example (5/7 ) public boolean keyUp( Event e, int key ) { eventHandler.reportEvent( "keyUp" ); return true; } public boolean gotFocus(Event e, Object what) { hasFocus = true; eventHandler.reportEvent( "gotFocus" ); repaint(); return true; } public boolean lostFocus(Event e, Object what) { hasFocus = false; eventHandler.reportEvent( "lostFocus" ); repaint(); return true; } 交通大學資訊工程學系 蔡文能 5-第40頁 Java More-GUI Another example (6/7 ) public void paint( Graphics g ) { Rectangle r; r = bounds(); g = getGraphics(); if ( hasFocus ) g.setColor( Color.red ); else g.setColor( Color.yellow ); g.drawRect( 0, 0, r.width-1, r.height-1 ); g.drawRect( 1, 1, r.width-3, r.height-3 ); } } //class eventCanvas 交通大學資訊工程學系 蔡文能 5-第41頁 Java More-GUI Another example (7/7) public class eventHandler extends java.applet.Applet { eventCanvas eCanvas; static TextArea tArea; public void init() { add( new Label( "Click and type in this Canvas:" ) ); eCanvas = new eventCanvas( 200, 100 ); add( eCanvas ); add( new Label( "Here’s a list of canvas events:" ) ); tArea = new TextArea( 15, 30 ); add( tArea ); setVisible(true); } public static void reportEvent( String eventString ) { tArea.appendText( eventString + "\r" ); } 需要寫一個簡單的 HTML 把這 Applet 叫起來 <HTML><body> <applet code=eventHandler.class Width=555 Height=333> </applet> } 交通大學資訊工程學系 蔡文能 5-第42頁 Java More-GUI AWT 1.1. Event Model In the 1.1 AWT event model, events are generated by event sources. One or more listeners can register to be notified about events of a particular kind from a particular source. In every program that has an event handler, you'll see three bits of code: Code that registers an instance of a listener. someComponent.addActionListener(instanceOfMyClass); Declare the event handler implementing a listener interface. public class MyClass implements ActionListener { The implementation of the methods in the listener interface. public void actionPerformed(ActionEvent e) { ...//code that reacts to the action... } 交通大學資訊工程學系 蔡文能 5-第43頁 Java More-GUI Example public class MultiListener ... implements ActionListener { //... //where initialization occurs: button1.addActionListener(this); button2.addActionListener(this); button2.addActionListener(new Eavesdropper(bottomTextArea)); public void actionPerformed(ActionEvent e) { topTextArea.append(e.getActionCommand() + "\n"); } } class Eavesdropper implements ActionListener { ... public void actionPerformed(ActionEvent e) { myTextArea.append(e.getActionCommand() + "\n"); } } 交通大學資訊工程學系 蔡文能 5-第44頁 Java More-GUI Events The Java standard class library contains several classes that represent typical events Certain objects, such as an applet or a graphical button, generate (fire) an event when it occurs Other objects, called listeners, respond to events We can write listener objects to do whatever we want when an event occurs 交通大學資訊工程學系 蔡文能 5-第45頁 Java More-GUI Listener Interfaces We can create a listener object by writing a class that implements a particular Listener interface The Java standard class library contains several interfaces that correspond to particular event categories For example, the MouseListener interface contains methods that correspond to mouse events After creating the listener, we add the listener to the component that might generate the event to set up a formal relationship between the generator and listener 交通大學資訊工程學系 蔡文能 5-第46頁 Java More-GUI ActionListener 交通大學資訊工程學系 蔡文能 5-第47頁 Java More-GUI Problem of Using Listeners AWT Listeners usually have several methods. If a class implements the listener, need to write all the methods. //An example with cluttered but valid code. public class MyClass implements MouseListener { //... someObject.addMouseListener(this); //... /* Empty method definitions are required. */ public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { //..Event handler implementation goes here... } } 交通大學資訊工程學系 蔡文能 5-第48頁 Java More-GUI Solution: Using Adaptors Use Adaptor instead of Listener to simplify design. /* * An example of extending an adapter class instead of * directly implementing a listener interface. */ public class MyClass extends MouseAdapter { //... someObject.addMouseListener(this); //... public void mouseClicked(MouseEvent e) { //...Event handler implementation goes here... } } 交通大學資訊工程學系 蔡文能 5-第49頁 Java 交通大學資訊工程學系 蔡文能 More-GUI 5-第50頁 Java More-GUI Using Inner Classes Use inner classes with adaptors to simplify design. //An example of using an anonymous inner class. public class MyClass extends Applet { //... someObject.addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent e) { //..Event handler implementation // .. goes here... } // with Adapter, only methos we want } ); //... } } 交通大學資訊工程學系 蔡文能 5-第51頁 Java More-GUI Listener interfaces ActionListener actionPerformed(ActionEvent e) AdjustmentListener adjustmentValueChanged(AdjustmentEvent e) AncestorListener ancestorAdded(AncestorEvent event) ancestorMoved(AncestorEvent event) ancestorRemoved(AncestorEvent event) AWTEventListener eventDispatched(AWTEvent event) BeanContextMembershipListener childrenAdded(BeanContextMembershipEvent bcme) childrenRemoved(BeanContextMembershipEvent bcme) ... 交通大學資訊工程學系 蔡文能 5-第52頁 Java More-GUI Standard AWT Events (1/2) Handling standard AWT events Listener Interface ActionListener AdjustmentListener ComponentListener Adapter Class none none ComponentAdapter ContainerListener ContainerAdapter FocusListener FocusAdapter ItemListener KeyListener none KeyAdapter 交通大學資訊工程學系 蔡文能 Methods actionPerformed adjustmentValueChanged componentHidden componentMoved componentResized componentShown componentAdded componentRemoved focusGained focusLost itemStateChanged keyPressed keyReleased keyTyped 5-第53頁 Java More-GUI Standard AWT Events (2/2) Listener Interface MouseListener MouseMotionListener TextListener WindowListener 交通大學資訊工程學系 蔡文能 Adapter Class MouseAdapter Methods mouseClicked mouseEntered mouseExited mousePressed mouseReleased MouseMotionAdapter mouseDragged mouseMoved None textValueChanged WindowAdapter windowActivated windowClosed windowClosing windowDeactivated windowDeiconified windowIconified windowOpened 5-第54頁 Java More-GUI Events Generated by AWT Components The AWT events can be divided into two groups: component-level (low-level) events and semantic events. Component-Level Events Represent user or window-system actions such as a mouse click or a key press, … ComponentEvent, FocusEvent, InputEvent, KeyEvent, MouseEvent, ContainerEvent, WindowEvent Semantic Events Represent higher-level functions or meanings of events such as double-clicking a text-line, … ActionEvent, AdjustmentEvent, ItemEvent, TextEvent Please see our text book: chap 7 , .. 交通大學資訊工程學系 蔡文能 5-第55頁 Java More-GUI Action Listener Writing an action listener The ActionListener interface contains a single method. void actionPerformed(ActionEvent) No corresponding adapter class since there is only one method. An action event occurs, When the user clicks a button, When doubleclicks a list item, When chooses a menu item, When presses return in a text field, An action event handling code example : public class Beeper ... implements ActionListener { //... //where initialization occurs: button.addActionListener(this); //... public void actionPerformed(ActionEvent e) { //…Make a beep sound... } } 交通大學資訊工程學系 蔡文能 5-第56頁 Java More-GUI Action Events The ActionEvent class String getActionCommand() Returns the string associated with this action. Default string is the text displayed in the component. int getModifiers() Returns an integer representing the modifier keys the user was pressing when the action event occurred. For example, if the user shift-selects a menu item, then the following expression is nonzero: actionEvent.getModifiers() & ActionEvent.SHIFT_MASK 交通大學資訊工程學系 蔡文能 5-第57頁 Java More-GUI ActionEvent methods 交通大學資訊工程學系 蔡文能 5-第58頁 Java More-GUI Adjustment Listener Adjustment events notify you of changes in the value of components that implement the adjustable interface. The only AWT class that implements adjustable is scrollbar. There are five kinds of adjustment events: Track Unit increment, unit decrement Block increment, block decrement The AdjustmentListener interface contains a single method. No corresponding adapter class. void adjustmentValueChanged(AdjustmentEvent) 交通大學資訊工程學系 蔡文能 5-第59頁 Java More-GUI Adjustment Events The AdjustmentEvent class defines the following handy methods: Adjustable getAdjustable() Returns the component that generated the event. int getAdjustmentType() Returns the type of adjustment that occurred. The returned value is one of the following UNIT_INCREMENT, UNIT_DECREMENT, BLOCK_INCREMENT, BLOCK_DECREMENT, TRACK. int getValue() Returns the value of the component just after the adjustment occurred. 交通大學資訊工程學系 蔡文能 5-第60頁 Java More-GUI Component Listener One or more component events are generated by a component object. After the component is hidden, made visible, moved, or resized. The component hidden and component visible events occur only as the result of calls to a component's setVisible method. For example, a window might be miniaturized into an icon (iconified), without a component hidden event being generated. Component Listener Methods void void void void componentHidden(ComponentEvent) componentMoved(ComponentEvent) componentResized(ComponentEvent) componentShown(ComponentEvent) 交通大學資訊工程學系 蔡文能 5-第61頁 Java More-GUI Container Listener Methods Void componentAdded(ContainerEvent) Void componentRemoved(ContainerEvent) The ContainerEvent class defines two useful methods: Component getChild() Container getContainer() 交通大學資訊工程學系 蔡文能 5-第62頁 Java More-GUI Focus Listener Writing a focus listener Focus events are generated whenever a component gains or loses the keyboard focus -- the ability to receive keyboard events. At most one component in the window system can have the keyboard focus. You can request that a component get the focus by invoking the Component`s requestFocus method. The FocusListener interface and its corresponding adapter class, FocusAdapter, contain two methods: void focusGained(FocusEvent) void focusLost(FocusEvent) 交通大學資訊工程學系 蔡文能 5-第63頁 Java More-GUI Item Listener Writing an Item Listener Item events are generated by components that implement the ItemSelectable interface. The 1.1 AWT components that generate item events are checkboxes, checkbox menu items, choices, and lists. The ItemListener interface has just one method, so it has no corresponding adapter class. void itemStateChanged(ItemEvent) Called by the AWT just after a state change in the listenedto component. 交通大學資訊工程學系 蔡文能 5-第64頁 Java More-GUI Item Events The ItemEvent class defines the following handy methods: Object getItem() Returns the component-specific object associated with the item whose state changed. Often this is a String containing the text on the selected item. For an item event generated by a List, this is an Integer that specifies the index of the selected item. ItemSelectable getItemSelectable() Returns the component that generated the item event. int getStateChange() Returns the new state of the item. The ItemEvent class defines two states: SELECTED and DESELECTED. 交通大學資訊工程學系 蔡文能 5-第65頁 Java More-GUI Key Listener Writing a key listener Key events tell you when the user types at the keyboard. Two basic kinds of key events: Typing of a Unicode character -- key typed event. Pressing or releasing of a key on the keyboard -- key pressed and key released event. Three methods: void keyTyped(KeyEvent) void keyPressed(KeyEvent) void keyReleased(KeyEvent) 交通大學資訊工程學系 蔡文能 5-第66頁 Java More-GUI Key Events The KeyEvent class defines the following useful methods: int getKeyChar() void setKeyChar(char) Get or set the Unicode character associated with this event. int getKeyCode() void setKeyCode(int) Get or set the key code associated with this event. For example, VK_A specifies the key labeled A, and VK_ESCAPE specifies the ESCAPE key. void setModifiers(int) Sets the state of the modifier keys for this event. 交通大學資訊工程學系 蔡文能 5-第67頁 Java More-GUI Mouse Listener Writing a mouse listener Mouse events tell you when the user uses the mouse (or similar input device) to interact with a component. Methods: Void void void void void mouseClicked(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) Mouse Events: int getClickCount() int getX() int getY() Point getPoint() boolean isPopupTrigger() 交通大學資訊工程學系 蔡文能 5-第68頁 Java More-GUI import java.applet.Applet; import java.awt.*; public class Dots extends Applet { private final int APPLET_WIDTH = 200; private final int APPLET_HEIGHT = 100; private final int RADIUS = 6; private Point clickPoint = null; public void init() { DotsMouseListener listener = new DotsMouseListener(this); addMouseListener(listener); setBackground (Color.black); setSize (APPLET_WIDTH, APPLET_HEIGHT); } 交通大學資訊工程學系 蔡文能 5-第69頁 Java More-GUI public void paint (Graphics page){ page.setColor (Color.green); if (clickPoint != null) page.fillOval (clickPoint.x - RADIUS, clickPoint.y - RADIUS, RADIUS * 2, RADIUS * 2); } public void setPoint (Point point) { clickPoint = point; } } 交通大學資訊工程學系 蔡文能 5-第70頁 Java Class implementing listener interface More-GUI import java.applet.Applet; import java.awt.*; import java.awt.event.*; class DotsMouseListener implements MouseListener { private Dots applet; public DotsMouseListener (Dots applet) { this.applet = applet; } public void mouseClicked (MouseEvent event) { Point clickPoint = event.getPoint(); applet.setPoint (clickPoint); applet.repaint(); } 交通大學資訊工程學系 蔡文能 5-第71頁 Java More-GUI //-----------------------------------------------------// Provide empty definitions for unused event methods. //-----------------------------------------------------public void mousePressed (MouseEvent event) {} public void mouseReleased (MouseEvent event) {} public void mouseEntered (MouseEvent event) {} public void mouseExited (MouseEvent event) {} }// end of DotsMouseListener 交通大學資訊工程學系 蔡文能 5-第72頁 Java More-GUI Input Events The MouseEvent class extends InputEvent, which extends ComponentEvent. InputEvent provides the following useful methods: int getWhen() boolean isAltDown() boolean isControlDown() boolean isMetaDown() boolean isShiftDown() int getModifiers() 交通大學資訊工程學系 蔡文能 5-第73頁 Java More-GUI Mouse Motion Listener Writing a mouse motion listener Mouse motion events tell you when the user uses the mouse (or a similar input device) to move the onscreen cursor. Methods: void mouseDragged(MouseEvent) void mouseMoved(MouseEvent) 交通大學資訊工程學系 蔡文能 5-第74頁 Java More-GUI Text Listener Writing a text listener Text events are generated after the text in a text component has changed somehow. The TextListener interface has just one method, so it has no corresponding adapter class. Void textValueChanged(TextEvent) Called by the AWT just after the text in the listened-to component changes. 交通大學資訊工程學系 蔡文能 5-第75頁 Java More-GUI Window Listener Writing a window listener Window events are generated by a window just after the window is opened, closed, iconified, deiconified, activated, or deactivated. Methods: void void void void void void void windowOpened(WindowEvent) windowClosing(WindowEvent) windowClosed(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent) windowActivated(WindowEvent) windowDeactivated(WindowEvent) 交通大學資訊工程學系 蔡文能 5-第76頁 Java More-GUI Take a Break Take a Break Take a Break Take a Break Take a Break Take a Break Take a Break Take a Break 交通大學資訊工程學系 蔡文能 5-第77頁 Java More-GUI What Is Layout Managers? An object that controls the size and position of components in a container. Panel : default -- FlowLayout Window : default -- GridLayout 交通大學資訊工程學系 蔡文能 5-第78頁 Java More-GUI How to Use BorderLayout Example: setLayout(new BorderLayout()); add("North", new Button("North")); add("South", new Button("South")); add("East", new Button("East")); add("West", new Button("West")); add("Center", new Button("Center")); 交通大學資訊工程學系 蔡文能 5-第79頁 Java More-GUI • If you use the one-argument version of add(), or if you specify an invalid first argument, your component might not be visible. • BorderLayout puts no gap between the components by default. • Specify gaps (in pixels) using the following constructor: – public BorderLayout(int horizontalGap, int verticalGap) 交通大學資訊工程學系 蔡文能 5-第80頁 Java More-GUI How to Use FlowLayout setLayout(new FlowLayout()); add(new add(new add(new add(new add(new Button("Button 1")); Button("2")); Button("Button 3")); Button("Long-Named Button 4")); Button("Button 5")); Three constructors: public FlowLayout() public FlowLayout(int alignment) alignment value : FlowLayout.LEFT, FlowLayout.CENTER, or FlowLayout.RIGHT public FlowLayout(int alignment, int horizontalGap, int verticalGap) Default gap is 5 pixels. 交通大學資訊工程學系 蔡文能 5-第81頁 Java More-GUI How to Use CardLayout public class CardWindow extends Frame implements ItemListener { Panel cards; final static String BUTTONPANEL = "Panel with Buttons"; final static String TEXTPANEL = "Panel with TextField"; public CardWindow() { setLayout(new BorderLayout()); //Put the Choice in a Panel to get a nicer look. Panel cp = new Panel(); Choice c = new Choice(); c.addItem(BUTTONPANEL); c.addItem(TEXTPANEL); c.addItemListener(this); cp.add(c); add("North", cp); 交通大學資訊工程學系 蔡文能 5-第82頁 Java cards = new Panel(); cards.setLayout(new CardLayout()); Panel p1 = p1.add(new p1.add(new p1.add(new More-GUI new Panel(); Button("Button 1")); Button("Button 2")); Button("Button 3")); Panel p2 = new Panel(); p2.add(new TextField("TextField", 20)); cards.add(BUTTONPANEL, p1); cards.add(TEXTPANEL, p2); add("Center", cards); . . . } public void itemStateChanged(ItemEvent evt) { CardLayout cl = (CardLayout)(cards.getLayout()); cl.show(cards, (String)evt.getItem()); } 交通大學資訊工程學系 蔡文能 5-第83頁 Java More-GUI How to Use GridLayout //Construct a GridLayout with 2 columns and // an unspecified number of rows. setLayout(new GridLayout(0,2)); add(new add(new add(new add(new add(new Button("Button 1")); Button("2")); Button("Button 3")); Button("Long-Named Button 4")); Button("Button 5")); Two constructors: public GridLayout(int rows, int columns) At least one of the rows and columns arguments must be non-zero. public GridLayout(int rows, int columns, int horizontalGap, int verticalGap) 交通大學資訊工程學系 蔡文能 5-第84頁 Java More-GUI GridBag Layout Layout controls using a rectangular grid controls can span multiple rows or columns use constraints (0,0) (1,0) (2,0) Spans 3 columns Spans 2 columns 交通大學資訊工程學系 蔡文能 5-第85頁 Java More-GUI GridBag Layout Constraints gridx, gridy = upper left corner of control (0,0) (1,0) (2,0) Spans 3 columns Spans 2 columns gridwidth = columns to span gridheight = rows to span weightx = how much of extra space goes to this column weighty = how much of extra space goes to this row fill = (none, H, V) anchor = {NW, N, NE, E…} 交通大學資訊工程學系 蔡文能 5-第86頁 Java More-GUI How to Use GridBagLayout Using GridBagLayout GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); //For each component to be added to this container: //...Create the component... //...Set instance variables in the GridBagConstraints // instance... gridbag.setConstraints(theComponent, c); add(theComponent); 交通大學資訊工程學系 蔡文能 5-第87頁 Java More-GUI GridBagContraints again (1/2) gridx,gridy • Specify the row and column at the upper left of the component. • GridBagConstraints.RELATIVE (default value) gridwidth,gridheight Specify the number of columns (for gridwidth) or rows (for gridheight) of the component. The default value is 1. GridBagConstraints.REMAINDER GridBagConstraints.RELATIVE fill GridBagConstraints.NONE (the default) GridBagConstraints.HORIZONTAL GridBagConstraints.VERTICAL GridBagConstraints.BOTH ipadx,ipady Specifies the internal padding. The default value is zero. 交通大學資訊工程學系 蔡文能 5-第88頁 Java More-GUI GridBagContraints again (2/2) insets Specifies the external padding of the component. Default is no external padding. anchor Valid values are GridBagConstraints.CENTER (the default), GridBagConstraints.NORTH, GridBagConstraints.NORTHEAST, GridBagConstraints.EAST, GridBagConstraints.SOUTHEAST, GridBagConstraints.SOUTH, GridBagConstraints.SOUTHWEST, GridBagConstraints.WEST, and GridBagConstraints.NORTHWEST. weightx,weighty Used to determine how to distribute space among columns (weightx) and among rows (weighty). 交通大學資訊工程學系 蔡文能 5-第89頁 Java More-GUI GridBagLayout Example (1/2) protected void makebutton(String name, GridBagLayout gridbag, GridBagConstraints c) { Button button = new Button(name); gridbag.setConstraints(button, c); add(button); } public GridBagWindow() { GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; makebutton("Button1", gridbag, c); makebutton("Button2", gridbag, c); makebutton("Button3", gridbag, c); c.gridwidth = GridBagConstraints.REMAINDER; //end of row makebutton("Button4", gridbag, c); 交通大學資訊工程學系 蔡文能 5-第90頁 Java More-GUI GridBagLayout Example (2/2) c.weightx = 0.0; //reset to the default makebutton("Button5", gridbag, c); //another row c.gridwidth = GridBagConstraints.RELATIVE; //next to last in row makebutton("Button6", gridbag, c); c.gridwidth = GridBagConstraints.REMAINDER; //end of row makebutton("Button7", gridbag, c); c.gridwidth = 1; //reset to the default c.gridheight = 2; c.weighty = 1.0; makebutton("Button8", gridbag, c); c.weighty = 0.0; //reset to the default c.gridwidth = GridBagConstraints.REMAINDER; //end of row c.gridheight = 1; //reset to the default makebutton("Button9", gridbag, c); makebutton("Button10", gridbag, c); } 交通大學資訊工程學系 蔡文能 5-第91頁 Java More-GUI fill = GridBagConstraints.NONE weight = 0 交通大學資訊工程學系 蔡文能 5-第92頁 Java More-GUI General Rules for Using Layout Managers How to Choose a Layout Manager Display a component in as much space as it can get BorderLayout Put the space-hungry component in the center. GridBagLayout Set the constraints for the component so that fill=GridBagConstraints.BOTH. GridLayout All components will be the same size. Display a few components in a compact row at their natural size Using a Panel and using the Panel's default FlowLayout manager. Display a few same-sized components in rows and/or columns GridLayout How to Create a Layout Manager and Associate It with a Container aContainer.setLayout(new CardLayout()); 交通大學資訊工程學系 蔡文能 5-第93頁 Java More-GUI Doing Without a Layout Manager public class NoneWindow extends Frame { private boolean laidOut = false; private Button b1, b2, b3; public NoneWindow() { super(); setLayout(null); b1 = new Button("one"); add(b1); b2 = new Button("two"); add(b2); b3 = new Button("three"); add(b3); } public void paint(Graphics g) { if (!laidOut) { Insets insets = insets(); b1.reshape(50 + insets.left, 5 + insets.top, 50, 20); b2.reshape(70 + insets.left, 35 + insets.top, 50, 20); b3.reshape(130 + insets.left, 15 + insets.top, 50, 30); laidOut = true; } } . . . } 交通大學資訊工程學系 蔡文能 5-第94頁 Java More-GUI Overview of AWT Graphics Support The Graphics Object paint(Graphics g), update(Graphics g) Two basic kinds of drawing Primitive graphics (such as lines, rectangles, and text) Images Provides a drawing context The current drawing area The current drawing color The Coordinate System The Four Forms of the repaint() Method public void repaint() public void repaint(long time) public void repaint(int x, int y, int width, int height) public void repaint(long time, int x, int y, int width, int height) 交通大學資訊工程學系 蔡文能 5-第95頁 Java More-GUI Drawing Shapes The Graphics class drawing the following kinds of shapes: Lines (drawLine()) Rectangles, (drawRect(), fillRect(), and clearRect()) Raised or lowered rectangles (draw3DRect() and fill3DRect()) Round-edged rectangles (drawRoundRect() and fillRoundRect()) Ovals (drawOval() and fillOval()) Arcs (drawArc() and fillArc()) Polygons (drawPolygon() and fillPolygon()) 交通大學資訊工程學系 蔡文能 5-第96頁 Java More-GUI Example: Simple Rectangle Drawing //In FramedArea (a Panel subclass): public Insets getInsets() { return new Insets(4,4,5,5); } public void paint(Graphics g) { Dimension d = getSize(); Color bg = getBackground(); g.setColor(bg); g.draw3DRect(0, 0, d.width - 1, d.height - 1, true); g.draw3DRect(3, 3, d.width - 7, d.height - 7, false); } 交通大學資訊工程學系 蔡文能 5-第97頁 Java More-GUI Example (cont.) class CoordinateArea extends Canvas { Point point = null; CoordinatesDemo controller; public CoordinateArea(CoordinatesDemo controller) { super(); this.controller = controller; addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { int x=e.getX(); int y=e.getY(); if(point==null) { point=new Point(x, y); } else { point.x=x; point.y=y; } repaint(); } }); } public void paint(Graphics g) { if(point != null) { controller.updateLabel(point); g.fillRect(point.x - 1, point.y - 1, 2, 2); } } } 交通大學資訊工程學系 蔡文能 5-第98頁 Java More-GUI Example: Selected Area Using a Rectangle to Indicate a Selected Area class SelectionArea extends Canvas { Rectangle currentRect = null; RectangleDemo controller; public SelectionArea(RectangleDemo controller) { super(); this.controller = controller; MyListener myListener = new MyListener(); addMouseListener(myListener); addMouseMotionListener(myListener); } 交通大學資訊工程學系 蔡文能 5-第99頁 Java More-GUI public void paint(Graphics g) { //update has already cleared the previous rectangle, //so we don't need to here. //If currentRect exists, paint a rectangle on top. if (currentRect != null) { Dimension d = getSize(); Rectangle box = getDrawableRect(currentRect, d); controller.updateLabel(box); //Draw the box outline. g.drawRect(box.x, box.y, box.width - 1, box.height - 1); } } Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) { . . . //Make sure rectangle width and height are positive. . . . //The rectangle shouldn't extend past the drawing area. . . . } 交通大學資訊工程學系 蔡文能 5-第100頁 Java More-GUI class MyListener extends MouseAdapter implements MouseMotionListener { public void mousePressed(MouseEvent e) { int x = e.getX(); int y = e.getY(); currentRect = new Rectangle(x, y, 0, 0); repaint(); } public void mouseReleased(MouseEvent e) {updateSize(e);} public void mouseDragged(MouseEvent e) {updateSize(e);} public void mouseMoved(MouseEvent e) {} void updateSize(MouseEvent e) { int x = e.getX(); int y = e.getY(); currentRect.setSize(x-currentRect.x, y-currentRect.y); repaint(); } } 交通大學資訊工程學系 蔡文能 5-第101頁 Java More-GUI Working With Text Drawing Text Using text-oriented Component Label, TextField, or TextArea Example: label.setText("Hello World!"); If a Component isn't appropriate Using the Graphics drawBytes(), drawChars(), or drawString() methods. Example: g.drawString("Hello World!", x, y); g.drawString("Hello World!", x, y); x and y specify the position of the lower left corner of the text. The y coordinate specifies the baseline of the text. d 交通大學資訊工程學系 蔡文能 5-第102頁 Java More-GUI Font and FontMetrics Getting Information about a Font: FontMetrics FontMetrics pickFont(Graphics g, String longString, int xSpace) { boolean fontFits = false; Font font = g.getFont(); FontMetrics fontMetrics = g.getFontMetrics(); int size = font.getSize(); String name = font.getName(); int style = font.getStyle(); while (!fontFits) { if ( fontMetrics.getHeight()<=maxCharHeight && fontMetrics.stringWidth(longString)<=xSpace ) { fontFits = true; } else { if (size <= minFontSize) { fontFits = true; } else { g.setFont(font = new Font(name, style, --size)); fontMetrics = g.getFontMetrics(); } } } return fontMetrics; } 交通大學資訊工程學系 蔡文能 5-第103頁 Java More-GUI FontMetrics – – – getAscent(), getMaxAscent() getDescent(), getMaxDescent() getHeight() getWidth() getMaxAdvance() charWidth(int), charWidth(char) charsWidth(char[], int, int) stringWidth(String) getWidths() 交通大學資訊工程學系 蔡文能 5-第104頁 Java More-GUI Using Images Loading Images Using the getImage() Methods It is easy to get an Image object for it if Image data is in GIF or JPEG format. myImage = getImage(URL); // in an Applet subclass only myImage = Toolkit.getDefaultToolkit().getImage(filenameOrURL); Applets The Applet class supplies : public Image getImage(URL url) public Image getImage(URL url, String name) Example: Image image1 = getImage(getCodeBase(), "imageFile.gif"); Image image2 = getImage(getDocumentBase(),"anImageFile.jpeg"); Image image3 = getImage(new URL("http://java.sun.com/graphics/people.gif")); Toolkit: Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image1 = toolkit.getImage("imageFile.gif"); Image image2 = toolkit.getImage(new URL("http://java.sun.com/graphics/people.gif")); 交通大學資訊工程學系 蔡文能 5-第105頁 Java More-GUI MemoryImageSource Creating Images with MemoryImageSource The following code example calculates a 100x100 image representing a fade from black to blue along the X axis and a fade from black to red along the Y axis. int w = 100; int h = 100; int[] pix = new int[w * h]; int index = 0; for (int y = 0; y < h; y++) { int red = (y * 255) / (h - 1); for (int x = 0; x < w; x++) { int blue = (x * 255) / (w - 1); pix[index++] = (255 << 24) | (red << 16) | blue; } } Image img = createImage( new MemoryImageSource(w, h, pix, 0, w)); 交通大學資訊工程學系 蔡文能 5-第106頁 Java More-GUI Image Loading Requesting and Tracking Image Loading: MediaTracker and ImageObserver The MediaTracker class is sufficient for many programs. See the example improvingImageAnim The ImageObserver interface lets you keep even closer track of image loading than MediaTracker allows. To use the ImageObserver interface, you implement the ImageObserver imageUpdate() method. 交通大學資訊工程學系 蔡文能 5-第107頁 Java More-GUI imageUpdate in ImageObserver Here is an example of imageUpdate() method: public boolean imageUpdate(Image theimg, int infoflags, int x, int y, int w, int h) { if ((infoflags & (ERROR)) != 0) { errored = true; } if ((infoflags & (WIDTH | HEIGHT)) != 0) { positionImages(); } boolean done = ( (infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0 ); // Repaint immediately if we are done, // otherwise batch up repaint requests // every 100 milliseconds repaint(done ? 0 : 100); //If done, no further updates required. return !done; } 交通大學資訊工程學系 蔡文能 5-第108頁 Java More-GUI Displaying Images Below is an applet that loads a single image and displays it twice, using both code examples below : g.drawImage(image, 0, 0, this); g.drawImage(myImage, 90, 0, 300, 62, this); 交通大學資訊工程學系 蔡文能 5-第109頁 Java More-GUI Manipulating Images The figure shows how image data is created: An image filter is an ImageFilterobject Sitting between a producer and a consumer. Modifying the image data before the consumer gets it. Image sourceImage; ...//Initialize sourceImage, using the Toolkit or Applet getImage() method. ImageFilter filter = new SomeImageFilter(); ImageProducer producer = new FilteredImageSource(sourceImage.getSource(), filter); Image resultImage = createImage(producer); 交通大學資訊工程學系 蔡文能 5-第110頁 Java More-GUI Example: Rotate an Image (1/2) public class ImageRotator extends Applet { . . . RotatorCanvas rotator; double radiansPerDegree = Math.PI / 180; public void init() { //Load the image. Image image = getImage(getCodeBase(), "../images/rocketship.gif"); ...//Create the component that uses the image filter: rotator = new RotatorCanvas(image); . . . add(rotator); . . . } public boolean action(Event evt, Object arg) { int degrees; ...//Get the number of degrees to rotate the image //Convert to radians. rotator.rotateImage((double)degrees * radiansPerDegree); return true; } } 交通大學資訊工程學系 蔡文能 5-第111頁 Java More-GUI Example: Rotate an Image (2/2) class RotatorCanvas extends Canvas { Image sourceImage; Image resultImage; public RotatorCanvas(Image image) { sourceImage = image; resultImage = sourceImage; } public void rotateImage(double angle) { ImageFilter filter = new RotateFilter(angle); ImageProducer producer = new FilteredImageSource( sourceImage.getSource(), filter); resultImage = createImage(producer); repaint(); } public void paint(Graphics g) { Dimension d = size(); int x = (d.width-resultImage.getWidth(this))/2; int y = (d.height-resultImage.getHeight(this))/2; g.drawImage(resultImage, x, y, this); } } 交通大學資訊工程學系 蔡文能 5-第112頁 Java More-GUI Another Suggestion int [] thispixels = new thispixels[width*height]; PixelGrabber pg = new PixelGrabber(anImage, 0, 0, width, height, thispixels, 0, width); try { pg.grabPixels(); } catch (InterruptedException e) { System.err.println("waiting for pixels!"); return null; } Image destination = Elife.createImage(new MemoryImageSource(width, height, thispixels, 0, width)); 交通大學資訊工程學系 蔡文能 5-第113頁 Java More-GUI Performing Animation Creating the Animation Loop Every program that performs animation by drawing at regular intervals needs an animation loop. This loop should be in its own thread and never be in the paint() or update() method. Initializing Instance Variables frameNumber represents the current frame. It's initialized to -1, even though the first frame number is 0. delay is the number of milliseconds between frames. animatorThread is a Thread object, representing the thread in which the animation loop runs. frozen is a boolean value that's initialized to false. Set it to true to indicate that the user has requested that the animation stop. 交通大學資訊工程學系 蔡文能 5-第114頁 Java More-GUI Example (1/2) public class AnimatorClass extends AComponentClass implements Runnable { //In initialization code: //From user-specified frames-per-second value, //determine how long to delay between frames. //In a method that does nothing but start the animation: //Create and start the animating thread. //In a method that does nothing but stop the animation: //Stop the animating thread. public boolean mouseDown(Event e, int x, int y) { if ( /* animation is currently frozen */ ) { //Call the method that starts the animation. } else { //Call the method that stops the animation. } } 交通大學資訊工程學系 蔡文能 5-第115頁 Java More-GUI Example (2/2) public void run() { // Lower this thread's priority so it can't // interfere with other processing going on. // Remember the starting time. // Here's the animation loop: while ( /* animation thread is still running */ ) { // Advance the animation frame. // Display it. // Delay depending on how far we are behind. } } public void paint(Graphics g) { // Draw the current frame of animation. } } 交通大學資訊工程學系 蔡文能 5-第116頁 Java More-GUI Animation Loop Advances the frame number. Calls the repaint() method to request that the current frame of animation be drawn. Sleeps for up to delay milliseconds. while (/* animation thread is still running */) { //Advance the animation frame. frameNumber++; //Display it. repaint(); ...//Delay depending on how far we are behind. } Ensuring a Constant Frame Rate long startTime = System.currentTimeMillis(); while (/* animation thread is still running */) { ...//Advance the animation frame and display it. try { startTime += delay; Thread.sleep(Math.max(0, startTime-System.currentTimeMillis())); } catch (InterruptedException e) { break; } } 交通大學資訊工程學系 蔡文能 5-第117頁 Java More-GUI Behaving Politely Allowing the user to stop (and restart) the animation, while the applet or application is still visible. Implemented by overriding the mouseDown() method. Suspending the animation whenever the applet or application is known not to be visible. This is achieved by implementing the Applet stop() and start() methods 交通大學資訊工程學系 蔡文能 5-第118頁 Java More-GUI Animating Graphics An example applet that creates a moving a checkerboard effect by painting alternate squares which are drawn by the Graphics fillRect() method. // Draw the rectangle if necessary. if (fillSquare) { g.fillRect(x, y, w, h); fillSquare = false; } else { fillSquare = true; } 交通大學資訊工程學系 蔡文能 5-第119頁 Java More-GUI Eliminating Flashing Problem The flashing effect is the result of two facts: By default, the background of the animation is cleared before the paint() method is called. The computation in the paint() method is complex enough that it takes longer to compute and draw each frame than the video screen's refresh rate. Solution I 請參考 http://scv.bu.edu/Doc/Java/tutorial/ui/drawing/example/Update.java 交通大學資訊工程學系 蔡文能 5-第120頁 Java More-GUI Solution I Eliminating Flashing: Overriding the update() Method public void paint(Graphics g) { update(g); } public void update(Graphics g) { Color bg = getBackground(); Color fg = getForeground(); ...//same as old paint() method if (fillSquare) { g.fillRect(x, y, w, h); fillSquare = false; } else { g.setColor(bg); g.fillRect(x, y, w, h); g.setColor(fg); fillSquare = true; } ...//same as old paint() method } 交通大學資訊工程學系 蔡文能 5-第121頁 Java More-GUI Solution II Eliminating Flashing: Double Buffering Forcing the entire frame to be drawn at once. First creating an undisplayed buffer -- backbuffer or offscreen buffer. Drawing to the buffer Displaying the resulting image onscreen. To create an offscreen buffer with the AWT: Creating an image of the proper size. Getting a graphics context to manipulate the image. 請參考: http://scv.bu.edu/Doc/Java/tutorial/ui/drawing/doubleBuffer.html 交通大學資訊工程學系 蔡文能 5-第122頁 Java More-GUI Example //Where instance variables are declared: Dimension offDimension; Image offImage; Graphics offGraphics; . . . public void update(Graphics g) { . . . //In the update() method, where d holds the size of //the onscreen drawing area: if( (offGraphics == null) || (d.width != offDimension.width) || (d.height != offDimension.height) ) { offDimension = d; offImage = createImage(d.width, d.height); offGraphics = offImage.getGraphics(); } //Erase the previous image. offGraphics.setColor(getBackground()); offGraphics.fillRect(0, 0, d.width, d.height); offGraphics.setColor(Color.black); 交通大學資訊工程學系 蔡文能 5-第123頁 Java More-GUI Animation: Displaying a Sequence of Images Below are the ten images this applet uses. 交通大學資訊工程學系 蔡文能 5-第124頁 Java More-GUI Sample Code . . .//Where instance variables are declared: Image duke[10]; . . .//In the init() method: for (int i = 1; i <= 10; i++) { images[i-1] = getImage(getCodeBase(), "../../../images/duke/T"+i+".gif"); } . . .//In the update() method, //instead of calling drawFrame(): offGraphics.drawImage(images[frameNumber % 10], 0, 0, this); Problem: delay for each loading in drawImage(). Solution: Use MediaTracker to improve the performance 交通大學資訊工程學系 蔡文能 5-第125頁 Java More-GUI MediaTracker Using MediaTracker to Download Images and Delay Image Display To request a group of images be preloaded asynchronously, you can use checkID(true) and checkAll(true). To load data synchronously (waiting for the data to arrive), use the waitForID() and waitForAll() methods. 請參考 Java tutorial 裡的範例 交通大學資訊工程學系 蔡文能 improvingImageAnim 5-第126頁 Java More-GUI Speeding Up Image Loading Loading images using URLs (as applets usually do) usually takes a long time. Most of the time is taken up by initiating HTTP connections. The key to avoiding this performance hit is to combine the images in a single file. One simple way to combine images in a single file is to create an image strip. 交通大學資訊工程學系 蔡文能 5-第127頁 Java More-GUI Image Clipping To draw an image from the strip First set the clipping area to the size of one image. Then you draw the image strip, shifted to the left (if necessary) so that only the image you want appears within the clipping area. //imageStrip is the Image object representing the image strip. //imageWidth is the size of an individual image in the strip. //imageNumber is the number (from 0 to numImages) // of the image to draw. int stripWidth = imageStrip.getWidth(this); int stripHeight = imageStrip.getHeight(this); int imageWidth = stripWidth / numImages; g.clipRect(0, 0, imageWidth, stripHeight); g.drawImage(imageStrip, -imageNumber*imageWidth, 0, this); 交通大學資訊工程學系 蔡文能 5-第128頁 Java Swing Library again More-GUI http://java.sun.com/docs/books/tutorial/uiswing/TOC.html#start 交通大學資訊工程學系 蔡文能 5-第129頁 Java http://java.sun.com/docs/books/tutorial/ 交通大學資訊工程學系 蔡文能 More-GUI 5-第130頁 Java Swing Library More-GUI http://java.sun.com/docs/books/tutorial/uiswing/TOC.html#start 交通大學資訊工程學系 蔡文能 5-第131頁 Java 交通大學資訊工程學系 蔡文能 More-GUI 5-第132頁 Java More-GUI JFC/Swing GUI Components (1/6) Top-Level Containers Applet 交通大學資訊工程學系 蔡文能 Dialog Frame 5-第133頁 Java More-GUI JFC/Swing GUI Components (2/6) General-Purpose Containers Tabbed Pane Split Pane Scroll Pane Toolbar 交通大學資訊工程學系 蔡文能 Panel 5-第134頁 Java More-GUI JFC/Swing GUI Components (3/6) Special-Purpose Containers Internal Frame Layered Pane Root Pane 交通大學資訊工程學系 蔡文能 5-第135頁 Java More-GUI JFC/Swing GUI Components (4/6) Basic Controls Buttons Menu 交通大學資訊工程學系 蔡文能 Combobox Slider List Text Fields 5-第136頁 Java More-GUI JFC/Swing GUI Components (5/6) Uneditable Information Displays Progress Bar Label Tooltip 交通大學資訊工程學系 蔡文能 5-第137頁 Java More-GUI JFC/Swing GUI Components (6/6) Editable Displays of Formatted Information Table Color Chooser 交通大學資訊工程學系 蔡文能 Text Tree File Chooser 5-第138頁 Java More-GUI Introduction to Java Programming 謝謝捧場 http://www.csie.nctu.edu.tw/~tsaiwn/java/ 蔡文能 交通大學資訊工程學系 蔡文能 5-第139頁 Java 交通大學資訊工程學系 蔡文能 More-GUI 5-第140頁