260 likes | 584 Views
Swing: the art of the GUI. COMP204, Bernhard Pfahringer. Swing. Swing is very powerful, but also complex built on top of AWT Swing classes start with J.., e.g. JFrame need (at least): import javax.swing.*;
E N D
Swing: the art of the GUI COMP204, Bernhard Pfahringer
Swing • Swing is very powerful, but also complex • built on top of AWT • Swing classes start with J.., e.g. JFrame • need (at least): import javax.swing.*; • often Swing classes are subclasses of AWT classes, e.g. javax.swing JFrame extends java.awt.Frame • Swing GUIs use double-buffering (default) => no flickering • GUI elements are either: • Objects with specific function (e.g. JButton) • Containers for GUI elements (e.g. JFrame)
Generic GUI app (composition) • Swing is NOT thread-safe, for efficiency reasons (see link on web-page for more details) • Need to be careful: public static void main (String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { new GUIClass().createAndShowGUI(); } });
cont. public void createAndShowGUI() { _frame = new JFrame(”Title"); // make sure closing exits _frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // // … more setup code // _frame.pack(); _frame.setVisible(true); }
Updating the display • Whenever something changes (e.g. text of a JLabel), need to call repaint() • NEVER call paint directly • Event handling thread queues repaint() request, will fuse multiple calls on the same object into one, and eventually call paint • All Components have appropriate paint methods, but you can do your own, if you need (e.g. animation, see code example) public void paint(Graphics g) { g.setColor(_color); g.fillOval(_x-_radius,_y-_radius,2*_radius,2*_radius); }
LayoutManager Container classes need to know where elements go to on the screen: Container content = getContentPane(); LayoutManager layout = new GridLayout(3, 2); content.setLayout(layout); _celsiusLabel = new JLabel("Celsius"); content.add(_celsiusLabel); Typical: BorderLayout, FlowLayout, BoxLayout, CardLayout, GridBagLayout, … see JavaDoc for details, and others
Buttons and ActionListeners Specify interaction by attaching Listeners to GUI objects JButton b = new JButton(“do it!”); b.addActionListener(new DoIt()); … private class DoIt implements ActionListener { public void actionPerformed( ActionEvent e) { // whatever } }
Alternative: inheritance + interface implementation in one go private class ColorButton extends JButton implements ActionListener { private Color c; public ColorButton(Color c1, String name) { super(name); c = c1; addActionListener(this); // OURSELVES !!! } public void actionPerformed(ActionEvent e) { setFromColor(c); } }
Abstract class: ButtonAdapter abstract class ButtonAdapter extends Jbutton implements ActionListener { public ButtonAdapter(String name) { super(name); addActionListener(this); } public void actionPerformed(ActionEvent e) { pressed(); } public abstract void pressed(); }
Usage Use with anonymous class: JPanel p = new JPanel(); p.add(new ButtonAdapter(“Quit”) { public void pressed() { System.exit(0); } } );
MouseListener Interface Five events: mousePressed(MouseEvent e) mouseReleased(..) mouseClicked(..) mouseEntered(..) mouseExited(..) tedious to implement all when only one is needed: instead subclass abstract MouseAdapter see also: MouseMotionListener http://java.sun.com/docs/books/tutorial/uiswing/events/mouselistener.html
Animations: javax.swing.Timer ActionListener incrementYPosition = new ActionListener() { public void actionPerformed(ActionEvent evt) { if (_y < 400) { _y++; if (_frame != null) _frame.repaint(); } else { _timer.stop(); } } }; _timer = new javax.swing.Timer(10,incrementYPosition); _timer.start();
Safe loading of an ImageIcon /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL = ButtonDemo.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: " + path); return null; } }
ButtonDemo action method public void actionPerformed(ActionEvent e) { if ("disable".equals(e.getActionCommand())) { b2.setEnabled(false); b1.setEnabled(false); b3.setEnabled(true); } else { b2.setEnabled(true); b1.setEnabled(true); b3.setEnabled(false); } }
Setting up a button b1 = new JButton("Disable middle button", leftButtonIcon); b1.setVerticalTextPosition(AbstractButton.CENTER); //aka LEFT, for left-to-right locales b1.setHorizontalTextPosition(AbstractButton.LEADING) b1.setMnemonic(KeyEvent.VK_D); b1.setActionCommand("disable"); b1.addActionListener(this); b1.setToolTipText("Click this button to disable the middle button.");
JCheckbox • Maintain/display labeled binary state (on/off, yes/no, selected/unselected) • getLabel(), setLabel(String), isSelected(), setSelected() • also: an ItemListener for an ItemEvent
Trivial example import javax.swing.*; import java.awt.*; import java.awt.event.*; public class CheckBoxTest extends JFrame { private JCheckBox cb = new JCheckBox("off"); public static void main(String[] args) { CheckBoxTest w = new CheckBoxTest(); w.show(); }
cont. public CheckBoxTest() { setTitle("CheckBoxTest"); setSize(300,70); cb.addItemListener(new CheckBoxTestListener()); add("Center", cb); } private class CheckBoxTestListener implements ItemListener { public void itemStateChanged(ItemEvent e) { cb.setLabel( (cb.isSelected()) ? "ON" : "OFF"); } }
RadioButtonDemo public class RadioButtonDemo extends JPanel implements ActionListener { static String birdString = "Bird"; …. JRadioButton birdButton = new JRadioButton(birdString); birdButton.setMnemonic(KeyEvent.VK_B); birdButton.setActionCommand(birdString); birdButton.setSelected(true); .... ButtonGroup group = new ButtonGroup(); group.add(birdButton); group.add(catButton); …
cont. birdButton.addActionListener(this); … JPanel radioPanel = new JPanel(new GridLayout(0, 1)); radioPanel.add(birdButton); … add(radioPanel, BorderLayout.LINE_START); add(picture, BorderLayout.CENTER); setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); public void actionPerformed(ActionEvent e) { picture.setIcon(createImageIcon("images/" + e.getActionCommand() + ".gif")); }
Dialogs • Special purpose window displayed shortly • To notify, or ask simple questions • Always attached to a Frame • Modal: demands user response, prevents further actions; show() won’t return until dismissed, setVisible(false) • Nonmodal: actions often placed into separate Thread Dialog dig = new Dialog(this,false);
Dialog example public class DialogTest extends JFrame { public static void main(String[] args) { DialogTest w = new DialogTest(); w.show(); } private JTextArea d = new JTextArea(); private JCheckBox cb = new JCheckBox("Modal Dialog?"); public DialogTest() { setTitle("DialogTest"); setSize(300,220); add("West",cb); add("East",new MakeButton()); add("South",d); }
cont private void makeDialog(boolean modalFlag) { final JDialog dialog = new JDialog(this,modalFlag); dialog.setSize(100,100); dialog.add("North",new CountButton(1)); dialog.add("West",new CountButton(2)); dialog.add("East",new CountButton(3)); dialog.add("South", new ButtonAdapter("Hide") { public void pressed() { dialog.setVisible(false); } }); dialog.show(); }
cont. private class MakeButton extends ButtonAdapter { public MakeButton() { super("Make Dialog"); } public void pressed() { makeDialog(cb.isSelected()); } } private class CountButton extends ButtonAdapter { public CountButton(int value) { super("" + value); } public void pressed() { d.append("Button " + getLabel() + " pressed\n"); } } }
JFileChooser import javax.swing.filechooser.*; fc = new JFileChooser(); public void actionPerformed(ActionEvent e) { if (e.getSource() == openButton) { int returnVal = fc.showOpenDialog(FileChooserDemo.this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); // … This is where a real application would open the file. log.append("Opening: " + file.getName() + "." + newline); } else { log.append("Open command cancelled by user." + newline); } log.setCaretPosition(log.getDocument().getLength());
JMenuBar • Attached to JFrame by setJMenuBar(): JMenuBar bar = new JMenuBar(); setJMenuBar(bar); • Add menus: JMenu HelpMenu = new JMenu(“Help”); bar.add(helpMenu); • Add menu items: JMenuItem quitItem = new JMenuItem(“Quit”); quitItem.addActionListener(new QuitListener()); helpMenu.add(quitItem);