2010-03-16 15 views
5

Próbowałem zrobić JMenu zachowywać się jak JButton, ale mam pewne problemy i mam nadzieję, że ktoś tutaj może pomóc!Jak zmusić JMenu do zachowania przycisku w JMenuBar

Dodałem MenuListener do elementu JMenu z tym ale nie mogę dostać menu podręcznego/fokusu zostawić, aby umożliwić mi właściwe klikanie razy JMenu powtarzające się, aby uruchomić tę funkcję i miałem nadzieję, że ktoś może mi powiedzieć co Robię źle. Dzięki.

public void menuSelected(MenuEvent e) 
     { 
      ... // do stuff here code 
      JMenu source = (JMenu)e.getSource(); 
      source.setSelected(false); 
      source.setPopupMenuVisible(false); 

     } 
+0

nie jestem pewien, rozumiem co próbujesz osiągnąć tutaj. Dlaczego chcesz JMenu działać jak przycisk zamiast po prostu za pomocą JMenuItem? –

+0

Może dostarczyć więcej kodu źródłowego, z którym pracujesz, abyśmy mogli zobaczyć ogólniej, co próbujesz osiągnąć –

Odpowiedz

8

Nie całkowicie pewny co pytasz ...

Ale JMenuBar dziedziczy z Container - jeśli wolisz dodać JButton do niego niż JMenu można po prostu zadzwonić -

JMenuBar menuBar = .... 
JButton myButton = .... 
menuBar.add(myButton); 
+0

Ahhhh Nie wiedziałem, że możesz dodać JButton do JMenuBar ... Dzięki soo much – Kurru

+0

ale czy działa to w systemie MAC OS X? – user584397

+3

przycisk wygląda inaczej niż JMenu. –

1

Ten przykładowy kod działa w czasie zaćmienia, Ponownie niepokojący o tym, jak go używasz?

public class MyMenuFrame extends JFrame { 


    public MyMenuFrame() throws HeadlessException { 
     super("My Frame"); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.setSize(400, 300); 
     Container pane = this.getContentPane(); 
     pane.setLayout(new BorderLayout()); 
     pane.add(new JLabel("Hi there"), BorderLayout.PAGE_START); 
     this.setVisible(true); 
     JMenuBar menubar = new JMenuBar(); 
     JMenu menu = new JMenu("File"); 

     menu.addMenuListener(new MenuListener() { 

      @Override 
      public void menuSelected(MenuEvent e) { 
       System.out.println("a"); 

      } 

      @Override 
      public void menuDeselected(MenuEvent e) { 
       System.out.println("a"); 

      } 

      @Override 
      public void menuCanceled(MenuEvent e) { 
       System.out.println("a"); 

      } 
     }); 
     menubar.add(menu); 
     this.setJMenuBar(menubar); 
    } 

    public static void main(String[] args) { 
     new MyMenuFrame(); 
    } 
} 
0

Bardzo trudno jest ustalić, co próbujesz tutaj zrobić. Ale nie sądzę, że poprawnie używasz JMenu.

JMenu jest obiektem reprezentującym menu. Jest on oddzielony od paska menu (JMenuBar) i pozycji menu (JMenuItem). JMenuBar zwykle zawiera wiele JMenus (Plik, Edycja, itp.), Które z kolei zawierają wiele JMenuItems (Nowy, Otwórz, Zamknij). JMenuItems są tym, co zostało kliknięte i "działa jak przycisk" w menu.

Aby uzyskać pozycję menu, która działa jak przycisk, po prostu dodaj ją do menu. Na przykład:

JMenu fileMenu = new JMenu("File"); 
JMenuItem newChoice = new JMenuItem("New"); 
newChoice.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     newHasBeenSelected(); 
    } 
}); 
fileMenu.add(newChoice); 

Jeśli próbujesz stworzyć wyskakujące menu, musisz użyć JPopupMenu zamiast JMenu, i nie trzeba się JMenuBar. Oto tutoriale Java w menu: http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html

A tutaj są docs Java dla JMenuBar, JMenu, JPopupMenu i JMenuItem.

Jeśli edytujesz swoje pytanie i przedstawisz bardziej szczegółowe wyjaśnienie, co robisz, być może będę mógł udzielić bardziej szczegółowej pomocy.

1

Wiem, że to stara nitka, ale myślę, że mogę mieć rozwiązanie. Natknąłem się na ten problem w jednej z moich aplikacji i znalazłem obejście. Spróbuj użyć JMenuItem zamiast JMenu. Będzie miał ten sam L & F jako JMenu, gdy podłączysz go do paska JMenuBar. Jedyną rzeczą, którą musisz zrobić, to ustawić rozmiar nowego „przycisk”, jako menedżera układu (nawet jeśli nie zostało ustawione) będzie zmieniać rozmiar tego elementu na podstawie własnych zasad:

http://www.javaworld.com/javaworld/jw-09-2000/jw-0922-javatraps.html

