Applicazioni grafiche Finestre Frame I programmi grafici scritti finora erano applet Possiamo anche scrivere applicazioni grafiche Costituite da varie finestre frame Creiamo il frame all’interno del metodo main dell’applicazione public class FrameTest { public static void main(String[] args) { JFrame frame = new JFrame(); … frame.show(); } } 2 Frame Un frame è una finestra indipendente dotata di barra del titolo pulsanti di ridimensionamento e chiusura Per creare un frame si usa la classe JFrame JFrame frame = new JFrame(); Per creare il titolo si usa il metodo setTitle frame.setTitle(“Titolo”); 3 Frame Il metodo pack() assegna le dimensioni al frame in modo che possa contenere tutti i suoi componenti frame.pack(); Il metodo show() mostra la finestra sullo schermo (inizialmente è invisibile) frame.show(); 4 Finestre Frame Impostiamo l’operazione di chiusura predefinita: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Aggiungiamo delle etichette (immagini, scritte) al frame JLabel iconLabel = new JLabel(new ImageIcon("world.gif")); JLabel textLabel = new JLabel("Hello, World!"); Aggiungiamo i componenti ad un pannello e assegnamo il pannello ai contenuti della finestra JPanel panel = new JPanel(); panel.add(iconLabel); panel.add(textLabel) frame.setContentPane(panel); 5 Esempio Scriviamo un programma che visualizza un frame con un’immagine e un’etichetta di testo 6 File FrameTest.java import import import import javax.swing.ImageIcon; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; /** Questo programma visualizza un frame con un’immagine e un’etichetta di testo */ public class FrameTest { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 7 JLabel iconLabel = new JLabel(new ImageIcon("world.gif")); JLabel textLabel = new JLabel("Hello, World!"); JPanel panel = new JPanel(); panel.add(iconLabel); panel.add(textLabel); frame.setContentPane(panel); frame.pack(); frame.show(); } } 8 Esempio Scriviamo un programma che Mostra una finestra contenente un campo di testo per l’inserimento del tasso di interesse Mostra una finestra che visualizza la crescita di un investimento 9 File TextAreaTest.java import import import import import import import import import java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JButton; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JScrollPane; javax.swing.JTextArea; javax.swing.JTextField; /** Questo programma mostra un frame con un’area di testo che visualizza la crescita di un investimento e un frame con un’area di testo per l’inserimento del tasso di interesse */ 10 public class TextAreaTest { public static void main(String[] args) { // l’applicazione aggiunge l’interesse al conto final BankAccount account = new BankAccount(INITIAL_BALANCE); // l’area di testo per visualizzare la crescita dell’investimento final JTextArea textArea = new JTextArea(10, 30); textArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(textArea); 11 // costruisce il frame che visualizza l’area di testo JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(scrollPane); frame.pack(); frame.show(); // l’etichetta e il campo di testo per inserire il tasso di interesse JLabel rateLabel = new JLabel("Interest Rate: "); final JTextField rateField = new JTextField(10); rateField.setText("" + DEFAULT_RATE); // il pulsante per innescare il calcolo JButton calculateButton = new JButton("Add Interest"); 12 class CalculateListener implements ActionListener { public void actionPerformed(ActionEvent event) { double rate = Double.parseDouble( rateField.getText()); double interest = account.getBalance() * rate / 100; account.deposit(interest); textArea.append(account.getBalance() + "\n"); } } ActionListener listener = new CalculateListener(); calculateButton.addActionListener(listener); 13 // il pannello che contiene i componenti JPanel controlPanel = new JPanel(); controlPanel.add(rateLabel); controlPanel.add(rateField); controlPanel.add(calculateButton); // il frame che contiene il pannello JFrame controlFrame = new JFrame(); controlFrame.setContentPane(controlPanel); controlFrame.pack(); controlFrame.show(); } private static final double DEFAULT_RATE = 10; private static final double INITIAL_BALANCE = 1000; } 14 Aggiungere la grafica ad un’applicazione In un applet, per aggiungere la grafica estendiamo la classe Applet e sovrascriviamo il metodo paint Questo approccio non funziona per le finestre frame, sulla cui superficie non possiamo disegnare direttamente Per mostrare grafica, occorre disegnarla in un JPanel, sovrascrivendone il metodo paintComponent 15 Aggiungere la grafica ad un’applicazione Importante: dobbiamo invocare il metodo paintComponent della superclasse (per cancellare I vecchi contenuti del pannello) public class MyPanel extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; //istruzioni di disegno. . . } } 16 Aggiungere la grafica ad un’applicazione La dimensione predefinita del pannello è 0 x 0 pixel Possiamo impostare le dimensioni nel costruttore: public class MyPanel extends JPanel { public MyPanel() { setPreferredSize( new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); . . . } private static final int PANEL_WIDTH = 300; private static final int PANEL_HEIGHT = 300; } 17 Trasformare un applet in un’applicazione grafica RectangleApplet disegnava un rettangolo nel punto di pressione del tasto del mouse Trasformiamolo in un’applicazione grafica: Creiamo una classe RectanglePanel per creare un pannello e impostiamone le dimensioni nel costruttore Installiamo un ricevitore di eventi del mouse Il risultato sarà identico all’applet, ma non avrà bisogno di un file HTML nè di un visualizzatore di applet 18 Applicazione grafica 19 Applet Æ applicazione grafica public class RectanglePanel extends JPanel { public RectanglePanel() { setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); // aggiungi un ricevitore per gli eventi del mouse …. } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; … } } 20 Trasformare un applet in un’applicazione grafica La classe di un pannello che traccia un disegno dovrebbe memorizzare tutti i dati necessari per ridisegnarsi Nel nostro caso, si tratta di un rettangolo 21 Applet Æ applicazione public class RectanglePanel extends JPanel { public RectanglePanel() { // il rettangolo disegnato dal metodo paint box = new Rectangle(…); …. } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.draw(box); } private Rectangle box; } 22 File RectanglePanel.java import import Import import import import import import java.awt.event.MouseEvent; java.awt.event.MouseListener; java.awt.event.MouseAdapter; java.awt.Dimension; java.awt.Graphics; java.awt.Graphics2D; java.awt.Rectangle; javax.swing.JPanel; /** Un pannello che visualizza un rettangolo che può essere spostato dall’utente premendo il pulsante del mouse. */ 23 public class RectanglePanel extends JPanel { /** Costruisce il pannello con il rettangolo in posizione predefinita. */ public RectanglePanel() { setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); // il rettangolo disegnato dal metodo paint box = new Rectangle(BOX_X, BOX_Y, BOX_WIDTH, BOX_HEIGHT); 24 // aggiungi il ricevitore di eventi del mouse class MousePressListener extends MouseAdapter { public void mousePressed(MouseEvent event) { int x = event.getX(); int y = event.getY(); box.setLocation(x, y); repaint(); } } MouseListener listener = new MousePressListener(); addMouseListener(listener); } 25 public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.draw(box); } private Rectangle box; private static final int BOX_X = 100; private static final int BOX_Y = 100; private static final int BOX_WIDTH = 20; private static final int BOX_HEIGHT = 30; private static final int PANEL_WIDTH = 300; private static final int PANEL_HEIGHT = 300; } 26 File RectangleTest.java import import import import import javax.swing.JButton; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JTextField; /** Questo programma visualizza un frame contenente un RectanglePanel. */ public class RectangleTest { public static void main(String[] args) { RectanglePanel rectPanel = new RectanglePanel(); 27 JFrame appFrame = new JFrame(); appFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); appFrame.setContentPane(rectPanel); appFrame.pack(); appFrame.show(); } } 28 Classi usate nell’applicazione RectangleTest 29 Errori comuni Bisogna sovrascrivere il metodo paintComponent del pannello e non il metodo paint! Altrimenti il contenuto del pannello sarà imprevedibile Bisogna invocare il metodo paintComponent della superclasse per disegnare nel pannello Altrimenti lo sfondo del pannello non sarà cancellato 30 Uso dell’ereditarietà per personalizzare i frame Per creare un frame complesso conviene usare l’ereditarietà, definendo una sottoclasse di JFrame Aggiungiamo i componenti dell’interfaccia utente nel costruttore Se sono troppi, è preferibile usare un metodo separato I componenti che devono essere condivisi tra questi metodi vanno trasformati in variabili istanza della classe 31 Uso dell’ereditarietà per personalizzare i frame Utilizziamo tre classi: RectangleFrame, per creare il frame contenente il pannello per i componenti dell’interfaccia utente RectanglePanel, per creare il pannello che disegna il rettangolo RectangleTest, per visualizzare il frame 32 Uso dell’ereditarietà per personalizzare i frame 33 Uso dell’ereditarietà per personalizzare i frame public class RectangleFrame extends JFrame { public RectangleFrame() { //il pannello che disegna il rettangolo rectPanel = new RectanglePanel(); getContentPane().add(rectPanel, BorderLayout.CENTER); createControlPanel(); pack(); } 34 private void createControlPanel() { //campi di testo per le coordinate x e y final JTextField xField = new JTextField(5); final JTextField yField = new JTextField(5); class MoveButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { int x = Integer.parseInt(xField.getText()); int y = Integer.parseInt(yField.getText()); rectPanel.setLocation(x, y); } } 35 //crea un pulsante e associa un ricevitore JButton moveButton = new JButton("Move"); ActionListener listener = new MoveButtonListener(); moveButton.addActionListener(listener); // il pannello per i componenti JPanel controlPanel = new JPanel(); //aggiunta dei componenti al pannello … getContentPane().add(controlPanel, BorderLayout.SOUTH); } private RectanglePanel rectPanel; } 36 Visualizzare il frame Creiamo una classe di test separata public class RectangleTest { public static void main(String[] args) { JFrame appFrame = new RectangleFrame(); appFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); appFrame.show(); } } 37 Problema Il ricevitore di eventi del pulsante Move non ha accesso diretto al rettangolo che si trova nell’oggetto di tipo RectanglePanel… Bisogna aggiungere alla classe RectanglePanel un metodo che consenta ad altri di impostare la posizione del rettangolo class RectanglePanel extends JPanel { . . . public void setLocation(int x, int y) { box.setLocation(x, y); repaint(); } } 38 File RectangleTest.java import javax.swing.JFrame; /** Questo programma collauda la classe RectangleFrame public class RectangleTest { public static void main(String[] args) { JFrame appFrame = new RectangleFrame(); appFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); appFrame.show(); } } 39 File RectangleFrame.java import import import import import import import import java.awt.BorderLayout; java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JButton; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JTextField; /** Questo frame contiene un pannello che mostra un rettangolo e un pannello di campi di testo per specificare la posizione del rettangolo */ 40 public class RectangleFrame extends JFrame { /** Costruisce il frame. */ public RectangleFrame() { // il pannello che disegna il rettangolo rectPanel = new RectanglePanel(); // aggiungi il pannello al pannello dei contenuti getContentPane().add(rectPanel, BorderLayout.CENTER); createControlPanel(); pack(); } 41 /** Crea il pannello di controllo con i campi di testo nella parte bassa del frame. */ private void createControlPanel() { // i campi di testo per x e y final JTextField xField = new JTextField(5); final JTextField yField = new JTextField(5);; // il bottone per muovere il rettangolo JButton moveButton = new JButton("Move"); 42 class MoveButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { int x = Integer.parseInt(xField.getText()); int y = Integer.parseInt(yField.getText()); rectPanel.setLocation(x, y); } } ActionListener listener = new MoveButtonListener(); moveButton.addActionListener(listener); // le etichette per i campi di testo JLabel xLabel = new JLabel("x = "); JLabel yLabel = new JLabel("y = "); 43 // il pannello per le componenti JPanel controlPanel = new JPanel(); controlPanel.add(xLabel); controlPanel.add(xField); controlPanel.add(yLabel); controlPanel.add(yField); controlPanel.add(moveButton); getContentPane().add(controlPanel, BorderLayout.SOUTH); } private RectanglePanel rectPanel; } 44 File RectanglePanel.java import import import import import java.awt.Dimension; java.awt.Graphics; java.awt.Graphics2D; java.awt.Rectangle; javax.swing.JPanel; /** Questo pannello visualizza un rettangolo. */ public class RectanglePanel extends JPanel { /** Costruisce un pannello con un rettangolo in posizione predefinita */ 45 public RectanglePanel() { setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); // the rectangle that the paint method draws box = new Rectangle(BOX_X, BOX_Y, BOX_WIDTH, BOX_HEIGHT); } /** Imposta la posizione del rettangolo e ridisegna il pannello. @param x la coord x dell’angolo sup. sx @param y la coord y dell’angolo sup. sx */ 46 public void setLocation(int x, int y) { box.setLocation(x, y); repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.draw(box); } 47 private Rectangle private static private static private static private static box; final final final final int int int int BOX_X = 100; BOX_Y = 100; BOX_WIDTH = 20; BOX_HEIGHT = 30; private static final int PANEL_WIDTH = 300; private static final int PANEL_HEIGHT = 300; } 48 49 Le classi usate nell’applicazione RectangleFrame 50 Convertire un frame in un applet Il pacchetto javax.swing ha una classe JApplet simile a JFrame Un oggetto di tipo JApplet ha anche un pannello dei contenuti con gestore di layout Per convertire un frame in un applet: Eliminare la classe che contiene il metodo main Ereditare da JApplet invece che da JFrame Eliminare l’invocazione a setSize e impostare la dimensione della finestra nella pagina HTML Eliminare l’invocazione a setTitle e inserire il titolo nella pagina HTML 51 Un frame complesso per gestire le scelte 52 File ChoiceFrame.java import import import import import import import import import import import import import import import java.awt.BorderLayout; java.awt.Container; java.awt.Font; java.awt.GridLayout; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; javax.swing.ButtonGroup; javax.swing.JButton; javax.swing.JCheckBox; javax.swing.JComboBox; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; 53 import javax.swing.JRadioButton; import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; /** Questo frame contiene un campo di testo e un pannello di controllo per cambiare il font del testo */ public class ChoiceFrame extends JFrame { // Costruisce il frame. public ChoiceFrame() { // costruisce il testo dimostrativo sampleField = new JLabel("Big Java"); getContentPane().add(sampleField, BorderLayout.CENTER); 54 // ascoltatore condiviso tra tutti i componenti class ChoiceListener implements ActionListener { public void actionPerformed(ActionEvent event) { setSampleFont(); } } listener = new ChoiceListener(); createControlPanel(); setSampleFont(); pack(); } 55 //Crea il pannello di controllo public void createControlPanel() { JPanel facenamePanel = createComboBox(); JPanel sizeGroupPanel = createCheckBoxes(); JPanel styleGroupPanel = createRadioButtons(); // allinea i pannelli JPanel controlPanel = new JPanel(); controlPanel.setLayout(new GridLayout(3, 1)); controlPanel.add(facenamePanel); controlPanel.add(sizeGroupPanel); controlPanel.add(styleGroupPanel); // aggiunge i pannelli al pannello dei contenuti getContentPane().add(controlPanel, BorderLayout.SOUTH); } 56 /** Crea la casella combinata per la scelta dello stile del font. @return il pannello che contiene la casella combinata */ public JPanel createComboBox() { facenameCombo = new JComboBox(); facenameCombo.addItem("Serif"); facenameCombo.addItem("SansSerif"); facenameCombo.addItem("Monospaced"); facenameCombo.setEditable(true); facenameCombo.addActionListener(listener); JPanel panel = new JPanel(); panel.add(facenameCombo); return panel; } 57 /** Crea le caselle di controllo @return il pannello contenente le caselle */ public JPanel createCheckBoxes() { italicCheckBox = new JCheckBox("Italic"); italicCheckBox.addActionListener(listener); boldCheckBox = new JCheckBox("Bold"); boldCheckBox.addActionListener(listener); JPanel panel = new JPanel(); panel.add(italicCheckBox); panel.add(boldCheckBox); panel.setBorder (new TitledBorder(new EtchedBorder(), "Style")); return panel; } 58 /** Crea i bottoni radio @return il pannello contenentei bottoni radio */ public JPanel createRadioButtons() { smallButton = new JRadioButton("Small"); smallButton.addActionListener(listener); mediumButton = new JRadioButton("Medium"); mediumButton.addActionListener(listener); largeButton = new JRadioButton("Large"); largeButton.addActionListener(listener); largeButton.setSelected(true); // aggiunge i bottoni radio al gruppo di pulsanti ButtonGroup group = new ButtonGroup(); group.add(smallButton); group.add(mediumButton); group.add(largeButton); 59 JPanel panel = new JPanel(); panel.add(smallButton); panel.add(mediumButton); panel.add(largeButton); panel.setBorder (new TitledBorder(new EtchedBorder(), "Size")); return panel; } // Acquisisce le scelte dell’utente. public void setSampleFont() { // acquisisce il nome del font String facename = (String)facenameCombo.getSelectedItem(); // acquisisce lo stile del font int style = 0; 60 if (italicCheckBox.isSelected()) style = style + Font.ITALIC; if (boldCheckBox.isSelected()) style = style + Font.BOLD; // acquisisce la dimensione del font int size = 0; final int SMALL_SIZE = 24; final int MEDIUM_SIZE = 36; final int LARGE_SIZE = 48; if (smallButton.isSelected()) size = SMALL_SIZE; else if (mediumButton.isSelected()) size = MEDIUM_SIZE; else if (largeButton.isSelected()) size = LARGE_SIZE; 61 // imposta il font sampleField.setFont(new Font(facename, style, size)); sampleField.repaint(); } private private private private private private private private JLabel sampleField; JCheckBox italicCheckBox; JCheckBox boldCheckBox; JRadioButton smallButton; JRadioButton mediumButton; JRadioButton largeButton; JComboBox facenameCombo; ActionListener listener; } 62 File ChoiceTest.java import javax.swing.JFrame; /** Testa la classe ChoiceFrame. */ public class ChoiceTest { public static void main(String[] args) { JFrame frame = new ChoiceFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.show(); } } 63 Classi nel programma ChoiceTest 64 Barra dei menu Una barra dei menu è costituita da un gruppo di menu lungo il margine superiore di una finestra 65 Barra dei menu Per creare una barra dei menu si usa la classe JMenuBar JMenuBar menuBar = new JMenuBar(); La barra dei menu deve essere associata a un oggetto di tipo Frame con il metodo setJmenuBar() setJMenuBar(menuBar); 66 Menu Per creare un menu si usa la classe JMenu JMenu fileMenu = new JMenu(“File”); I menu vengono aggiunti alla barra dei menu mediante il metodo add() menuBar.add(fileMenu); 67 Menu All’interno dei menu si aggiungono le voci di menu Per creare una voce di menu si usa la classe JMenuItem JMenuItem fileNewMenuItem = new JMenuItem(“New”); filemenu.add(fileNewMenuItem); 68 Menu Quando una voce di menu viene selezionata, invia un evento di azione Per riceverlo, è necessario installare un ricevitore di azioni (classe che implementa l’interfaccia ActionListener) class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) { … } } ActionListener listener = new menuItemListener(); fileNewMenuItem.addActionListener(listener); 69 File MenuFrame.java import import import import import import import import java.awt.BorderLayout; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.util.Random; javax.swing.JFrame; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; /** Questo frame ha un menu con comandi per impostare la posizione di un rettangolo. */ 70 class MenuFrame extends JFrame { // Costruisce il frame public MenuFrame() { generator = new Random(); // aggiunge al pannello dei contenuti un pannello per disegnare panel = new RectanglePanel(); getContentPane().add(panel, BorderLayout.CENTER); pack(); 71 // costruisce il menu JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); menuBar.add(createFileMenu()); menuBar.add(createEditMenu()); } /** Crea il menu File. @return il menu */ public JMenu createFileMenu() { JMenu menu = new JMenu("File"); menu.add(createFileNewItem()); menu.add(createFileExitItem()); return menu; } 72 /** Crea il menu Edit. @return il menu */ public JMenu createEditMenu() { JMenu menu = new JMenu("Edit"); menu.add(createMoveMenu()); menu.add(createEditRandomizeItem()); return menu; } 73 /** Crea il sottomenu Move. @return il menu */ public JMenu createMoveMenu() { JMenu menu = new JMenu("Move"); menu.add(createMoveItem("Up", 0, -1)); menu.add(createMoveItem("Down", 0, 1)); menu.add(createMoveItem("Left", -1, 0)); menu.add(createMoveItem("Right", 1, 0)); return menu; } 74 /** Crea la voce di menu File->New menu e imposta il ricevitore. @return la voce di menu */ public JMenuItem createFileNewItem() { JMenuItem item = new JMenuItem("New"); class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) { panel.reset(); } } ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } 75 /** Crea la voce di menu File->Exit e imposta il ricevitore. @return la voce di menu */ public JMenuItem createFileExitItem() { JMenuItem item = new JMenuItem("Exit"); class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) { System.exit(0); } } ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } 76 /** Crea la voce di menu che sposta il rettangolo e imposta il ricevitore. @param label l’etichetta del menu @param dx l’ammonstare dello spostamento in direz. x @param dy l’ammontare dello spostamento in direz. y @return la voce di menu */ public JMenuItem createMoveItem(String label, final int dx, final int dy) { JMenuItem item = new JMenuItem(label); 77 class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) { panel.moveRectangle(dx, dy); } } ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } 78 /** Crea la voce di menu Edit->Randomize e imposta il ricevitore. @return la voce di menu */ public JMenuItem createEditRandomizeItem() { JMenuItem item = new JMenuItem("Randomize"); class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) { int width = panel.getWidth(); int height = panel.getHeight(); int dx = -1 + generator.nextInt(2); int dy = -1 + generator.nextInt(2); panel.moveRectangle(dx, dy); } } 79 ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } private RectanglePanel panel; private Random generator; } 80 File MenuTest.java import javax.swing.JFrame; /** Testa la classe MenuFrame. */ public class MenuTest { public static void main(String[] args) { JFrame frame = new MenuFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.show(); } } 81 File RectanglePanel.java import import import import import java.awt.Dimension; java.awt.Graphics; java.awt.Graphics2D; java.awt.Rectangle; javax.swing.JPanel; // Questo pannello visualizza un rettangolo. class RectanglePanel extends JPanel { /** Costruisce un pannello con un rettangolo in posizione predefinita. */ 82 public RectanglePanel() { setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); // il rettangolo disegnato dal metodo paint box = new Rectangle(0, 0, BOX_WIDTH, BOX_HEIGHT); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.draw(box); } 83 // Riporta il rettangolo nell’angolo superiore sx. public void reset() { box.setLocation(0, 0); repaint(); } /** Muove il rettangolo per multipli di larghezza e altezza e lo ridisegna. @param dx le unità di larghezza @param dy le unità di altezza */ public void moveRectangle(int dx, int dy) { box.translate(dx * BOX_WIDTH, dy * BOX_HEIGHT); repaint(); } 84 private private private private private Rectangle box; static final int static final int static final int static final int BOX_WIDTH = 20; BOX_HEIGHT = 30; PANEL_WIDTH = 300; PANEL_HEIGHT = 300; } 85 86 Consultare la documentazione di Swing Vogliamo creare un’applicazione grafica in cui l’utente crea un nuovo colore spostando dei cursori per i colori primari Come creare un cursore? Come sapere se l’utente lo sposta? Come conoscerne il valore? 87 Consultare la documentazione di Swing Consultiamo la documentazione della classe JSlider: ci sono 6 costruttori… JSlider() Crea un cursore orizzontale tra 0 e 100 con valore iniziale 50 JSlider(int min, int max, int value) Crea un cursore orizzontale usando i valori specificati … … 88 Consultare la documentazione di Swing Quali eventi genera un cursore? Può subire una modifica, relativa allo spostamento Per intercettare la modifica, una classe deve implementare l’interfaccia ChangeListener, che ha un solo metodo public interface ChangeListener { void stateChanged(ChangeEvent event); } 89 Consultare la documentazione di Swing Per calcolare il valore attuale del cursore usiamo il metodo getValue() Possiamo aggiungere lo stesso ricevitore di eventi a tutti e tre i cursori 90 File SliderFrame.java import import import import import import import import import import import import import import java.awt.BorderLayout; java.awt.Color; java.awt.Container; java.awt.Dimension; java.awt.GridLayout; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JSlider; javax.swing.SwingConstants; javax.swing.event.ChangeListener; javax.swing.event.ChangeEvent; 91 class SliderFrame extends JFrame { public SliderFrame() { colorPanel = new JPanel(); colorPanel.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); getContentPane().add(colorPanel, BorderLayout.CENTER); createControlPanel(); setSampleColor(); pack(); } 92 public void createControlPanel() { class ColorListener implements ChangeListener { public void stateChanged(ChangeEvent event) { setSampleColor(); } } 93 ChangeListener listener = new ColorListener(); redSlider = new JSlider(0, 100, 100); redSlider.addChangeListener(listener); greenSlider = new JSlider(0, 100, 70); greenSlider.addChangeListener(listener); blueSlider = new JSlider(0, 100, 70); blueSlider.addChangeListener(listener); JPanel controlPanel = new JPanel(); controlPanel.setLayout(new GridLayout(3, 2)); controlPanel.add(new JLabel("Red”, SwingConstants.RIGHT)); controlPanel.add(redSlider); 94 controlPanel.add(new JLabel("Green", SwingConstants.RIGHT)); controlPanel.add(greenSlider); controlPanel.add(new JLabel("Blue", SwingConstants.RIGHT)); controlPanel.add(blueSlider); getContentPane().add(controlPanel, BorderLayout.SOUTH); } /** Legge I valori del cursore e imposta il pannello sul colore selezionato. */ public void setSampleColor() { // legge I valori del cursore float red = 0.01F * redSlider.getValue(); float green = 0.01F * greenSlider.getValue(); float blue = 0.01F * blueSlider.getValue(); 95 // imposta lo sfondo del pannello sul colore selezionato colorPanel.setBackground(new Color(red, green, blue)); colorPanel.repaint(); } private private private private JPanel colorPanel; JSlider redSlider; JSlider greenSlider; JSlider blueSlider; private static final int PANEL_WIDTH = 300; private static final int PANEL_HEIGHT = 300; } 96 File SliderTest.java import javax.swing.JFrame; public class SliderTest { public static void main(String[] args) { SliderFrame frame = new SliderFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.show(); } } 97 Le Componenti di SliderFrame 98 Le Classi di SliderTest 99