2010-10-27 14 views
10

Para un proyecto escolar, necesito hacer una aplicación de pintura simple que pueda dibujar líneas, óvalos y rectángulos.Swing: botones de alternar enlaces junto con un grupo de botones, junto con los elementos de menú correspondientes

La asignación especifica que necesito botones de la barra de herramientas y elementos del menú para cada tipo de forma.

Me gustaría ir un poco más allá, al hacer que los botones JToggleButtons en la barra de herramientas y los elementos de menú JRadioButtonMenuItems. Además, lo quiero para que cuando seleccione uno de los botones de la barra de herramientas, anule la selección de los otros, seleccione el elemento de menú apropiado y deseleccione los otros elementos del menú. Lo mismo para seleccionar uno de los elementos del menú.

Sé que puedo agrupar cualquier AbstractButton con un ButtonGroup, pero no estoy seguro de si este es el camino correcto, porque aunque maneja un "grupo" de botones muy bien, no estoy seguro de que pueda manejar dos grupos paralelos.

Hacerlo sin ButtonGroup significaría que en cada uno de los 6 detectores de eventos tendría que anular manualmente la selección de los otros botones, y cada par llamaría al mismo código para establecer el tipo de forma.

También podría hacer dos ButtonGroup s, uno para el menú, uno para la barra de herramientas, pero luego también tengo que duplicar el código de configuración del tipo de forma.

En cualquier situación, también corro el riesgo de que el menú establezca un botón que establece un elemento de menú que establece un botón, ad infintum.

¿Cuál es la mejor manera de abordar este problema?

(puntos de bonificación para ser capaz de resolver el problema con el diseñador de interfaz gráfica de usuario Netbeans, es sólo más fácil)

+5

Puntos de bonificación por hacerlo sin un diseñador de GUI. Pasas tu tiempo aprendiendo Java que es portátil, en lugar del IDE que no lo es. – camickr

+0

@camickr - De hecho, prefiero usar Textmate y el terminal a través de un IDE, es solo que el diseñador de GUI hace que las cosas vayan * SO * mucho más rápido. Mi punto era que prefería resolverlo en el diseñador y ver cómo lo hacía, que lidiar con la edición del código generado automáticamente y pasar horas averiguando por qué las cosas pequeñas no funcionan. –

Respuesta

18

La interfaz Action es un enfoque eficaz "si tiene dos o más componentes que realizan la misma función" como se discutió en How to Use Actions. En particular, un Action permitiría que sus botones y elementos de menú usen el mismo código.

Adición: El ejemplo siguiente muestra cómo un JMenu y un JToolBar pueden compartir el mismo Action para cada uno de varios archivos.

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.io.File; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JToolBar; 

/** @see http://stackoverflow.com/questions/4038605 */ 
public class FileMenu { 

    public static void main(String[] args) { 

     EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       new FileMenu().create(); 
      } 
     }); 
    } 

    void create() { 
     File userDir = new File(System.getProperty("user.dir")); 
     File[] files = userDir.listFiles(); 

     JMenu menu = new JMenu("Recent Files"); 
     JToolBar toolBar = new JToolBar(JToolBar.VERTICAL); 
     JLabel label = new JLabel(" ", JLabel.CENTER); 
     for (File f : files) { 
      if (f.isFile() && !f.isHidden()) { 
       RecentFile rf = new RecentFile(f, label); 
       menu.add(new JMenuItem(rf.getAction())); 
       toolBar.add(rf.getAction()); 
      } 
     } 
     JMenuBar menuBar = new JMenuBar(); 
     menuBar.add(menu); 

     JFrame f = new JFrame("FileMenu"); 
     f.setJMenuBar(menuBar); 
     f.add(toolBar, BorderLayout.CENTER); 
     f.add(label, BorderLayout.SOUTH); 
     f.pack(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 

class RecentFile extends AbstractAction { 

    private final File file; 
    private final JLabel label; 

    public RecentFile(final File file, final JLabel label) { 
     this.file = file; 
     this.label = label; 
     this.putValue(Action.NAME, file.getName()); 
     this.putValue(Action.SHORT_DESCRIPTION, file.getAbsolutePath()); 
    } 

    public void actionPerformed(ActionEvent e) { 
     label.setText(file.getName()); 

    } 

    public Action getAction() { 
     return this; 
    } 
} 
+3

+1, las acciones son tan fáciles de escribir como un ActionListener, pero proporcionan mucha más funcionalidad en general. – camickr

+2

¿Puede explicar por qué agrega (rf.getAction()) y no solo (rf) a la barra de herramientas en este código: 'toolBar.add (rf.getAction());', así como en la línea de arriba? –

+2

@userunknown: Buena pregunta; parece que lo adapté de otro ejemplo que usó composición en lugar de extensión. – trashgod

Cuestiones relacionadas