2013-02-12 5 views
1

Я хочу программно вызывать конкретный элемент в меню, которое нужно выбрать, и отображать как таковое, чтобы при нажатии Enter выполнялось соответствующее действие. К сожалению, я считаю, что ни JMenuItem.setSelected(), ни JPopupMenu.setSelectedItem() не делают то, что я хочу. В основном я хочу, чтобы произошло то, что происходит, когда нажата клавиша со стрелкой, или мышь перемещается в пространство определенного элемента - цвет фона изменяется, указывая на выбор. Я не программировал это, это просто происходит. Почему эти API не делают то же самое? Это сводит меня с ума. Это не должно быть так сложно. Есть ли какой-то API, который делает то, что я хочу?JMenuItem.setSelected() не изменяет внешний вид выбранного элемента?

+0

В 'setSelected()' управляет метод ли '' JCheckBoxMenuItem' или JRadioButtonMenuItem' имеет флажок рядом с ней. Это не относится к тому, выделен ли элемент. –

+0

Есть ли API, который делает? –

+0

После прочтения комментариев, я думаю, что мне не нравится ваш подход по многим причинам: (1) он не кажется задерживающим, если у вас несколько меню с одним включенным элементом (2) неожиданное поведение имеет меню auto-expand с включенным и включенным элементом только что включенным (3) Что делать, если во время изменения состояния в приложении, которое вызывает это, фокус на вашем фрейме также находится на интерактивном компоненте, таком как JButton? Кто побеждает в войне с пробелами? (4) Я делаю пользовательские интерфейсы в течение длительного времени и никогда не видел этого. Я стараюсь не изобретать велосипед, насколько это касается взаимодействия с пользователем. Только мои 2 цента. – splungebob

ответ

2

Это своего рода работал:

JMenuItem#setArmed(boolean); 

хотя вы не видите его, если не пересекать JMenus, чтобы попасть туда. Возможно, если вы назовете это в каждом меню над ним?

EDIT: Возможно, вам нужен ускоритель для вашего пункта меню? См: How To Use Menus: Enabling Keyboard Operation

+0

Это частично работает. Он меняет внешний вид.То, что он не делает, это запустить изменение состояния, которое позволяет нажать клавишу (), которая запускает текущее вооруженное действие. Другими словами, мне нужно вытащить мышь из вооруженного предмета, а затем снова войти, и как только я сделаю это, выполнит действие, на которое ссылается вооруженный элемент. Все, что я пытаюсь сделать, это «предварительно выбрать» элемент для действия по умолчанию. Должен быть простой способ сделать это. Sheesh! –

+0

Должен признаться, это кажется необычным требованием. Не могли бы вы уточнить, что вы пытаетесь выполнить? – splungebob

+0

У вас есть предварительно выбранный элемент в меню, для которого ничего, кроме нажатия пробела, не выполнит действие этого элемента, не требуя движения мыши или клавиши со стрелкой, чтобы «попасть туда». Это приложение очень ориентировано на клавиатуру. Использование мыши, хотя это возможно, устарело, и каждое действие должно быть выполнено с помощью нажатия клавиш. –

0

Это некрасиво, как грех, но это, в связи с setArmed splungebob (в) ответ выше является полное решение: Во-первых, сделать меню из MenuKeyListener и добавить ему в MenuKeyListener себе. Затем:

