200 likes | 321 Views
More Swing Widgets and Listeners. Joel Adams and Jeremy Frens Calvin College. Review: Widgets & Events. Component. java.util.EventObject. Container. java.awt.AWTEvent. javax.swing.ChangeEvent. JComponent. java.awt.event.ActionEvent. AbstractButton. JButton.
E N D
More Swing Widgetsand Listeners Joel Adams and Jeremy Frens Calvin College
Review: Widgets & Events Component java.util.EventObject Container java.awt.AWTEvent javax.swing.ChangeEvent JComponent java.awt.event.ActionEvent AbstractButton JButton • Almost everything in Java is-an Object… Object • When the user interacts with a Java widget, the JRE generates an event…
Review: Java User Interface Widgets Object Component … Button Canvas Checkbox Container Scrollbar … JComponent Panel ScrollPane Window … AbstractButton JFile Chooser JLabel JPanel JScrollPane JTabbedPane JButton • Original Java had the awt package of user-interface widgets: • Java 1.2 added the swing package of lighter-weight widgets
Review: MVC JFrame Listener Object View Model Controller Viewi Controlleri • Java encourages UI designers to use the MVC design pattern, in which: • The application’s core functionality is isolated in a model class: • The application’s user-interface is isolated in a view class: • The application’s control is isolated in a controller class: • This pattern lets you modify the UI (or add additional ones) without touching the app’s core functionality.
Listeners Events Widgets • Swing provides many widgets, that trigger various events • Listener Event Widgets • ActionListener ActionEvent JButton • JComboBox • JTextField • JCheckBox • JRadioButton • JMenu • AdjustmentListener AdjustmentEvent JScrollbar • ChangeListener ChangeEvent JSlider • KeyListener KeyEvent keyboard • MouseListener MouseEvent mouse • MouseMotionListener MouseEvent mouse
Inner Classes • It is sometimes convenient to nest a class within a class: • public class OuterClass { • // instance variables • // methods • // etc. • } • private class InnerClass { • // instance variables • // methods • // etc. • } • The inner class is another attribute of the class (and so is usually declared private). • It can access any of the attributes of the outer class!
Inner Classes: Example • A GUI can define inner classes for its widgets’ listeners: • public class ListenersExample1 extends JFrame { • private JComboBox myBox; // generates ActionEvents • private JSlider mySlider; // generates ChangeEvents • ... • } • myBox.addActionListener( new BoxListener() ); • mySlider.addChangeListener( new SliderListener() ); • ... • private class BoxListener implements ActionListener { • public BoxListener() {} • public void actionPerformed(ActionEvent ae) { ... } • } • private class SliderListener implements ChangeListener { • public SliderListener() {} • public void stateChanged(ChangeEvent ce) { ... } • }
Exercise: Part I • Take a few minutes to work through part I of today’s exercise.
Anonymous Inner Classes • Unlike C++, Java lets you create anonymous inner classes: • public class ListenersExample1 extends JFrame { • private JComboBox myBox; // generates ActionEvents • private JSlider mySlider; // generates ChangeEvents • ... • } • myBox.addActionListener( new ActionListener() { • public void actionPerformed(ActionEvent ae) { ... } • } ); • mySlider.addChangeListener(new ChangeListener() { • public void stateChanged(ChangeEvent ce) { ... } • } ); • ... • Each anonymous inner class defines the method needed to implement the listener-interface needed by that widget.
Anonymous Inner Class Pattern • The pattern for an anonymous inner class declaration is: • new SuperType ( SuperTypeConstructorParameters ) { • // inner class methods, attributes, etc. • } • If SuperType is an interface, then the anonymous class implements that interface. • If SuperType is an existing class, then the anonymous class extends that class: • Employee e1 = new Employee("John"), // normal • e2 = new Employee("Jane") { ... }; // uh-oh • For readability: Use anonymous inner classes sparingly…
Exercise: Part II • Take a few minutes to work through part II of today’s exercise.
Example: SliderExample SliderExample To change my background, use the sliders below: R G B • Let’s build a GUI application with three color-control sliders: • We will need: • A JFrame • Several JLabels • Three JSliders • Some JPanels (one per label+slider) • Since there is not much in the way of a “core application”, we will build our model, view, and controller in 1 class…
Example: SliderExample (ii) • We start by defining our class and its attributes: • import javax.swing.*; // JLabel, JSlider, ... • import java.awt.*; // Color, GridLayout, ... • import javax.swing.event.*; • class SliderExampleA extends JFrame • implements ChangeListener { • private JLabel myLabel; • private JSlider myRedSlider, myGreenSlider, • myBlueSlider; • private JPanel myPane, myRedPanel, myGreenPanel, • myBluePanel; • private int myRed, myGreen, myBlue; • ...
Example: SliderExample (iii) • Next, its constructor: • public SliderExampleA() { • myPane = new JPanel( new GridLayout(4,1) ); • myLabel = new JLabel("<html>To change my background color," • + "<br/>use the RGB sliders below:</html>", • JLabel.CENTER); • myPane.add(myLabel); • ... • Note that we can use HTML to format the text in a JLabel, a JButton, and other Swing widgets
Example: SliderExample (iv) • // ... Continuation of constructor • myRedSlider = new JSlider(0, 255); • myRedPanel = buildAndAddPanel("R", myRedSlider); • myGreenSlider = new JSlider(0, 255); • myGreenPanel = buildAndAddPanel("G", myGreenSlider); • myBlueSlider = new JSlider(0, 255); • myBluePanel = buildAndAddPanel("B", myBlueSlider); • myRed = myGreen = myBlue = 255; • this.setContentPane(myPane); • this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • } • ...
Example: SliderExample (v) • ... • private JPanel buildAndAddPanel(String s, JSlider js) { • JPanel jp = new JPanel(); • JLabel aLabel = new JLabel(s, JLabel.RIGHT); • jp.add(aLabel); • js.setValue(255); • js.setPaintTicks(true); • js.setMajorTickSpacing(20); • js.setMinorTickSpacing(5); • js.addChangeListener(this); • jp.add(js); • myPane.add(jp); • return jp; • }
Example: SliderExample (vi) • We could define our slider-event-handler this way… • ... • public void stateChanged(ChangeEvent ce) { • Object es = ce.getSource(); • if (es instanceof JSlider) { • JSlider js = (JSlider) es; • if ( js == myRedSlider ) { // pointer comparison • myRed = myRedSlider.getValue(); • } else if ( js == myGreenSlider ) { • myGreen = myGreenSlider.getValue(); • } else if ( js == myBlueSlider ) { • myBlue = myBlueSlider.getValue(); • } else { • // ...error-handling code omitted here • myPane.setBackground( new Color(myRed, myGreen, myBlue) ); • }
Example: SliderExample (vii) • … but inner classes give us a cleaner way to do so (as we’ll see in the exercises). • Finally, we define our main() method: • ... • public static void main(String [] args) { • SliderExampleA gui = new SliderExampleA(); • gui.pack(); • gui.setVisible(true); • } • } // class SliderExampleA • … and we’re finished!
Summary • Java’s Swing package provides a wide variety of widgets. • Many widgets generate ActionEvents, which must be listened for with an ActionListener. • Some widgets generate different kinds of events, which must be listened for with different kinds of listeners. • Java’s inner classes are similar to C++ nested classes, but with more capabilities. • Unlike C++, Java supports anonymous inner classes that implement an interface or extend an existing class.
Exercise: Part III • Use the remaining time to work through part III of today’s exercise.