Sposób, w jaki to robisz, znajduje się pod tym linkiem (jeśli czujesz się nieswojo klikając na link, google dla "settize doesnt work" - będzie to w pierwszej dziesiątce wyników). Jeśli nie ustawisz właściwie rozmiaru, twój nowy "przycisk" wypełni pozostałą przestrzeń twojego JMenuBar.

wypróbować ten kod:

menuItem.setMinimumSize(someMenu.getSize()); 
menuItem.setPreferredSize(someMenu.getSize()); 
menuItem.setMaximumSize(someMenu.getSize()); 
menuItem.setActionCommand("ActionText"); 

setActionCommand() metoda będzie ustawić polecenie Akcja, tak że po kliknięciu nowego przycisku „” To będzie komenda działania przeszły przez argument zdarzenia działanie do działania wykonaną metodę, aby łatwo ją zidentyfikować:

public void actionPerformed(ActionEvent e) { 
    System.out.println(e.getActionCommand()); 
} 

Mam nadzieję, że to pomoże!

0

OK Postanowiłem zbadać to nieco dalej. Poniżej znajduje się omówienie i wydaje się, że działa podobnie jak JButton, ale wygląda jak jmenu na jmenubarze. Kod poniżej. (zauważ, że dodanie actionMistenera do JMenu nie działa poprawnie, co jest powodem dla mouselistener Dodajecie actionListener do menubutton tak jak normalny przycisk i tak długo, jak nie dodajecie żadnych menuitems do menubutton (co technicznie mogliście) pojawi się ona jako JMenu na JMenuBar ale zachowują się jak przycisk.

import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.lang.reflect.Method; 
import java.util.EventListener; 
import javax.swing.ImageIcon; 
import javax.swing.JMenu; 

public class MenuButton extends JMenu { 

private boolean startedIn = false; 
private ActionListener action; 

public MenuButton(String title) { 
    super(title); 
    removeListeners(this); 
    this.addMouseListener(new MenuButtonListener()); 

} 

public MenuButton(ImageIcon icon) { 
    super(); 
    removeListeners(this); 
    this.addMouseListener(new MenuButtonListener()); 
    this.setIcon(icon); 
} 

public void addActionListener(ActionListener a) { 
    action = a; 
} 
    //we need to remove all the listeners already associated with a JMenu. If we do 
//not do this, then it will not behave as expected because some mouseclicks are eaten 
//by these listeners. There is no easy way to do that, the following method is a 
//workaroundprovided in the java bug database. 
static private void removeListeners(Component comp) { 
    Method[] methods = comp.getClass().getMethods(); 
    for (int i = 0; i < methods.length; i++) { 
     Method method = methods[i]; 
     String name = method.getName(); 
     if (name.startsWith("remove") && name.endsWith("Listener")) { 

      Class[] params = method.getParameterTypes(); 
      if (params.length == 1) { 
       EventListener[] listeners = null; 
       try { 
        listeners = comp.getListeners(params[0]); 
       } catch (Exception e) { 
        // It is possible that someone could create a listener 
        // that doesn't extend from EventListener. If so, ignore 
        // it 
        System.out.println("Listener " + params[0] 
          + " does not extend EventListener"); 
        continue; 
       } 
       for (int j = 0; j < listeners.length; j++) { 
        try { 
         method.invoke(comp, new Object[] { listeners[j] }); 
         // System.out.println("removed Listener " + name + 
         // " for comp " + comp + "\n"); 
        } catch (Exception e) { 
         System.out 
           .println("Cannot invoke removeListener method " 
             + e); 
         // Continue on. The reason for removing all 
         // listeners is to 
         // make sure that we don't have a listener holding 
         // on to something 
         // which will keep it from being garbage collected. 
         // We want to 
         // continue freeing listeners to make sure we can 
         // free as much 
         // memory has possible 
        } 
       } 
      } else { 
       // The only Listener method that I know of that has more 
       // than 
       // one argument is removePropertyChangeListener. If it is 
       // something other than that, flag it and move on. 
       if (!name.equals("removePropertyChangeListener")) 
        System.out.println(" Wrong number of Args " + name); 
      } 
     } 
    } 
} 

public class MenuButtonListener extends MouseAdapter { 

    boolean within = false; 
    boolean pressed = false; 


    public void mousePressed(MouseEvent e) { 
     MenuButton.this.setSelected(true); 
     pressed = true; 
     //System.out.println("pressed"); 
    } 

    public void mouseReleased(MouseEvent e) { 
     //System.out.println("released"); 
     MenuButton.this.setSelected(false); 
     if (action != null && within && pressed) { 
      action.actionPerformed(new ActionEvent(this, 
        ActionEvent.ACTION_PERFORMED, null)); 
      MenuButton.this.setSelected(false); 
     } 
     pressed = false; 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) { 
     within = true; 
    } 

    @Override 
    public void mouseExited(MouseEvent e) { 
     within = false; 
    } 
} 
}