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
Zaawansowane programowanie obiektowe Lecture 4 (Intro to GUI programming and applets) Szymon Grabowski [email protected] http://szgrabowski.kis.p.lodz.pl/zpo/ Thx to Wojciech Bieniecki for sharing stuff and friendly advices Łódź, 2009 1 GUIs Two main Java GUI libraries: Abstact Windows Toolkit (AWT) and Swing. AWT is much worse than Swing. Rumors say it was designed and implemented (in Sun) within a month... One of the weaknesses of AWT is that it contains ‘heavy’ components. Which means on different platforms AWT apps look different. 2 AWT class hierarchy 3 Swing class hierarchy 4 Common AWT component properties Size Location Bounds (ie. size and location) Font Background (its color) Foreground (its color) Parent Name Visible (boolean) Enabled (boolean) reading a property: getNNN() reading a boolean property: isNNN() setting (if possible): setNNN() 5 Basic properties: font, color Font(fontname, style, size); Font style constants: Font.BOLD, Font.ITALIC, Font.PLAIN. size - in points Example - setting the font for a button b: Button b = new Button("Press me"); b.setFont(new Font("Dialog", Font.PLAIN, 14)); b.setBackground(Color.blue); // or ...Color.BLUE b.setForeground(Color.white); or: int _r=200, _g=200, _b=200; b.setBackground(new Color(_r, _g, _b)); 6 Color, cont’d There are static fields for basic colors in java.awt.Color. E.g. public static final Color ORANGE // in sRGB space 7 Blocking a compontent Button b = new Button(...); b.setEnabled(false); // blocked; clicks onto b won’t have an effect if (!b.isEnabled()) // now, remove blocking b.setEnabled(true); Making a component visible b.setVisible(false); // will be invisible if (!b.isVisible()) b.setVisible(true); 8 Frames and Dialogs The Frame class provides windows for applets and applications. Every application needs at least one Frame. If an application has a window that should be dependent on another window – disappearing when the other window is iconified, for example – then you should use a Dialog instead for the dependent window. Frame, useful methods Minimize icon Image getIconImage(), setIconImage(Image) Title String getTitle(), setTitle(String) Menu bar MenuBar getMenuBar(), setMenuBar(MenuBar) remove(MenuComponent) setResizable(boolean), boolean isResizable() 9 Containers Containers are components that can hold other components (incl. containers!). Use add method to add a component to a container; remove – you know what for... someContainer.add(myCuteLabel); ... someContainer.remove(uglyBrownButton); A container has a layout that determines how the child components are arranged within the container. 10 Layouts FlowLayout BoxLayout BorderLayout OverlayLayout GridLayout ScrollpaneLayout CardLayout ViewportLayout GridBagLayout NoLayout Swing supports those layouts too (actually a few above are in Swing only, e.g. BoxLayout): See: http://www.cs.cf.ac.uk/Dave/HCI/HCI_Handout_CALLER/node55.html http://www.cis.upenn.edu/~matuszek/cit591-2004/Pages/layout-examples.html 11 Basic layouts 12 Flow layout The components won’t change (their size, their position) upon a change of the container. Constructors: FlowLayout () FlowLayout.CENTER, gap between 5 pixels FlowLayout (int) alignment parameter, gap FlowLayout (int, int, int) alignment, horizontal gap, vertical gap FlowLayout – quick and easy. Good first choice when using iterative development (later you can switch to a better layout, if necessary). 13 java.awt.GridLayout (1/3) Basic constructor: GridLayout (int rows, int cols) Beware: the number of columns cols may depend on the number of components (few components – perhaps less columns than cols). For a fixed number of columns, set row=0 (0 means any numer of rows with a fixed number of columns). Analogously if you need to have a fixed number of rows. GridLayout [ http://java.sun.com/docs/books/tutorial/uiswing/layout/grid.html ] Each component takes all the available space within its cell, and each cell is exactly the same size. If the window is resized, the GridLayout object changes the cell size so that the cells are as large as possible, given the space available to the container. 14 java.awt.GridLayout (2/3) Reading the # of rows / columns: int getRows () int getColumns () ... Container cp = getContentPane (); cp.setLayout (new GridLayout (4,3)); cp.add (b1); cp.add (b2); cp.add (b3); cp.add (b4); cp.add (b5); cp.add (b6); cp.add (b7); 15 java.awt.GridLayout (3/3) ... Container cp = getContentPane (); cp.setLayout (new GridLayout (0,3)); cp.add (b1); Watch out! cp.add (b2); cp.add (b3); cp.add (b4); cp.add (b5); cp.add (b6); cp.add (b7); Another constructor exists: GridLayout(int rows, int cols, int hgap, int vgap) 16 A container example (1/2) 17 A container example (2/2) Rescaled By default (300 x 300 size) 18 Changing a container (changing background color of its buttons; adding a new button) static void chgCont(Component comp) { Container cont = comp.getParent(); // cont is comp’s parent in the component hierarchy Component[] c = cont.getComponents(); for (int i = 0; i<c.length; i++) { Color back = c[i].getBackground(); if (c[i] == comp) c[i].setBackground(back.brighter()); else c[i].setBackground(back.darker()): } LayoutManager lm = cont.getLayout(); if (lm instanceof FlowLayout) cont.add(new Button("New button")); cont.validate(); // necessary after adding smth (refresh) } 19 A ScrollPane example import java.awt.*; class Sptest extends Frame { public static void main(String args[]){ new Sptest(); } Sptest() { ScrollPane sp = new ScrollPane(); Panel p = new Panel(new GridLayout(0,1)); for (int i= 1; i <= 20; i++) { Button b=new Button("Very long button #" + i); b.setFont(new Font("Dialog", Font.BOLD, 24)); b.setForeground(Color.blue); b.setBackground(new Color(255,255,220)); p.add(b); } sp.setSize(150, 300); sp.add(p); add(sp); pack(); show(); } 20 } Menus [ http://www.eng.auburn.edu/~rayh/java/java/AWT.Introduction.html ] The following classes are related to menus: • MenuComponent • MenuBar • MenuItem • CheckboxMenuItem • Menu To use menus you need to create a MenuBar and Menus with MenuItems, then attach the MenuBar to your application via setMenuBar. You can even embed, Menus in MenuItems... 21 AWT menus are NOT descendants of the Component class! java.lang.Object | +--java.awt.MenuComponent | | | | java.awt.MenuItem java.awt.MenuBar | | | | java.awt.Menu java.awt.CheckBoxMenuItem 22 Menu example [ http://www.eng.auburn.edu/~rayh/java/java/AWT.Introduction.html ] MenuBar mb = new MenuBar(); Menu top = new Menu("File"); Menu sub = new Menu("New"); sub.add(new MenuItem("Document")); sub.add(new MenuItem("Message")); sub.add(new MenuItem("Image")); top.add(sub); top.add(new MenuItem("Open")); top.add(new MenuItem("Save")); setMenuBar(mb); 23 Selected methods of the Menu class add(MenuItem mi) Adds element mi at the end of the menu add(String s) Adds a new element with label s at the end of the menu insert(String s, int pos) Inserts an element with label s at position pos insert(MenuItem mi, int pos) Inserts a given menu item at position pos addSeparator() Adds a separator insertSeparator(int pos) Inserts separator at position pos int getItemCount() Return the # of elems in the menu MenuItem getItem(int pos) Returns the element as position pos remove(int pos) Removes the element at position pos remove(MenuComponent menucomp) Removes the pointed element removeAll() No comment. 24 Basics of event handling In GUI apps, the interaction with users is event-driven. Events are: mouse clicks, keystrokes, moving mouse over some object (button, text field) etc. etc. Any object can be notified of the event. All the object has to do is implement the appropriate interface and be registered as an event listener on the appropriate event source. 25 Basics of event handling, cont’d ([java.sun.com]) Every event handler requires three pieces of code: 1. In the declaration for the event handler class, one line of code specifies that the class either implements a listener interface or extends a class that implements a listener interface. For example: public class MyClass implements ActionListener { ... } 2. Another line of code registers an instance of the event handler class as a listener on one or more components. For example: someComponent.addActionListener(instanceOfMyClass); 3. The event handler class has code that implements the methods in the listener interface. For example: public void actionPerformed(ActionEvent e) { ... // code that reacts to the action... } 26 Listeners, simple example (1/2) ([Barteczko’00]) 27 Listeners, simple example (2/2) ([Barteczko’00]) 28 Inner classes [ http://builder.com.com/5100-6386-5035155.html , http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html ] An inner class is a class declared inside another class. Starting with Java 1.1, you can declare a class inside another, much like you declare fields and methods. The class that encloses the declaration of the inner class is called the outer class. Inner classes are used primarily to implement helper classes. You can declare an inner class within the body of a method (this is called a local inner class). Can also declare an inner class within the body of a method without naming it (anonymous inner classes). 29 Inner class example (1 / 3) [ http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html ] 30 Inner class example (2 / 3) [ http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html ] 31 Inner class example (3 / 3) [ http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html ] Output: 0, 2, 4, ..., 26 32 Closing an AWT window (and more...) All that is pretty boring, isn’t it? 33 Using adapters Implementing WindowListener, MouseListener etc. inferfaces required in human-interactive applications may be tedious. We often don’t need to implement all the required methods. Hence – null (empty) methods (see slide 2). A solution we know is to create an adapter (with null methods only) and extend it in our class. This is often unacceptable since then we cannot extend any other class! Anything better? 34 Anonymous classes [ http://cs.nyu.edu/~yap/classes/visual/03s/lect/l7/prog/ EmptyFrame1.java ] Java provides the class WindowAdapter (java.awt.event.*) which implements WindowListener with all 7 methods defaulted to the null implementation. But extending WindowAdapter still doesn’t solve the problem (of course). So we are going to implement an anonymous extension of WindowAdapter(). .... addWindowListener ( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } The parameter for method }); addWindowListener() is an object of a class 35 implementing WindowAdapter. Anonymous classes, more notes [ http://mindprod.com/jgloss/anonymousclasses.html ] You define it, and create an object of that type as a parameter all in one line. In other words, an anonymous class is defined by a Java expression, not a Java statement. Syntax a bit strange: no class or any other keyword (e.g. extends). You can refer to this of the outer class via MyOuterClass.this. You can refer to the outer class’s methods by myOuterInstanceMethod() or MyOuterClass.this.myOuterInstanceMethod(). Objects of anonymous classes have access to final local variables that are declared within the scope of the anonymous class. Unlike a local class, an anonymous class cannot have a constructor. 36 Actions (note: this is Swing!) Often same action (command) may be executed in a number of ways: a keystroke, click on a button, selecting a menu entry, etc. Swing provides the Action interface to handle multiple event sources. An action is an object which stores • a description of the command (as a text string), • necessary parameters. Action has several methods, but we’re most often satisfied with overriding only one: actionPerformed, inherited from java.awt.event.ActionListener. 37 Actions, cont’d Fortunately, there exists an abstract class AbstractAction which provides default implementions for the Action interface. Only actionPeformed needs to be defined. 38 Adding actions to menu items (1/2) 39 Adding actions to menu items (2/2) 40 Now we re-use the action threeTimesThree (code from prev slides modified) 41 Applets – basics As opposed to stand-alone apps, applets don’t have main() function. You can run an applet in a web browser or using Java appletviewer.exe (html document with a reference to a .class file). Executed in a sandbox – cannot access local data, e.g. write on disk. However, applets can e.g. invoke the public methods of other applets on the same page. An applet is displayed on the web page by making use of the deprecated applet html element, or the recommended object element. A Java applet extends the class java.applet.Applet, or in the case of a Swing applet, javax.swing.Japplet. 42 Sandbox – what it means [Core Java, vol. I, Chap. 10] 1. Programs in a sandbox cannot run any local executable file. 2. They cannot read / write local data (access local file system). 3. Cannot find out any info about the local machine, with a few harmless exceptions (like JVM version). 4. "Remote code can only phone home" = they can’t communicate with hosts other than the server they were downloaded from. 5. All popup windows carry a warning message. 43 Debugging an applet (harder than it seems...) [Core Java, vol. I, Chap. 10] We modify an applet (e.g. fix a bug). We reload (=refresh) the html page in a browser and... nothing. We have to re-open the browser... Fortunately, there is a faster way. Launch Java console from the browser and type command x, to clear the classloader cache. E.g. in Opera this is: Tools / Advanced / Java Console 44 A very simple applet import java.awt.*; import java.applet.*; public class RectApplet extends Applet { public void paint(Graphics g) { g.drawRect(35, 15, 125, 200); g.fillRoundRect(50, 30, 95, 170, 15, 15); } } Method paint() (defined by the AWT Component class) is called every time the applet’s output must be redrawn: the window in which the applet is running may be overwritten and then uncovered, the applet window was resized, etc. 45 HTML document for RectApplet [ http://docs.rinet.ru/KofeynyyPrimer/ch16.htm ] <title>Applet Test Page</title> <h1>Applet Test Page</h1> <applet code="RectApplet.class" width=200 height=250 name="RectApplet"> </applet> Every applet has an area of the screen (canvas), in which it displays. The canvas size depends on the size of the applet, which is in turn controlled by the parameters in the <applet> tag in the HTML doc. The larger the applet appears in the HTML, the larger the applet's visible canvas. Anything that you try to draw outside of the visible canvas doesn’t appear on the screen. 46 How the web browser controls an applet’s execution [ http://www.irt.org/articles/js070/index.htm ] Four methods defined in Applet class: init() start() stop() destroy(). Default implementations are provided. When an applet begins the AWT calls the following methods in this sequence: init(), start(), paint(). When an applet dies (or is terminated), the following sequence of method calls takes place: stop(), destroy(). 47 init, start, stop [ http://www.irt.org/articles/js070/index.htm ] Method init() called only once during the runtime of your applet. Serves e.g. for initializing variables. public void init() { setBackground(Color.yellow); setForeground(Color.blue); msg= "Inside init() – "; } start() called just after init(). Also called to restart an applet after it has been stopped. If a user leaves a web page, the applet calls stop(). When the user comes back, the applet resumes execution at start(). 48 Calling applets from a HTML doc [ http://www.cafeaulait.org/course/week5/ ] <applet code="HelloWorldApplet" name="Applet1" codebase="http://www.somepage.com/classes" width="200" height="200" align="right" hspace="5" vspace="10" alt="Some applet"><p>Sorry, I’m an ancient browser.</p></applet> Applet element attributes: codebase (optional): path (may be relative – to the location of the source document) to the .class file width, height (required): applet box dimensions align (optional): how the applet’s rectangle is placed on the page relative to other element (left, right, top, baseline...) hspace, vspace (optional): amount of blank space (in pix) between an applet and the surrounding text alt (optional): alternative text, used when Java turned off in a browser. 49 Converting desktop apps to applets [Core Java, vol. I, Chap. 10] 1. 2. 3. 4. 5. 6. 7. 8. Generate an appropriate HTML file. Sub-class JApplet (or Applet), make it public. Remove main(). Don’t construct a frame window. Initialization stuff – from the frame’s constructor to applet’s init() method. Remove setSize() calls. Remove setDefaultCloseOperation() (slide 70) – an applet cannot be closed! Remove setTitle(). Don’t call setVisible(true) – applets are displayed automatically. 50 Passing parameters to applets [Core Java, vol. I, Chap. 10] An analogy to cmd-line params: let the applet code make use of parameter specified in the surrounding HTML. Solution: use HTML tag <param ... /> with name and value attributes. In HTML: <applet ... > <param name="font" value="Helvetica"/> </applet> In Java code (getParameter(...) from Applet class), only in init(): ... String fontName = getParameter("Font"); // case-insensitive! 51 Drawing methods [ http://docs.rinet.ru/KofeynyyPrimer/ch16.htm ] (0,0) coordinates: upper-left corner For drawing, use: import java.awt. Graphics; 52 Reading mouse position in an applet box [ ftp://ftp.helion.pl/przyklady/cwjava.zip, exercise 8.2 ] MouseMotionListener! 53 Simple JApplet (adding 2 floating-point numbers) [ http://cs.fit.edu/~mmahoney/cis5100/ ] 54 Adding 2 floating-point numbers, cont’d 55 Sound in Java applets and applications Possible since Java 1.3. Formats AIFF, AU, WAV and MIDI handled. Applet class implements the interface AudioClip, with the following methods defined: • loop() – starts playing the audio clip in a loop • play() – starts playing the audio clip • stop() – stops playing the audio clip The Applet class also defines two play() methods: • play (URL url) • play(URL url, String filename) 56 Playing a wave file [ ftp://ftp.helion.pl/przyklady/cwjava.zip, chapter 6 ] Works if pinkpanther.au in the same dir as Sound.class. Exercise: eliminate that clutter... 57 Playing a wave if some rectangle is clicked (1/2) getX(), getWidth() etc. from class Rectangle return a double. 58 Playing a wave if some rectangle is clicked (2/2) Play one sound or another, depending on which rectangle is clicked. mousePressed – true when a mouse button has been pressed mouseClicked – when a mouse button has been pressed and released. Not a click if the mouse moved before releasing the button! 59 Rectangle class, some notes java.awt.Rectangle represents an area in the coordinate space. We can set negative width and height (!) but it means the rectangle is empty (and its method isEmpty() returns true). The behavior of methods that operate on more than one Rectangle is undefined if any of the participating Rectangle objects has a negative width or height. These methods include intersects, intersection and union. BEWARE! public Rectangle union(Rectangle r) – returns the smallest Rectangle containing both r and this Rectangle. So, THIS IS NOT A UNION IN THE MATHEMATICAL SENSE! 60 Drawing circles with a click [ ftp://ftp.helion.pl/przyklady/cwjava.zip, chapter 8 ] What’s wrong with this applet? No paint() method. Very easy to “lose” the screen content. 61 Drawing circles in a slightly more refined way. Still no paint()! 62 OK, we’ll use paint(). But how? Smth has covered our window for a while, how to know where were the circles (or know other parameters if variable, like radii and colors) to refresh (repaint)? Solution: keep them in an array (even better, use some JFC collection). Let's also add random colors to the circles (but fixed radii like in the 1st code variant). 63 Circles3 [ ftp://ftp.helion.pl/przyklady/cwjava.zip, chapter 8 ] 64 Circles3, cont’d [ ftp://ftp.helion.pl/przyklady/cwjava.zip, chapter 8 ] 65 Swing: an overview [ http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/ ] • Lightweight. Not built on native window-system windows. • Large set of built-in controls. Trees, image buttons, tabbed panes, sliders, toolbars, color choosers, tables, text areas to display HTML or RTF, etc. • Customizable. Can change border, text alignment, or add image to almost any control. Can customize how minor features are drawn. Can separate internal representation from visual appearance. • “Pluggable” look and feel. Can change look and feel at runtime, or design own look and feel. • Many new features not available in AWT: tool tips, dockable tool bars, keyboard accelerators, custom cursors, etc. 66 Swing: an overview, cont’d [ http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/ ] import javax.swing.*; GUI stuff is supposed to be hard. It builds character. Component names start with ‘J’ / Jim Ahlstrom / (JFrame, JPanel, JApplet, JDialog, JButton...) Do drawing with paintComponent, not paint. Instead of adding components directly to frames or applets, use the content pane: • add to content pane via getContentPane().add • replace content pane via setContentPane Mixing AWT and Swing is evil! AWT components are always on top, and z-ordering problems catch you in many unexpected ways. Stick with the AWT or move completely to Swing. 67 JFrame [ http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/ ] Starting point for graphical applications. One of few Swing components that is built on an underlying “heavyweight” window. JFrames close automatically when you click on the close button (unlike AWT Frames). However, closing the last JFrame does not result in your program exiting Java. So your “main” JFrame still needs a WindowListener. 68 Source code for the JFrame from the prev. picture [ http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/ ] 69 Closing a JFrame [ http://www.tutorialized.com/tutorial/ Exiting-an-Application-when-a-JFrame-is-Closed/12816 ] Default behavior: hide the window when the user clicks on the close box. There are four different actions that can be performed when the window is closed. These actions are defined in the interface javax.swing.WindowConstants which is implemented by JFrame. • DISPOSE_ON_CLOSE - Dispose the window when closed. • DO_NOTHING_ON_CLOSE - Do nothing when the window is closed. • EXIT_ON_CLOSE - Exit the application when the window is closed. • HIDE_ON_CLOSE - Hide the window when the window is closed. Example on how to change the default close action: JFrame myFrame = new JFrame(); myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 70