Hoofdstuk 14: Graphical User Interface Componenten: Deel 2 1 Inleiding Gevorderde GUI componenten Tekst gebieden Sliders Menu’s Multiple Document Interface (MDI) Gevorderde layoutmanagers BoxLayout GridBagLayout 2 2 JTextArea JTextArea Gebied voor het bewerken van diverse tekstlijnen Erft van JTextComponent 3 VB: Geselecteerde tekst uit een tekstgebied kopiëren naar een ander tekstgebied 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Fig. 14.1: TextAreaDemo.java // Copying selected text from one textarea to another. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class TextAreaDemo extends JFrame { private JTextArea textArea1, textArea2; private JButton copyButton; // set up GUI public TextAreaDemo() { super( "TextArea Demo" ); Maak een Box container voor het schikken van GUI componenten Box box = Box.createHorizontalBox(); String string = "This is a demo string to\n" + "illustrate copying text\nfrom one textarea to \n" + "another textarea using an\nexternal event\n"; // set up textArea1 textArea1 = new JTextArea( string, 10, 15 ); box.add( new JScrollPane( textArea1 ) ); Plaats een string in de JTextArea en voeg deze dan toe aan box 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 // set up copyButton copyButton = new JButton( "Copy >>>" ); box.add( copyButton ); copyButton.addActionListener( new ActionListener() { // anonymous inner class // set text in textArea2 to selected text from textArea1 public void actionPerformed( ActionEvent event ) { textArea2.setText( textArea1.getSelectedText() ); } } // end anonymous inner class ); // end call to addActionListener // set up textArea2 textArea2 = new JTextArea( 10, 15 ); textArea2.setEditable( false ); box.add( new JScrollPane( textArea2 ) ); // add box to content pane Container container = getContentPane(); container.add( box ); // place in BorderLayout.CENTER Wanneer de gebruiker de copyButton indrukt, wordt de geselecteerde tekst uit textArea1 gekopieerd naar textArea2 Maak een JTextArea die niet kan bewerkt worden 52 53 54 55 56 57 58 59 60 61 62 63 setSize( 425, 200 ); setVisible( true ); } // end constructor TextAreaDemo public static void main( String args[] ) { TextAreaDemo application = new TextAreaDemo(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class TextAreaDemo 3 Het maken van een aangepaste subklasse van JPanel “extends” JPanel om nieuwe componenten te maken Een specifiek en toepassingsgericht tekengebied Methode paintComponent van de klasse JComponent 8 VB: Het bouwen van een subklasse van JPanel aangepast aan de gebruiker 9 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // Fig. 14.2: CustomPanel.java // A customized JPanel class. import java.awt.*; import javax.swing.*; public class CustomPanel extends JPanel { public final static int CIRCLE = 1, SQUARE = 2; private int shape; // use shape to draw an oval or rectangle public void paintComponent( Graphics g ) { super.paintComponent( g ); Shape stelt de te tekenen vorm voor via een geheel getal Overschrijf de if ( shape == CIRCLE ) methode g.fillOval( 50, 10, 60, 60 ); paintComponent else if ( shape == SQUARE ) van class g.fillRect( 50, 10, 60, 60 ); JComponent om een } ovaal of een // set shape value and repaint CustomPanel rechthoek te tekenen public void draw( int shapeToDraw ) { shape = shapeToDraw; repaint(); } } // end class CustomPanel De methode repaint roept de methode paintComponent aan VB: Het gebruik van een subklasse van JPanel 11 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // Fig. 14.3: CustomPanelTest.java // Using a customized Panel object. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class CustomPanelTest extends JFrame { private JPanel buttonPanel; private CustomPanel myPanel; private JButton circleButton, squareButton; // set up GUI public CustomPanelTest() { super( "CustomPanel Test" ); // create custom drawing area myPanel = new CustomPanel(); myPanel.setBackground( Color.GREEN ); // set up squareButton squareButton = new JButton( "Square" ); squareButton.addActionListener( Maak een CustomPanel object en zet de achtergrond op groen 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 new ActionListener() { // anonymous inner class // draw a square public void actionPerformed( ActionEvent event ) { myPanel.draw( CustomPanel.SQUARE ); } } // end anonymous inner class ); // end call to addActionListener Wanneer de gebruiker squareButton indrukt, wordt een vierkant op CustomPanel getekend circleButton = new JButton( "Circle" ); circleButton.addActionListener( new ActionListener() { // anonymous inner class // draw a circle public void actionPerformed( ActionEvent event ) { myPanel.draw( CustomPanel.CIRCLE ); } } // end anonymous inner class ); // end call to addActionListener Wanneer de gebruiker circleButton indrukt, wordt een cirkel op CustomPanel getekend 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 // set up panel containing buttons buttonPanel = new JPanel(); buttonPanel.setLayout( new GridLayout( 1, 2 ) ); buttonPanel.add( circleButton ); buttonPanel.add( squareButton ); Gebruik GridLayout om buttons te organiseren // attach button panel & custom drawing area to content pane Container container = getContentPane(); container.add( myPanel, BorderLayout.CENTER ); container.add( buttonPanel, BorderLayout.SOUTH ); setSize( 300, 150 ); setVisible( true ); } // end constructor CustomPanelTest public static void main( String args[] ) { CustomPanelTest application = new CustomPanelTest(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class CustomPanelTest 4 Het maken van een SelfContained Subclass van JPanel JPanel Ondersteunt geen conventionele events In staat om lower-level events te herkennen Events met betrekking tot knoppen, tekstgebieden, enz. mouse events, key events, enz. Self-contained panel Luistert naar zijn eigen mouse events 15 VB Een self-contained JPanel klasse dat zijn eigen mouse events afhandelt 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // Fig. 14.4: SelfContainedPanel.java // A self-contained JPanel class that handles its own mouse events. package com.deitel.jhtp5.ch14; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SelfContainedPanel extends JPanel { private int x1, y1, x2, y2; // set up mouse event handling for SelfContainedPanel public SelfContainedPanel() { // set up mouse listener addMouseListener( Self-contained JPanel luistert naar MouseEvents new MouseAdapter() { // anonymous inner class // handle mouse press event public void mousePressed( MouseEvent event ) { x1 = event.getX(); y1 = event.getY(); } Bewaar coördinaten van de plaats waar de gebruiker de muisknop indrukt 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 // handle mouse release event public void mouseReleased( MouseEvent event ) { x2 = event.getX(); y2 = event.getY(); repaint(); } Bewaar coördinaten van de plaats waar de gebruiker de muistoets losliet en dan repaint } // end anonymous inner class ); // end call to addMouseListener // set up mouse motion listener addMouseMotionListener( Self-contained JPanel luistert naar de muisbewegingen new MouseMotionAdapter() { // anonymous inner class // handle mouse drag event public void mouseDragged( MouseEvent event ) { x2 = event.getX(); y2 = event.getY(); repaint(); } Bewaar coördinaten van de plaats waar de gebruiker de muis versleepte dan repaint 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 } // end anonymous inner class ); // end call to addMouseMotionListener } // end constructor SelfContainedPanel // return preferred width and height of SelfContainedPanel public Dimension getPreferredSize() { return new Dimension( 150, 100 ); } // paint an oval at the specified coordinates public void paintComponent( Graphics g ) { super.paintComponent( g ); } g.drawOval( Math.min( x1, x2 ), Math.min( y1, y2 ), Math.abs( x1 - x2 ), Math.abs( y1 - y2 ) ); } // end class SelfContainedPanel Teken ovaal VB: Het maken van een self-contained subclass van JPanel dat zijn eigen mouse events voortbrengt 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // Fig. 14.5: SelfContainedPanelTest.java // Creating a self-contained subclass of JPanel that processes // its own mouse events. import java.awt.*; import java.awt.event.*; import javax.swing.*; import com.deitel.jhtp5.ch14.SelfContainedPanel; public class SelfContainedPanelTest extends JFrame { private SelfContainedPanel myPanel; // set up GUI and mouse motion event handlers for application window public SelfContainedPanelTest() { // set up a SelfContainedPanel Maak SelfCustomPanel object myPanel = new SelfContainedPanel(); en zet achtergrond op geel myPanel.setBackground( Color.YELLOW ); Container container = getContentPane(); container.setLayout( new FlowLayout() ); container.add( myPanel ); 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 // set up mouse motion event handling addMouseMotionListener( Registreer een anoniem inner-class object voor het behandelen van de new MouseMotionListener() { // anonymous inner classevents van de muisbewegingen // handle mouse drag event public void mouseDragged( MouseEvent event ) { setTitle( "Dragging: x=" + event.getX() + "; y=" + event.getY() ); } // handle mouse move event public void mouseMoved( MouseEvent event ) { setTitle( "Moving: x=" + event.getX() + "; y=" + event.getY() ); } } // end anonymous inner class ); // end call to addMouseMotionListener setSize( 300, 200 ); setVisible( true ); } // end constructor SelfContainedPanelTest Toont een String in de title bar met de x-y coördinaat waar een event van de muisbeweging plaatsvond 51 52 public static void main( String args[] ) 53 { 54 SelfContainedPanelTest application = new SelfContainedPanelTest(); 55 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 56 } 57 58 } // end class SelfContainedPanelTest 5 JSlider JSlider Stelt de gebruikers in staat om te selecteren uit een interval van gehele getallen Kenmerken: Tick marks (groot en klein) Snap-to ticks Orientation (horizontaal en verticaal) 24 Horizontaal JSlider component thumb tick mark 25 VB: Een aangepaste JPanel klasse 26 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // Fig. 14.7: OvalPanel.java // A customized JPanel class. import java.awt.*; import javax.swing.*; public class OvalPanel extends JPanel { private int diameter = 10; // draw an oval of the specified diameter public void paintComponent( Graphics g ) { super.paintComponent( g ); } g.fillOval( 10, 10, diameter, diameter ); // validate and set diameter, then repaint public void setDiameter( int newDiameter ) { // if diameter invalid, default to 10 diameter = ( newDiameter >= 0 ? newDiameter : 10 ); repaint(); } Tekent een gevulde ovaal met een gegeven diameter Stel diameter in en repaint 25 26 27 28 29 30 31 32 33 34 35 36 37 // used by layout manager to determine preferred size public Dimension getPreferredSize() { return new Dimension( 200, 200 ); } // used by layout manager to determine minimum size public Dimension getMinimumSize() { return getPreferredSize(); } } // end class OvalPanel Voorbeeld Gebruiken JSlider om de afmetingen van een cirkel/ovaal te wijzigen 29 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // Fig. 14.8: SliderDemo.java // Using JSliders to size an oval. import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; public class SliderDemo extends JFrame { private JSlider diameterSlider; private OvalPanel myPanel; // set up GUI public SliderDemo() { super( "Slider Demo" ); // set up OvalPanel myPanel = new OvalPanel(); myPanel.setBackground( Color.YELLOW ); Maak OvalPanel object en zet achtergrond op geel Maak horizontaal JSlider object met een minimum waarde van 0, maximum waarde van 200 en de thumb op positie 10 // set up JSlider to control diameter value diameterSlider = new JSlider( SwingConstants.HORIZONTAL, 0, 200, 10 ); diameterSlider.setMajorTickSpacing( 10 ); diameterSlider.setPaintTicks( true ); 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 // register JSlider event listener diameterSlider.addChangeListener( new ChangeListener() { // anonymous inner class Registreer een anoniem ChangeListener object om de events van JSlider te behandelen // handle change in slider value public void stateChanged( ChangeEvent e ) { myPanel.setDiameter( diameterSlider.getValue() ); } } // end anonymous inner class ); // end call to addChangeListener // attach components to content pane Container container = getContentPane(); container.add( diameterSlider, BorderLayout.SOUTH ); container.add( myPanel, BorderLayout.CENTER ); setSize( 220, 270 ); setVisible( true ); } // end constructor SliderDemo Wanneer gebruiker een andere waarde aanduidt in JSlider, wordt de diameter van OvalPanel aangepast 52 53 54 55 56 57 58 public static void main( String args[] ) { SliderDemo application = new SliderDemo(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class SliderDemo 6 Windows JFrame Vensters met title bar en border Subclass van java.awt.Frame Subclass van java.awt.Window “Heavyweight” componenten De handelingen wanneer de gebruiker het venster sluit: DISPOSE_ON_CLOSE DO_NOTHING_ON_CLOSE HIDE_ON_CLOSE 33 7 Gebruik van menu’s met Frames Menu’s Staat toe om acties uit te voeren met het centraliseren van GUI Beheerst door menu bar JMenuBar Opgebouwd uit menu componenten JMenuItem 34 VB: Een applicatie die het gebruik van verschillende menu items en speciale karakters illustreert 35 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // Fig. 14.9: MenuTest.java // Demonstrating menus import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MenuTest extends JFrame { private final Color colorValues[] = { Color.BLACK, Color.BLUE, Color.RED, Color.GREEN }; private JRadioButtonMenuItem colorItems[], fonts[]; private JCheckBoxMenuItem styleItems[]; private JLabel displayLabel; private ButtonGroup fontGroup, colorGroup; private int style; // set up GUI public MenuTest() { super( "Using JMenus" ); // set up File menu and its menu items JMenu fileMenu = new JMenu( "File" ); fileMenu.setMnemonic( 'F' ); maak een File JMenu 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 // set up About... menu item JMenuItem aboutItem = new JMenuItem( "About..." ); aboutItem.setMnemonic( 'A' ); fileMenu.add( aboutItem ); maak About… JMenuItem om aboutItem.addActionListener( in fileMenu geplaatst te worden new ActionListener() { // anonymous inner class // display message dialog when user selects About... public void actionPerformed( ActionEvent event ) { JOptionPane.showMessageDialog( MenuTest.this, "This is an example\nof using menus", "About", JOptionPane.PLAIN_MESSAGE ); } } // end anonymous inner class Wanneer gebruiker About… JMenuItem selecteert, toon dan de message dialog met de geschikte tekst ); // end call to addActionListener // set up Exit menu item JMenuItem exitItem = new JMenuItem( "Exit" ); exitItem.setMnemonic( 'x' ); fileMenu.add( exitItem ); exitItem.addActionListener( maak Exit JMenuItem die moet geplaatst worden in fileMenu 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 new ActionListener() { // anonymous inner class // terminate application when user clicks exitItem public void actionPerformed( ActionEvent event ) { System.exit( 0 ); } } // end anonymous inner class Wanneer gebruiker Exit JMenuItem selecteert, verlaten we het systeem ); // end call to addActionListener // create menu bar and attach it to MenuTest window JMenuBar bar = new JMenuBar(); maak JMenuBar om setJMenuBar( bar ); bar.add( fileMenu ); JMenus te bevatten // create Format menu, its submenus and menu items JMenu formatMenu = new JMenu( "Format" ); formatMenu.setMnemonic( 'r' ); // create Color submenu String colors[] = { "Black", "Blue", "Red", "Green" }; maak Format JMenu 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 maak Color JMenu (submenu van Format JMenu) JMenu colorMenu = new JMenu( "Color" ); colorMenu.setMnemonic( 'C' ); colorItems = new JRadioButtonMenuItem[ colors.length ]; colorGroup = new ButtonGroup(); ItemHandler itemHandler = new ItemHandler(); // create color radio button menu items for ( int count = 0; count < colors.length; count++ ) { colorItems[ count ] = maak JRadioButtonMenuItems voor new JRadioButtonMenuItem( colors[ count ] ); Color JMenu en zorg ervoor dat één menu colorMenu.add( colorItems[ count ] ); item tegelijkertijd wordt geselecteerd. colorGroup.add( colorItems[ count ] ); colorItems[ count ].addActionListener( itemHandler ); } // select first Color menu item colorItems[ 0 ].setSelected( true ); // add format menu to menu bar formatMenu.add( colorMenu ); formatMenu.addSeparator(); Separator plaatst lijn tussen JMenuItems // create Font submenu String fontNames[] = { "Serif", "Monospaced", "SansSerif" }; 101 102 103 104 105 106 107 108 109 ); 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 maak Font JMenu (submenu van Format JMenu) JMenu fontMenu = new JMenu( "Font" ); fontMenu.setMnemonic( 'n' ); fonts = new JRadioButtonMenuItem[ fontNames.length ]; fontGroup = new ButtonGroup(); // create Font radio button menu items for ( int count = 0; count < fonts.length; count++ ) { fonts[ count ] = new JRadioButtonMenuItem( fontNames[ count ] } fontMenu.add( fonts[ count ] ); fontGroup.add( fonts[ count ] ); fonts[ count ].addActionListener( itemHandler ); // select first Font menu item fonts[ 0 ].setSelected( true ); maak JRadioButtonMenuItems voor Font JMenu en zorg ervoor dat één menu item tegelijkertijd wordt geselecteerd fontMenu.addSeparator(); // set up style menu items String styleNames[] = { "Bold", "Italic" }; styleItems = new JCheckBoxMenuItem[ styleNames.length ]; StyleHandler styleHandler = new StyleHandler(); 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 // create style checkbox menu items for ( int count = 0; count < styleNames.length; count++ ) { styleItems[ count ] = new JCheckBoxMenuItem( styleNames[ count ] ); fontMenu.add( styleItems[ count ] ); styleItems[ count ].addItemListener( styleHandler ); } // put Font menu in Format menu formatMenu.add( fontMenu ); // add Format menu to menu bar bar.add( formatMenu ); // set up label to display text displayLabel = new JLabel( "Sample Text", SwingConstants.CENTER ); displayLabel.setForeground( colorValues[ 0 ] ); displayLabel.setFont( new Font( "Serif", Font.PLAIN, 72 ) ); getContentPane().setBackground( Color.CYAN ); getContentPane().add( displayLabel, BorderLayout.CENTER ); setSize( 500, 200 ); setVisible( true ); } // end constructor 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 public static void main( String args[] ) { MenuTest application = new MenuTest(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } Opgeroepen wanneer de gebruiker // inner class to handle action events from menu items private class ItemHandler implements ActionListener { selecteert JMenuItem // process color and font selections public void actionPerformed( ActionEvent event ) Bepaal welk fonttype of { kleur in het menu de // process color selection for ( int count = 0; count < colorItems.length; count++ ) van het event is aanleiding if ( colorItems[ count ].isSelected() ) { displayLabel.setForeground( colorValues[ count ] ); break; } // process font selection for ( int count = 0; count < fonts.length; count++ ) if ( event.getSource() == fonts[ count ] ) { displayLabel.setFont( new Font( fonts[ count ].getText(), style, 72 ) ); break; } Zet het resp. aangepaste fonttype of kleur van JLabel 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 repaint(); } // end method actionPerformed } // end class ItemHandler Opgeroepen wanneer de gebruiker JCheckBoxMenuItem // inner class to handle item events from check box menu items selecteert private class StyleHandler implements ItemListener { // process font style selections public void itemStateChanged( ItemEvent e ) { style = 0; // check for bold selection if ( styleItems[ 0 ].isSelected() ) style += Font.BOLD; // check for italic selection if ( styleItems[ 1 ].isSelected() ) style += Font.ITALIC; Bepaalt nieuwe stijl van lettertype displayLabel.setFont( new Font( displayLabel.getFont().getName(), style, 72 ) ); 206 207 repaint(); 208 } 209 210 } // end class StyleHandler 211 212 } // end class MenuTest Oefening 1 Schrijf een applicatie met de volgende menu zonder functionaliteit 45 // MenuIcon.java import java.awt.event.*; import javax.swing.*; public class MenuIcon extends JFrame { private JMenuItem nieuwMenuItem, openMenuItem, printMenuItem, sluitMenuItem; public MenuIcon() { super("Menu Demo"); // Create menu bar and set menu bar to the frame JMenuBar bar = new JMenuBar(); setJMenuBar(bar); // Add menu "Bewerking" to menu bar JMenu bestandMenu = new JMenu("Bestand"); bestandMenu.setMnemonic('B'); bar.add(bestandMenu); // Add menu items with mnemonics to menu "Bestand" bestandMenu.add(nieuwMenuItem= new JMenuItem("Nieuw", 'N')); nieuwMenuItem.setIcon(new ImageIcon("new.gif")); bestandMenu.add(openMenuItem = new JMenuItem("Open", 'O')); openMenuItem.setIcon(new ImageIcon("open.gif")); bestandMenu.add(printMenuItem = new JMenuItem("Print", 'P')); bestandMenu.add(sluitMenuItem = new JMenuItem("Afsluiten", 'A')); setSize(300,300); setVisible(true); } //execute application public static void main(String[] args) { MenuIcon application = new MenuIcon(); application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } 8 Gebruik van JPopupMenu’s Context-gevoelige popup menu’s JPopupMenu Het menu wordt gegenereert afhankelijk van de gekozen component. 48 VB: Een programma dat een JPopupMenu maakt 49 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Fig. 14.10: PopupTest.java // Demonstrating JPopupMenus import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PopupTest extends JFrame { private JRadioButtonMenuItem items[]; private final Color colorValues[] = { Color.BLUE, Color.YELLOW, Color.RED }; private JPopupMenu popupMenu; // set up GUI public PopupTest() { super( "Using JPopupMenus" ); ItemHandler handler = new ItemHandler(); String colors[] = { "Blue", "Yellow", "Red" }; // set up popup menu and its items ButtonGroup colorGroup = new ButtonGroup(); popupMenu = new JPopupMenu(); items = new JRadioButtonMenuItem[ 3 ]; Maak een JPopupMenu object 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 // construct each menu item and add to popup menu; also // enable event handling for each menu item for ( int count = 0; count < items.length; count++ ) { items[ count ] = new JRadioButtonMenuItem( colors[ count ] ); popupMenu.add( items[ count ] ); colorGroup.add( items[ count ] ); Maak JRadioButtonMenuItem items[ count ].addActionListener( handler ); objecten om aan JPopupMenu } toe te voegen getContentPane().setBackground( Color.WHITE ); // declare a MouseListener for the window that displays // a JPopupMenu when the popup trigger event occurs addMouseListener( new MouseAdapter() { // anonymous inner class // handle mouse press event public void mousePressed( MouseEvent event ) { checkForTriggerEvent( event ); } // handle mouse release event public void mouseReleased( MouseEvent event ) { checkForTriggerEvent( event ); } Bepaal of popup-trigger event plaatsvond wanneer de gebruiker de muistoets indrukt of loslaat 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 // determine whether event should trigger popup menu private void checkForTriggerEvent( MouseEvent event ) { if ( event.isPopupTrigger() ) popupMenu.show( event.getComponent(), event.getX(), event.getY() ); } } // end anonymous inner clas ); // end call to addMouseListener Toon JPopupMenu wanneer popup-trigger plaatsvond setSize( 300, 200 ); setVisible( true ); } // end constructor PopupTest public static void main( String args[] ) { PopupTest application = new PopupTest(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 Opgeroepen wanneer de gebruiker // private inner class to handle menu item events JRadioButtonMenuItem private class ItemHandler implements ActionListener { selecteert // process menu item selections public void actionPerformed( ActionEvent event ) { // determine which menu item was selected for ( int i = 0; i < items.length; i++ ) if ( event.getSource() == items[ i ] ) { getContentPane().setBackground( colorValues[ i ] ); return; } Bepaal } } // end private inner class ItemHandler } // end class PopupTest welk JRadioButtonMenuItem geselecteerd was, zet dan de achtergrondkleur van het venster 9 Pluggable Look-and-Feel Pluggable look-and-feel Verander de “look-and-feel” op een dynamische manier Microsoft Windows look-and-feel of een Motif look-and-feel Flexibel 54 VB: Een programma dat aantoont hoe je de look-and-feel van een Swing-GUI kan veranderen 55 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // Fig. 14.11: LookAndFeelDemo.java // Changing the look and feel. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class LookAndFeelDemo extends JFrame { private final String strings[] = { "Metal", "Motif", "Windows" }; private UIManager.LookAndFeelInfo looks[]; private JRadioButton radio[]; private ButtonGroup group; Bevat geïnstalleerde look-and-feel private JButton button; private JLabel label; informatie private JComboBox comboBox; // set up GUI public LookAndFeelDemo() { super( "Look and Feel Demo" ); Container container = getContentPane(); // set up panel for NORTH of BorderLayout JPanel northPanel = new JPanel(); northPanel.setLayout( new GridLayout( 3, 1, 0, 5 ) ); 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 // set up label for NORTH panel label = new JLabel( "This is a Metal look-and-feel", SwingConstants.CENTER ); northPanel.add( label ); // set up button for NORTH panel button = new JButton( "JButton" ); northPanel.add( button ); // set up combo box for NORTH panel comboBox = new JComboBox( strings ); northPanel.add( comboBox ); // create array for radio buttons radio = new JRadioButton[ strings.length ]; // set up panel for SOUTH of BorderLayout JPanel southPanel = new JPanel(); southPanel.setLayout( new GridLayout( 1, radio.length ) ); // set up radio buttons for SOUTH panel group = new ButtonGroup(); ItemHandler handler = new ItemHandler(); 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 for ( int count = 0; count < radio.length; count++ ) { radio[ count ] = new JRadioButton( strings[ count ] ); radio[ count ].addItemListener( handler ); group.add( radio[ count ] ); southPanel.add( radio[ count ] ); } // attach NORTH and SOUTH panels to content pane container.add( northPanel, BorderLayout.NORTH ); container.add( southPanel, BorderLayout.SOUTH ); // get installed look-and-feel information looks = UIManager.getInstalledLookAndFeels(); setSize( 300, 200 ); setVisible( true ); radio[ 0 ].setSelected( true ); } // end constructor LookAndFeelDemo // use UIManager to change look-and-feel of GUI private void changeTheLookAndFeel( int value ) { 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 // change look and feel try { UIManager.setLookAndFeel( looks[ value ].getClassName() ); SwingUtilities.updateComponentTreeUI( this ); } } // process problems changing look and feel catch ( Exception exception ) { exception.printStackTrace(); } public static void main( String args[] ) { LookAndFeelDemo application = new LookAndFeelDemo(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } // private inner class to handle radio button events private class ItemHandler implements ItemListener { // process user's look-and-feel selection public void itemStateChanged( ItemEvent event ) { for ( int count = 0; count < radio.length; count++ ) Verander de lookand-feel 101 if ( radio[ count ].isSelected() ) { 102 label.setText( "This is a " + 103 strings[ count ] + " look-and-feel" ); 104 comboBox.setSelectedIndex( count ); 105 changeTheLookAndFeel( count ); 106 } 107 } 108 109 } // end private inner class ItemHandler 110 111 } // end class LookAndFeelDemo 10 JDesktopPane en JInternalFrame Multiple document interface (MDI) Main (parent) window Child window Schakel vrij tussen de documenten 61 VB: Multiple-document interface Interne Frames Minim Maxim Sluit Toont het gebruik van JDesktopPane en JInternalFrame klassen die ondersteuning bieden voor MDI Geminimaliseerde interne frames Plaats de muis window over een hoek om het formaat van het venster te veranderen (indien dit is toegestaan). 62 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // Fig. 14.12: DesktopTest.java // Demonstrating JDesktopPane. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DesktopTest extends JFrame { private JDesktopPane theDesktop; // set up GUI public DesktopTest() { super( "Using a JDesktopPane" ); Behandel JInternalFrame child windows getoond in JDesktopPane // create menu bar, menu and menu item JMenuBar bar = new JMenuBar(); JMenu addMenu = new JMenu( "Add" ); JMenuItem newFrame = new JMenuItem( "Internal Frame" ); addMenu.add( newFrame ); bar.add( addMenu ); setJMenuBar( bar ); // set up desktop theDesktop = new JDesktopPane(); getContentPane().add( theDesktop ); 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 // set up listener for newFrame menu item newFrame.addActionListener( new ActionListener() { // anonymous inner class Behandel het event wanneer de gebruiker het JMenuItem selecteert // display new internal window public void actionPerformed( ActionEvent event ) { // create internal frame JInternalFrame frame = new JInternalFrame( "Internal Frame", true, true, true, true ); // attach panel to internal frame content pane Container container = frame.getContentPane(); MyJPanel panel = new MyJPanel(); container.add( panel, BorderLayout.CENTER ); // set size internal frame to size of its contents frame.pack(); } // attach internal frame to desktop and show it theDesktop.add( frame ); frame.setVisible( true ); } // end anonymous inner class Opgeroepen wanneer de gebruiker JMenuItem selecteert Maak een JInternalFrame object JPanels kunnen toegevoegd worden aan JInternalFrames Gebruik het verkozen formaat voor het venster 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 ); // end call to addActionListener setSize( 600, 460 ); setVisible( true ); } // end constructor public static void main( String args[] ) { DesktopTest application = new DesktopTest(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class DesktopTest // class to display an ImageIcon on a panel class MyJPanel extends JPanel { private ImageIcon imageIcon; private String[] images = { "yellowflowers.png", "purpleflowers.png", "redflowers.png", "redflowers2.png", "lavenderflowers.png" }; // load image public MyJPanel() { 80 int randomNumber = ( int ) ( Math.random() * 5 ); 81 imageIcon = new ImageIcon( images[ randomNumber ] ); 82 } 83 84 // display imageIcon on panel 85 public void paintComponent( Graphics g ) 86 { 87 // call superclass paintComponent method 88 super.paintComponent( g ); 89 90 // display icon 91 imageIcon.paintIcon( this, g, 0, 0 ); 92 } 93 94 // return image dimensions 95 public Dimension getPreferredSize() 96 { 97 return new Dimension( imageIcon.getIconWidth(), 98 imageIcon.getIconHeight() ); 99 } 100 101 } // end class MyJPanel Interne Frames Geminimaliseerde interne frames Minimaliseren Maximaliseren Sluiten Plaats de muis window over een hoek om het formaat van het venster te veranderen (indien dit is toegestaan). 11 JTabbedPane Rangschikt GUI componenten in lagen “layers” Een laag zichtbaar tegelijk Toegang tot elke laag via een tab JTabbedPane 69 VB: JTabbedPane wordt gebruikt om GUI componenten te organiseren 70 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // Fig. 14.13: JTabbedPaneDemo.java // Demonstrating JTabbedPane. import java.awt.*; import javax.swing.*; public class JTabbedPaneDemo extends JFrame { // set up GUI public JTabbedPaneDemo() { super( "JTabbedPane Demo " ); // create JTabbedPane JTabbedPane tabbedPane = new JTabbedPane(); Maak een JTabbedPane // set up pane11 and add it to JTabbedPane JLabel label1 = new JLabel( "panel one", SwingConstants.CENTER ); JPanel panel1 = new JPanel(); panel1.add( label1 ); tabbedPane.addTab( "Tab One", null, panel1, "First Panel" ); Voeg het eerste panel toe // set up panel2 and add it to JTabbedPane JLabel label2 = new JLabel( "panel two", SwingConstants.CENTER ); JPanel panel2 = new JPanel(); panel2.setBackground( Color.YELLOW ); panel2.add( label2 ); tabbedPane.addTab( "Tab Two", null, panel2, "Second Panel" ); Voeg het tweede panel toe 28 29 // set up panel3 and add it to JTabbedPane 30 JLabel label3 = new JLabel( "panel three" ); 31 JPanel panel3 = new JPanel(); 32 panel3.setLayout( new BorderLayout() ); 33 panel3.add( new JButton( "North" ), BorderLayout.NORTH ); 34 panel3.add( new JButton( "West" ), BorderLayout.WEST ); 35 panel3.add( new JButton( "East" ), BorderLayout.EAST ); 36 panel3.add( new JButton( "South" ), BorderLayout.SOUTH ); 37 panel3.add( label3, BorderLayout.CENTER ); 38 tabbedPane.addTab( "Tab Three", null, panel3, "Third Panel" ); 39 40 // add JTabbedPane to container Voeg 41 getContentPane().add( tabbedPane ); 42 43 setSize( 250, 200 ); 44 setVisible( true ); 45 46 } // end constructor 47 48 public static void main( String args[] ) 49 { 50 JTabbedPaneDemo tabbedPaneDemo = new JTabbedPaneDemo(); 51 tabbedPaneDemo.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 52 } 53 54 } // end class CardDeck het derde panel toe 12 Layout Managers Layout Managers BoxLayout GridBagLayout 74 Bijkomende Layoutmanagers Layout Manager BoxLayout GridBagLayout Description Een layout manager die toestaat dat de GUI componenten worden geranschikt van links-naar-rechts of van bovennaar-onder in een container. Klasse Box definieert een container met BoxLayout als zijn default layou manager en voorziet statische methodes om een Box met een horziontale of verticale BoxLayout.te maken. Een layoutmanager die lijkt op een GridLayout. Verschillend van GridLayout, de grootte van elke component kan variëren en componenten kunnen toegevoegd worden in om het even welke volgorde. 75 BoxLayout layout manager BoxLayout Rangschikt GUI componenten Horizontaal langs x-as Verticaal langs y-as 76 VB: Een programma dat BoxLayout illustreert met de class Box die BoxLayout als de default layout manager gebruikt 77 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Fig. 14.15: BoxLayoutDemo.java // Demonstrating BoxLayout. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BoxLayoutDemo extends JFrame { // set up GUI public BoxLayoutDemo() { super( "Demostrating BoxLayout" ); // create Box containers with BoxLayout Box horizontal1 = Box.createHorizontalBox(); Box vertical1 = Box.createVerticalBox(); Box horizontal2 = Box.createHorizontalBox(); Box vertical2 = Box.createVerticalBox(); final int SIZE = 3; // number of buttons on each Box // add buttons to Box horizontal1 for ( int count = 0; count < SIZE; count++ ) horizontal1.add( new JButton( "Button " + count ) ); Maak Boxes Voeg drie JButtons toe aan horizontale Box 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 // create strut and add buttons to Box vertical1 for ( int count = 0; count < SIZE; count++ ) { vertical1.add( Box.createVerticalStrut( 25 ) ); vertical1.add( new JButton( "Button " + count ) ); } Voeg drie JButtons toe aan verticale Box Strut garandeert ruimte tussen de componenten // create horizontal glue and add buttons to Box horizontal2 for ( int count = 0; count < SIZE; count++ ) { horizontal2.add( Box.createHorizontalGlue() ); horizontal2.add( new JButton( "Button " + count ) ); } Voeg drie Buttons toe aan horizontale Box Glue garandeert uitbreidbare ruimte tussen de componenten // create rigid area and add buttons to Box vertical2 for ( int count = 0; count < SIZE; count++ ) { Voeg drie JButtons aan verticale vertical2.add( Box.createRigidArea( new Dimension( 12, 8 ) ) ); Box toe vertical2.add( new JButton( "Button " + count ) ); } Rigid gebied garandeert een vaste component grootte // create vertical glue and add buttons to panel JPanel panel = new JPanel(); panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ) ); for ( int count = 0; count < SIZE; count++ ) { panel.add( Box.createGlue() ); panel.add( new JButton( "Button " + count ) ); } 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 // create a JTabbedPane JTabbedPane tabs = new JTabbedPane( JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT ); Maak een JTabbedPane om de Boxes vast te houden // place each container on tabbed pane tabs.addTab( "Horizontal Box", horizontal1 ); tabs.addTab( "Vertical Box with Struts", vertical1 ); tabs.addTab( "Horizontal Box with Glue", horizontal2 ); tabs.addTab( "Vertical Box with Rigid Areas", vertical2 ); tabs.addTab( "Vertical Box with Glue", panel ); getContentPane().add( tabs ); // place tabbed pane on content pane setSize( 400, 220 ); setVisible( true ); } // end constructor public static void main( String args[] ) { BoxLayoutDemo application = new BoxLayoutDemo(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class BoxLayoutDemo GridBagLayout layout manager. GridBagLayout Flexibel GridBagLayout componenten kunnen variëren in grootte componenten kunnen diverse rijen en kolommen bezetten componenten kunnen in elke volgorde toegevoegd worden Gebruikt GridBagConstraints Specificeert hoe de component geplaatst wordt in de GridBagLayout 83 Het ontwerpen van een GUI dat GridBagLayout zal gebruiken 0 1 Colum n 2 0 1 Row 2 3 84 GridBagConstraints velden GridBagConstraints Omschrijving veld fill Pas de component aan in de aangeduide richting (NONE, HORIZONTAL, VERTICAL, BOTH) wanneer het uitvoergebied groter dan de component is. gridx De kolom waarin de component zal geplaatst worden. gridy De rij waarin de component zal geplaatst worden. gridwidth Het aantal kolommen dat de component in beslag neemt. gridheight Het aantal rijen dat de component in beslag neemt. weightx De hoeveelheid extra ruimte die horzitonale geplaatst wordt. De “grid slot” kan breder worden wanneer er extra ruimte beschikbaar is. weighty De hoeveelheid extra ruimte die verticaal geplaatst wordt. De “grid slot” kan hoger worden wanneer er extra ruimte beschikbaar is. 85 GridBagLayout met de extra ruimtes op nul geplaatst 86 VB: Een programma dat GridBagLayout gebruikt om de componenten in een GUI te schikken 87 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // Fig. 14.19: GridBagDemo.java // Demonstrating GridBagLayout. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class GridBagDemo extends JFrame { private Container container; private GridBagLayout layout; private GridBagConstraints constraints; // set up GUI public GridBagDemo() { super( "GridBagLayout" ); container = getContentPane(); layout = new GridBagLayout(); container.setLayout( layout ); // instantiate gridbag constraints constraints = new GridBagConstraints(); // create GUI components JTextArea textArea1 = new JTextArea( "TextArea1", 5, 10 ); JTextArea textArea2 = new JTextArea( "TextArea2", 2, 2 ); Zet GridBagLayout als layout manager Gebruikt om de locatie van de component te bepalen en zijn grootte in het raster 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 String names[] = { "Iron", "Steel", "Brass" }; JComboBox comboBox = new JComboBox( names ); JTextField textField = new JTextField( "TextField" ); JButton button1 = new JButton( "Button 1" ); JButton button2 = new JButton( "Button 2" ); JButton button3 = new JButton( "Button 3" ); Indien de gebruiker de grootte van Container wijzigt, zal de eerste JTextArea zijn toegekende ruimte in het raster volledig vullen // weightx and weighty for textArea1 are both 0: the default De eerste JTextArea overspant // anchor for all components is CENTER: the default 1 rij en drie kolommen constraints.fill = GridBagConstraints.BOTH; Indien de gebruiker de grootte van addComponent( textArea1, 0, 0, 1, 3 ); Container wijzigt, zal eerste JButton horizontaal in het raster gevuld worden // weightx and weighty for button1 are both 0: the default constraints.fill = GridBagConstraints.HORIZONTAL; addComponent( button1, 0, 1, 2, 1 ); De eerste JButton overspant twee rijen en één kolom // weightx and weighty for comboBox are both 0: the default // fill is HORIZONTAL addComponent( comboBox, 2, 1, 2, 1 ); // button2 constraints.weightx = 1000; // can grow wider constraints.weighty = 1; // can grow taller constraints.fill = GridBagConstraints.BOTH; addComponent( button2, 1, 1, 1, 1 ); Indien de gebruiker de grootte van Container wijzigt, zal de tweede JButton de extra ruimte opvullen 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 // fill is BOTH for button3 constraints.weightx = 0; constraints.weighty = 0; addComponent( button3, 1, 2, 1, 1 ); // weightx and weighty for textField are both 0, fill is BOTH addComponent( textField, 3, 0, 2, 1 ); // weightx and weighty for textArea2 are both 0, fill is BOTH addComponent( textArea2, 3, 2, 1, 1 ); setSize( 300, 150 ); setVisible( true ); } // end constructor GridBagDemo // method to set constraints on private void addComponent( Component component, int row, int column, int width, int height ) { // set gridx and gridy constraints.gridx = column; constraints.gridy = row; 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 // set gridwidth and gridheight constraints.gridwidth = width; constraints.gridheight = height; } // set constraints and add component layout.setConstraints( component, constraints ); container.add( component ); public static void main( String args[] ) { GridBagDemo application = new GridBagDemo(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class GridBagDemo GridBagConstraints Constanten RELATIVE en REMAINDER Constanten RELATIVE en REMAINDER Gebruikt in plaats van de variabelen gridx en gridy RELATIVE Specificeert next-to-last component plaatsing in rij of kolom De component moet geplaatst worden naast diegene die voorafgaand werd toegevoegd. REMAINDER Specificeert de component als de laatste in rij of kolom 93 VB: De klasse GridBagDemo2 schikt de componenten in GridBagLayout met gebruik van de GridBagConstraints constanten 94 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // Fig. 14.20: GridBagDemo2.java // Demonstrating GridBagLayout constants. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class GridBagDemo2 extends JFrame { private GridBagLayout layout; private GridBagConstraints constraints; private Container container; // set up GUI public GridBagDemo2() { super( "GridBagLayout" ); container = getContentPane(); layout = new GridBagLayout(); container.setLayout( layout ); // instantiate gridbag constraints constraints = new GridBagConstraints(); // create GUI components String metals[] = { "Copper", "Aluminum", "Silver" }; JComboBox comboBox = new JComboBox( metals ); Zet GridBagLayout als layout manager Gebruikt om de locatie van de component te bepalen en zijn grootte in het raster 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 JTextField textField = new JTextField( "TextField" ); String fonts[] = { "Serif", "Monospaced" }; JList list = new JList( fonts ); String names[] = { "zero", "one", "two", "three", "four" }; JButton buttons[] = new JButton[ names.length ]; for ( int count = 0; count < buttons.length; count++ ) buttons[ count ] = new JButton( names[ count ] ); // define GUI component constraints for textField Specifieer textField als constraints.weightx = 1; laatste (enige) component constraints.weighty = 1; in de eerste rij constraints.fill = GridBagConstraints.BOTH; constraints.gridwidth = GridBagConstraints.REMAINDER; addComponent( textField ); // buttons[0] -- weightx and weighty are 1: fill is BOTH constraints.gridwidth = 1; addComponent( buttons[ 0 ] ); // buttons[1] -- weightx and weighty are 1: fill is BOTH constraints.gridwidth = GridBagConstraints.RELATIVE; addComponent( buttons[ 1 ] ); Plaats buttons[0] als eerste component in de tweede rij Plaats buttons[1] rechts naast buttons[0] 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 // buttons[2] -- weightx and weighty are 1: fill is BOTH constraints.gridwidth = GridBagConstraints.REMAINDER; addComponent( buttons[ 2 ] ); // comboBox -- weightx is 1: fill is BOTH constraints.weighty = 0; constraints.gridwidth = GridBagConstraints.REMAINDER; addComponent( comboBox ); // buttons[3] -- weightx is 1: fill is BOTH constraints.weighty = 1; constraints.gridwidth = GridBagConstraints.REMAINDER; addComponent( buttons[ 3 ] ); Plaats buttons[2] rechts naast buttons[1] Specifieer comboBox als laatste (enige) component in de derde rij Specifieer buttons[3] als laatste (enige) component in de vierde rij // buttons[4] -- weightx and weighty are 1: fill is BOTH constraints.gridwidth = GridBagConstraints.RELATIVE; Plaats buttons[4] als addComponent( buttons[ 4 ] ); eerste component in de vijfde rij // list -- weightx and weighty are 1: fill is BOTH constraints.gridwidth = GridBagConstraints.REMAINDER; addComponent( list ); setSize( 300, 200 ); setVisible( true ); } // end constructor Specifieer list als laatste component in de vijfde rij 81 82 83 84 85 86 87 88 89 90 91 92 93 94 // add a Component to the container private void addComponent( Component component ) { layout.setConstraints( component, constraints ); container.add( component ); // add component } public static void main( String args[] ) { GridBagDemo2 application = new GridBagDemo2(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class GridBagDemo2 14 Design Patterns gebruikt in Packages java.awt en javax.swing Introductie van de “Design patterns” die gekoppeld zijn aan Java GUI componenten GUI componenten halen voordeel uit “design patterns” 99