330 likes | 440 Views
Creating GUIs in Java using Swing. Medialogy, Semester 7, 2010 Aalborg University, Aalborg http://mea.create.aau.dk/course/view.php?id=26 David Meredith dave@create.aau.dk. Resources. The Sun Java Tutorial on “Creating a GUI with JFC/Swing”, available here:
E N D
Creating GUIs in Java using Swing Medialogy, Semester 7, 2010 Aalborg University, Aalborg http://mea.create.aau.dk/course/view.php?id=26 David Meredith dave@create.aau.dk
Resources • The Sun Java Tutorial on “Creating a GUI with JFC/Swing”, available here: http://java.sun.com/docs/books/tutorial/uiswing/index.html
Java Foundation Classes (JFC) • JFC is a group of Java packages for • building GUIs • adding rich graphics • adding interactivity • JFC defined to provide the following features: • Swing GUI Components • From buttons to split panes and tables • Components capable of sorting, printing, drag-and-drop, etc. • Pluggable look-and-feel Support • So the same program can use different look-and-feels (e.g., Java look, Windows look, GTK+ and many more) • Accessibility API • Enables assistive technologies like screen readers and Braille displays to get information from the UI • Java 2D API • Enables easy incorporation of high-quality 2D graphics, text, and images in applications and applets. Java 2D includes extensive APIs for generating and sending high-quality output to printing devices. • Internationalization • Allows developers to build applications that interact with users using many different languages and alphabets
Swing packages • Swing API has 18 packages: • javax.swing • javax.swing.event • javax.swing.plaf • javax.swing.text • ... • Most of the time we use only two: • javax.swing • javax.swing.event
Concurrency in Swing • In Swing, you use three different kinds of thread • Initial threads • In a normal application, there will be only one initial thread: the main thread • Event dispatch thread • Most code that interacts with the Swing framework executes on this thread • Worker threads • “Background” threads on which time-consuming tasks are executed • You don’t need to create these threads explicitly • They are provided by the runtime or the Swing framework
Initial threads • In Swing, initial thread (main thread) usually just creates a Runnable object (the GUI) which is passed to the event dispatch thread to be executed • Once the GUI is running, GUI events cause short tasks to be carried out on the event dispatch thread • Longer tasks should be scheduled for execution on Worker threads
invokeLater • Main thread schedules the GUI creation task by invoking javax.swing.SwingUtilities.invokeLater • This takes a single Runnable object as its argument and schedules it to be executed on the event dispatch thread • Can also use invokeAndWait (synchronous) • Main thread does not create and run the GUI itself because almost all code that interacts with Swing must run on the event dispatch thread
The event dispatch thread • Event handling code is code that is executed when some GUI event occurs (e.g., the user clicks a button or moves a slider) • All event handling code in Swing must run on the event dispatch thread • Most code that calls Swing methods should also run on the event dispatch thread • This is because most Swing object methods are not thread safe • Invoking these methods from different threads can lead to interference • Think of the code running on the event dispatch thread as a series of short tasks, most of which are carried out in response to GUI events • If longer events are run on the event dispatch thread, unhandled GUI events build up and the interface becomes unresponsive
HelloWorld in Swing • Use invokeLater to create a Runnable to be executed on the event dispatch thread • The run method starts by creating a JFrame object which is the main window of the application (l.10) • Set the default close operation to be “EXIT_ON_CLOSE” which means the app exits when the close button is pressed (l.11) • Create a label object containing the “Hello World” message (l.12) • We get the content pane for the JFrame object and put the label in it (l.13) • The content pane contains all the Swing components for a JFrame • We invoke the “pack” method on the JFrame to set the size of the window so that it is just big enough to hold all the components in the content pane (l.14) • We make the JFrame visible (l.15)
A visual index to the Swing components http://java.sun.com/docs/books/tutorial/ui/features/components.html
JFrame • The main window of the application is a JFrame object • A JFrame contains a JRootPane object • The JRootPane object contains • a Container object called contentPane and • a JMenuBar object called menuBar • All the components in a window (e.g., buttons, text fields, labels, sliders) but not the menubar must be contained in the JFrame’s contentPane • The window’s menubar is stored separately in the menuBar object • The menuBar field of a JFrame can be null • menu bars are optional • The contentPane field of a JFrame cannot be null • throws an exception
Accessing the content pane of a JFrame • To retrieve the content pane of a JFrame: frame.getContentPane(); • To add a component to the content pane: frame.getContentPane().add(yellowLabel); • To remove a component from the content pane: frame.getContentPane().remove(yellowLabel);
Layout managers • A layout manager is an object that implements the LayoutManager interface • Determines size and position of components within a container • Each component can request to have a certain size and alignment • But layout manager has final say • The only containers with layout managers that you need to worry about are content panes and JPanels • A JPanel is simply a rectangular region within a window’s content pane into which you can put Swing components, just as you would put them into a content pane • It’s a region of the window where you can control layout independently from the rest of the window
A Visual Guide to Layout Managers http://java.sun.com/docs/books/tutorial/uiswing/layout/visual.html
BorderLayout • See BorderLayoutDemo.java • Add components using pane.add(new JLabel(“Hello”), BorderLayout.PAGE_START) • Gaps between areas can be specified using layout.setVgap() and layout.setHgap() • Can leave regions empty • If try adding second component to a region, it replaces the first • Center region expands to fill space available • By default, components added to center region • i.e. as if with BorderLayout.CENTER
JPanels and FlowLayout • See FlowLayoutDemo.java • JPanel is a container that can be used inside another container such as a content pane • JPanel uses FlowLayout layout manager • Put a JPanel in one area of BorderLayout so that you can put more than one component into that area (by putting the components in the JPanel) • FlowLayout puts components in a row • If container is not wide enough, FlowLayout starts a new row • If container is more than wide enough, components are centered • Can change alignment using FlowLayout.setAlignment() • Change the padding using setHgap() and setVgap()
BoxLayout • See BoxLayoutDemo.java • BoxLayout stacks components on top of each other or places them in a row • To get them in a row, use panel1.setLayout(new BoxLayout(panel1, BoxLayout.X_AXIS)) • To get them in a column, use panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS)) • Like FlowLayout but with greater functionality
GroupLayout • GroupLayout developed for GUI builders like the one in NetBeans • But also works for manual coding of GUIs • Works with horizontal and vertical layouts separately • Can forget about horizontal layout when defining vertical and vice-versa • But need to define each component twice in the layout • If forget to define a component twice, GroupLayout generates an exception
Layout Organization in GroupLayout: Hierarchical Groups • GroupLayout uses two different types of groups, arranged into a hierarchy • Sequential groups • Components placed one after the other as in BoxLayout or FlowLayout • Parallel groups • Next to each other in the same dimension • Parallel group usually an element in a sequential group in the other dimension • A group may contain components or other groups
An example of GroupLayout • Layout three components in a row • Sequential horizontal group of 3 components • Parallel vertical group of the same 3 components with same (vertical) location, size and baseline In pseudo-code: horizontal_layout = sequential_group { c1, c2, c3 } vertical_layout = parallel_group (BASELINE) { c1, c2, c3 }
Another example of GroupLayout • C4 is left-aligned with C3 • C4 and C3 have the same horizontal position • C4 and C3 form a parallel horizontal group • Vertically, there is a sequential group consisting of the parallel group, {C1,C2,C3} followed by C4 In pseudo-code: horizontal_layout = sequential_group { c1, c2, parallel_group (LEFT) { c3, c4 } } vertical_layout = sequential_group { parallel_group (BASELINE) { c1, c2, c3 }, c4 }
Gaps in GroupLayout • Gap is an invisible component that controls distance between other components • GroupLayout defines automatic gaps • Give preferred distances between neighbouring components and between components and container borders • Size computed based on look-and-feel • Need to turn on automatic gaps using layout.setAutoCreateGaps(true); layout.setAutoCreateContainerGaps(true);
Writing code in GroupLayout • See GroupLayoutDemo.java
Convert.java • Convert class extends JFrame • run() method in GUI runnable simply instantiates the Convert class • components stored as instance variables in the Convert class • GUI created and shown in the Convert constructor • uses GroupLayout as the LayoutManager • layout.linkSize(Components... ) method used to make sizes of text field, fahrenheit value label and button the same
Convert.java • When button clicked, emits an ActionEvent that will be responded to by any object that • implements the ActionListener interface • has to implement the ActionPerformed method • is registered as a listener with the button • using button.addActionListener(listenerObject) • When press enter in the text field, also generates an ActionEvent which will be responded to by an ActionEventListener that is registered with the text field • using textField.addActionListener(listenerObject) • uses java.awt.Frame.setResizable(boolean resizable) to define window to be not resizable • See Convert.java
SquareSliders.java • Again, run() method of GUI Runnable simply instantiates the SquareSliders class which extends JFrame • All GUI setup done in SquareSliders constructor • Components stored as instance variables in SquareSliders object so that they can be accessed by event handlers defined in inner Event Listener classes • Two ChangeListeners required – one for each slider, because effect of moving one slider is different from effect of moving the other one • implies different listeners must be registered with the different sliders • See SquareSliders.java
Menus • Menus aren’t placed with the other components in the UI • either in the menu bar or popup menu • Menubar usually across the top of the main window • though in Mac OS X, it’s across the top of the screen • Popup menus are invisible until user makes a platform-specific mouse action (e.g., right-click) • MenuLookDemo has • a menu bar, menus, menu items, radio button menu items, checkbox menu items and separators • Menu item can have image, text or both • Can also specify font and colour
Menu Component Hierarchy • Menu items (JMenuItem) and menus (JMenu) are buttons • When a menu item is pressed, it brings up a popup menu (JPopupMenu) which contains the menu’s menu items
Creating Menus • See createMenuBar method in MenuLookDemo.java • To set menu bar for a JFrame, use frame.setJMenuBar(menuBar) • To add a JMenu to a JMenuBar, use menuBar.add(menu) • To add a JMenuItem to a JMenu, use menu.add(menuItem) • We’ll deal later with setAccelerator, setMnemonic and setAccessibleDescription
Handling Events from Menu Items • To detect when a user selects a JMenuItem, need to listen for action events (just as for a JButton), so register with an ActionListener: menuItem.addActionListener(this) • define an actionPerformed method • JRadioButtonMenuItems emit either action events or item events • have to register with an ActionListener: rbMenuItem.addActionListener(this) • add an actionPerformed method • JCheckBoxMenuItems emit item events • have to register with an ItemListener: cbMenuItem.addItemListener(this) • need to define an itemStateChanged method • See MenuDemo.java
Enabling Keyboard Operation • Menus can use mnemonics and accelerators • Mnemonics are usually single letter abbreviations for a menu item (e.g., “A” for the “Save As” menu item in the File menu), • accessible only from within the menu hierarchy • Accelerators are keyboard shortcuts that bypass the menu hierarchy • allows access to menu item even if not visible (e.g., Ctrl-F for the Find dialog) • Specify mnemonic either in constructor: menuItem = new JMenuItem(“Save As...”,KeyEvent.VK_A); • or using setMnemonic method: menuItem.setMnemonic(KeyEvent.VK_A); • Specify accelerator using setAccelerator method: menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK); • KeyEvent constant is a constant corresponding to a particular key (just static variables in the KeyEvent class) • Modifier key required for accelerator specified using a constant defined in ActionEvent class