public void menuKeyReleased(MenuKeyEvent e) { 
    if (e.getModifiers() == 0) { 
     switch (e.getKeyCode()) { 
     case KeyEvent.VK_ENTER: 
     case KeyEvent.VK_SPACE: 
      for (MenuElement elem : this.getSubElements()) { 
       if (elem instanceof JMenuItem) { 
        JMenuItem item = (JMenuItem) elem; 
        if (item.isArmed()) { 
         Action action = item.getAction(); 
         if (action != null) { 
          action.actionPerformed(new ActionEvent(this, 0, null)); 
          e.consume(); 
          setVisible(false); 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Я не могу поверить, что это было так сложно. У Swing есть определенные ограничения, когда дело доходит до построения интерфейсов, ориентированных на клавиатуру.

1

java.awt.Robot может сделать трюк;)
Рассмотрим код, указанный ниже:

import javax.swing.JFrame; 
import javax.swing.JButton; 
import javax.swing.JMenu; 
import javax.swing.JMenuItem; 
import javax.swing.JMenuBar; 
import javax.swing.JOptionPane; 
import javax.swing.JPopupMenu; 
import javax.swing.SwingUtilities; 
import java.awt.Dimension; 
import java.awt.BorderLayout; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.Robot; 
public class JMenuFrame extends JFrame implements ActionListener 
{ 
    JMenuBar bar; 
    JMenu menu ; 
    String[] items; 
    JMenuItem[] menuItems; 
    JButton start; 
    Robot robot; 
    public void prepareAndShowGUI() 
    { 
     try 
     { 
      robot = new Robot();  
     } 
     catch (Exception ex){} 
     bar = new JMenuBar(); 
     menu = new JMenu("File"); 
     items = new String[]{"Open","Save","Save As","Quit"}; 
     menuItems = new JMenuItem[items.length]; 
     start = new JButton("Click me"); 
     for (int i = 0 ; i < items.length ; i++) 
     { 
      menuItems[i] = new JMenuItem(items[i]); 
      menuItems[i].addActionListener(this); 
      menu.add(menuItems[i]); 
     } 
     bar.add(menu); 
     setJMenuBar(bar); 
     start.addActionListener(this); 
     getContentPane().add(start,BorderLayout.SOUTH); 
     setPreferredSize(new Dimension(300,400)); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 
    @Override 
    public void actionPerformed(ActionEvent evt) 
    { 
     if ("Click me".equals(evt.getActionCommand())) 
     { 
      menu.doClick(); 
      if (robot!=null) 
      { 
       for (int i = 0 ; i<=2 ; i++) //Suppose you want to select 3rd MenuItem 
       { 
        if (!menuItems[i].isEnabled()) 
        { 
         continue; 
        } 
        robot.keyPress(KeyEvent.VK_DOWN); 
        robot.keyRelease(KeyEvent.VK_UP); 
       } 
      } 
     } 
     else 
     { 
      JOptionPane.showMessageDialog(this,evt.getActionCommand()+" is pressed","Information",JOptionPane.INFORMATION_MESSAGE); 
     } 
    } 
    public static void main(String st[]) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       JMenuFrame mf = new JMenuFrame(); 
       mf.prepareAndShowGUI(); 
      } 
     }); 
    } 
} 
+0

Интересно. Раньше я никогда не слышал о java.awt.Robot. –

+0

Да .. действительно использующий .. !! –

+0

+1 для 'doClick()', также видно [здесь] (http://stackoverflow.com/a/7137801/230513) и [здесь] (http://stackoverflow.com/a/5797965/230513). – trashgod

0

Хотя я не уверен, что согласен с требованиями (см мой комментарий в ОП), я все еще хотел, чтобы дать это трещина. Первая половина кода - это просто настройка GUI, чтобы пользователь мог выполнить условие.

- Меню создано с 3-мя элементами, а для управления состоянием элементов меню создаются 3 отдельные флажки.

- Если в любой момент включен только один пункт меню, автоматически разворачивайте меню и «предварительно выберите» элемент. Код для автоматического расширения меню был сорван с JMenu.

- Добавить MenuKeyListener в меню, чтобы захватить пользователя, нажимая пробел, когда дерево меню расширено.

import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 

import javax.swing.*; 
import javax.swing.event.*; 

public class JMenuDemo implements Runnable 
{ 
    private final String[] ACTIONS = new String[]{"Open", "Print", "Close"}; 

    private JMenu fileMenu; 
    private JMenuItem[] menuItems; 
    private JCheckBox[] checkBoxes; 

    public static void main(String args[]) 
    { 
    SwingUtilities.invokeLater(new JMenuDemo()); 
    } 

    public void run() 
    { 
    JPanel panel = new JPanel(new GridLayout(0,1)); 
    panel.setBorder(BorderFactory.createTitledBorder("Enabled")); 

    menuItems = new JMenuItem[ACTIONS.length]; 
    checkBoxes = new JCheckBox[ACTIONS.length]; 

    for (int i = 0; i < ACTIONS.length; i++) 
    { 
     final int index = i; 
     final String action = ACTIONS[i]; 

     menuItems[i] = new JMenuItem(action); 
     menuItems[i].setAccelerator(KeyStroke.getKeyStroke(action.charAt(0), 
            ActionEvent.ALT_MASK)); 
     menuItems[i].setMnemonic(action.charAt(0)); 
     menuItems[i].addActionListener(new ActionListener() 
     { 
     public void actionPerformed(ActionEvent event) 
     { 
      System.out.println(action); 
     } 
     }); 

     checkBoxes[i] = new JCheckBox(action); 
     checkBoxes[i].setSelected(true); 
     checkBoxes[i].addItemListener(new ItemListener() 
     { 
     public void itemStateChanged(ItemEvent event) 
     { 
      checkBoxChanged(index); 
     } 
     }); 
     panel.add(checkBoxes[i]); 
    } 

    JFrame frame = new JFrame("Demo"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setJMenuBar(createJMenuBar()); 
    frame.add(panel, BorderLayout.SOUTH); 
    frame.setSize(300, 400); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
    } 

    private void checkBoxChanged(int index) 
    { 
    menuItems[index].setEnabled(checkBoxes[index].isSelected()); 
    evaluate(); 
    } 

    private JMenuBar createJMenuBar() 
    { 
    fileMenu = new JMenu("File"); 
    fileMenu.setMnemonic('F'); 
    fileMenu.addMenuKeyListener(new MenuKeyListener() 
    { 
     @Override 
     public void menuKeyTyped(MenuKeyEvent event) 
     { 
     autoClick(event); 
     } 

     @Override 
     public void menuKeyPressed(MenuKeyEvent event) {} 

     @Override 
     public void menuKeyReleased(MenuKeyEvent event) {} 
    }); 

    for (int i = 0; i < menuItems.length; i++) 
    { 
     fileMenu.add(menuItems[i]); 
    } 

    JMenuBar menuBar = new JMenuBar(); 
    menuBar.add(fileMenu); 

    return menuBar; 
    } 

    private void autoClick(MenuKeyEvent event) 
    { 
    if (event.getModifiers() == 0 && event.getKeyChar() == KeyEvent.VK_SPACE) 
    { 
     for (JMenuItem menuItem : menuItems) 
     { 
     if (menuItem.isArmed()) 
     { 
      menuItem.doClick(); 
      MenuSelectionManager.defaultManager().setSelectedPath(null); 
     } 
     } 
    } 
    } 

    private void evaluate() 
    { 
    JMenuItem onlyOne = null; 

    for (JMenuItem menuItem : menuItems) 
    { 
     menuItem.setArmed(false); 

     if (menuItem.isEnabled()) 
     { 
     if (onlyOne == null) 
     { 
      onlyOne = menuItem; 
     } 
     else 
     { 
      onlyOne = null; 
      break; 
     } 
     } 
    } 

    // Show the path if only one is enabled 
    if (onlyOne != null) 
    { 
     onlyOne.setArmed(true); 
     MenuElement me[] = buildMenuElementArray(fileMenu); 
     MenuSelectionManager.defaultManager().setSelectedPath(me); 
    } 
    } 

    /* 
    * Copied from JMenu 
    */ 
    private MenuElement[] buildMenuElementArray(JMenu leaf) 
    { 
    Vector<JComponent> elements = new Vector<JComponent>(); 
    Component current = leaf.getPopupMenu(); 

    while (true) 
    { 
     if (current instanceof JPopupMenu) 
     { 
     JPopupMenu pop = (JPopupMenu) current; 
     elements.insertElementAt(pop, 0); 
     current = pop.getInvoker(); 
     } 
     else if (current instanceof JMenu) 
     { 
     JMenu menu = (JMenu) current; 
     elements.insertElementAt(menu, 0); 
     current = menu.getParent(); 
     } 
     else if (current instanceof JMenuBar) 
     { 
     JMenuBar bar = (JMenuBar) current; 
     elements.insertElementAt(bar, 0); 
     MenuElement me[] = new MenuElement[elements.size()]; 
     elements.copyInto(me); 
     return me; 
     } 
    } 
    } 
} 
0
jMenu1.doClick(); // this open the menu again 

 Смежные вопросы

  • Нет связанных вопросов^_^