【问题标题】:Adding a clickable, action-firing JMenuItem directly to a JMenuBar?将可点击的、触发动作的 JMenuItem 直接添加到 JMenuBar?
【发布时间】:2009-12-07 20:02:05
【问题描述】:

有没有办法将 JMenuItem(或类似的按钮类型对象)添加到 JMenuBar?

添加 JMenuItem 并不能很好地配合 JMenuBar 的布局,并且按钮看起来太像按钮了。

我们应该调整按钮看起来像 JMenuItem 还是调整 JMenuBar 以正确显示 JMenuItem?还是完全不同的东西?

【问题讨论】:

    标签: java swing jmenubar


    【解决方案1】:

    以下代码实现了 camickr 的解决方案,尽管在看到 JMenuItems 以 JMenuBar 呈现的默认方式后,我会想出同样的事情。它看起来相当真实并且响应点击,但不响应助记符。

    我尝试提供 JMenuItems 加速器(请参阅代码),效果很好,但看起来很奇怪。

    public class TheDude19 extends JFrame {
    
       private class Action1 extends AbstractAction {
          private Action1() {
             super("Action1");
             putValue(MNEMONIC_KEY, (int) '1');
             // putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK));
          }
          public void actionPerformed(ActionEvent arg0) {
             System.out.println("Action 1!");
          }
       }
       private class Action2 extends AbstractAction {
          private Action2() {
             super("Action2");
             putValue(MNEMONIC_KEY, (int) '2');
          }
          public void actionPerformed(ActionEvent arg0) {
             System.out.println("Action 2!");
          }
       }
       private class NarrowMenuItem extends JMenuItem {
    
          public NarrowMenuItem(Action a) {
             super(a);
          }
          public Dimension getMaximumSize() {
             return new Dimension(super.getPreferredSize().width, super.getMaximumSize().height);
          }
       }
       public TheDude19() {
          JMenuItem menu1 = new NarrowMenuItem(new Action1());
          JMenuItem menu2 = new NarrowMenuItem(new Action2());
          JMenuBar mb = new JMenuBar();
          mb.add(menu1);
          mb.add(menu2);
          add(mb, BorderLayout.NORTH);
          setSize(400, 300);
       }
    
       public static void main(String[] args) {
          (new TheDude19()).setVisible(true);
       }
    
    }
    

    【讨论】:

      【解决方案2】:

      JMenuItem 不能很好地配合 JMenuBar 的布局

      菜单栏使用 BoxLayout,它会尝试将组件拉伸到最大尺寸。尝试使用:

      menuItem.setMaximumSize( menuItem.getPreferredSize() );
      

      如果您需要更多帮助,请发布您的 SSCCE 以显示问题。

      【讨论】:

      • 对我没用,左边有一些空白(JMenuItems 为图标保留空间)。
      【解决方案3】:

      只需调整 JButton。

      button= new JButton("MenuItem");
      button.setOpaque(true);
      button.setContentAreaFilled(false);
      button.setBorderPainted(false);
      button.setFocusable(false);
      button.addActionListener(new buttonHandler());
      menuBar.add(button);
      

      setContentAreaFilled 使其透明,
      setBorderPainted 去除边框,
      setFocusable 去除文本周围的小边框。

      【讨论】:

        【解决方案4】:

        也许您忘记了您的 JMenu。您需要将 JMenuItem 放在 JMenu 中,然后将 JMenu 添加到 JMenuBar。

        要构建菜单栏,您需要执行以下操作:

        JMenuBar myBar = new JMenuBar();
        
        JMenu fileMenu = new JMenu("File");
        
        JMenuItem newFileMenuItem = new JMenuItem("New");
        newFileMenuItem.addActionListener(new ActionListerner() { ... Define Action Handler here... });
        
        fileMenu.add(newFileMenuItem);
        
        myBar.add(fileMenu);
        

        【讨论】:

        • 不,我没有忘记任何事情。我对JMenuBar、JMenu、JMenuItem的结构了如指掌。我的问题是是否有办法完全“跳过”JMenu 并将 JMenuItem 直接添加到 JMenuBar。不过还是谢谢。
        • 我不相信有,听起来您在这种情况下正在寻找的是 JToolBar:java.sun.com/javase/6/docs/api 而不是 JMenuBar。
        • 您是否正在尝试使用 Linux 实用程序面板之类的功能,您可以在其中拥有别名链接和菜单?
        【解决方案5】:

        我最近发生了这样的事情,我有一个 JMenuBar,其中只有 2 个 JMenuItems(所以请注意,我没有在混合的 JMenu 和 JMenuItem 环境中尝试过。

        起初我最终将 Layout 更改为具有左对齐的 FlowLayout,但在组件之间留下了太多空间。我乱七八糟地尝试做各种事情,但很不满意。我最终做的只是使用了一个 JMenu,但覆盖了它的一些行为,以便它伪装成一个 JMenuItem。像这样:

            JMenuBar mainMenuBar = new JMenuBar();
            final JMenu quitMenuItem = new JMenu("Quit");
            quitMenuItem.addMenuListener(new MenuListener() {
                public void menuSelected(MenuEvent e) {
                    System.exit(0);
        
                }
                public void menuDeselected(MenuEvent e) {}
                public void menuCanceled(MenuEvent e) {}
            });
        
            quitMenuItem.setPopupMenuVisible(false);
            final JMenu aboutMenuItem = new JMenu("About");
        
            aboutMenuItem.addMenuListener(new MenuListener() {
                public void menuSelected(MenuEvent e) {
                    JOptionPane.showMessageDialog(MainFrame.this, "Assignment 3 With Swing UI. Author: T.Byrne", "About", JOptionPane.INFORMATION_MESSAGE);
                    aboutMenuItem.setSelected(false);//otherwise it will still be selected after the dialog box.  
                }
                public void menuDeselected(MenuEvent e) {}
        
                public void menuCanceled(MenuEvent e) {}
            });
            aboutMenuItem.setPopupMenuVisible(false);
            mainMenuBar.add(quitMenuItem);
            mainMenuBar.add(aboutMenuItem);
            this.setJMenuBar(mainMenuBar);
        

        【讨论】:

        • 问题是 menuSelected 事件可以在没有实际点击菜单的情况下被触发。您没有注意到这一点,因为您的菜单栏中没有常规菜单。如果您单击常规菜单以展开其弹出菜单,然后移至另一个菜单,则会自动选择该菜单并展开弹出菜单。如果您在特殊菜单上移动,则只需将鼠标悬停在其上即可退出应用程序,而无需单击它。
        【解决方案6】:

        是的。或者用简单的方法来做

        mb.add(new JMenuItem(closeAction) {
            public Dimension getMaximumSize() {
                return new Dimension(
                    super.getPreferredSize().width, 
                    super.getMaximumSize().height);
            }
        });
        

        它创建了一个类文件,但是没用。

        【讨论】:

          【解决方案7】:

          要让按钮看起来像 JMenu,只需添加一个翻转效果并移除按钮的边框(例如,请参见下面的代码)

          必需的导入

          import javax.swing.*;
          import java.awt.event.*;
          import javax.swing.event.*;
          import java.awt.Dimension;
          import java.awt.Color;
          

          代码

          JButton tstButton = new JButton(); //Button
          
          tstButton.setText("Test"); //Button Text
          
          tstButton.setOpaque(false); //These remove the button filling and border
          tstButton.setContentAreaFilled(false);
          tstButton.setBorder(null);
          tstButton.setFocusable(false);
          
          tstButton.setRolloverEnabled(true); //Allows the button to detect when mouse is over it
          tstButton.getModel().addChangeListener(new ChangeListener()
          {
              @Override
              public void stateChanged(ChangeEvent e) 
              {
                  ButtonModel model = (ButtonModel) e.getSource();
          
                  if(model.isRollover())
                  {
                      tstButton.setBackground(Color.RED); //Changes the colour of the button
                      tstButton.setOpaque(true);
                  } 
          
                  else 
                  {
                      tstButton.setBackground(null);
                      tstButton.setOpaque(false);
                  }
               }
          });
          
          Dimension dBt = new Dimension(75,25); //Sets the size of the button in the  JMenuBar
          tstButton.setMinimumSize(dBt);
          tstButton.setPreferredSize(dBt);
          tstButton.setMaximumSize(dBt);
          
          tstButton.setMnemonic('T'); //Allows you to press Alt+T on your keyboard to press the button
          
          tstButton.addActionListener(new ActionListener() //Adds action listener so it can do something
          {
              public void actionPerformed(ActionEvent e) 
              {
                  System.out.println("Button pressed");
              }
          });
          
          menuBar.add(tstButton); //Adds the button to the JMenuBar
          

          编辑

          有一种改进的方法可以做到这一点

          JButton tstButton = new JButton();
          tstButton.setVisible(false);
          tstButton.addActionListener(new CustomActionListener());
          
          menuBar.add(tstButton);
          
          JMenu menuButton = new JMenu();
          addHotKey(menuButton, "shift C", 'm', "Menu Button","pressed");
          menuButton.addMouseListener(new CustomMouseListener());
          menuButton.addMenuKeyListener(new CustomKeyListener());
          
          menuBar.add(menuButton);
          
          public void addHotKey(JMenu J, String s, char c, String S, String key)
          {
              Action buttonAction = new AbstractAction(S) 
              {
                  @Override
                  public void actionPerformed(ActionEvent evt) 
                  {
                      clcikComponent(tstButton);
                  }
              };
          
              J.setAction(buttonAction);
          
              buttonAction.putValue(Action.MNEMONIC_KEY, KeyEvent.getExtendedKeyCodeForChar(c));
          
              J.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
              KeyStroke.getKeyStroke(s), key);
          
              J.getActionMap().put(key, buttonAction);
          }
          
          class CustomMouseListener implements MouseListener
          {
              public void mouseClicked(MouseEvent e) 
              {
                  clcikComponent(m_Invisible);
              }
          
              public void mousePressed(MouseEvent e){}
          
              public void mouseReleased(MouseEvent e){}
          
              public void mouseEntered(MouseEvent e){}
          
              public void mouseExited(MouseEvent e){}
          }
          
          class CustomKeyListener implements MenuKeyListener
          {
              @Override
              public void menuKeyTyped(MenuKeyEvent e)
              {
                  char c = e.getKeyChar();
                  if(c==KeyEvent.VK_ENTER)
                  {
                      if(m_code.isSelected())
                      {
                          clcikComponent(m_Invisible);
                      }
                  }
              }
          
              @Override
              public void menuKeyPressed(MenuKeyEvent e){}
          
              @Override
              public void menuKeyReleased(MenuKeyEvent e){}
          }
          
          public void clcikComponent(JButton comp)
          {
              comp.doClick();
          }
          
          class CustomActionListener implements ActionListener
          {
              @Override
              public void actionPerformed(ActionEvent e)
              {
                  //Makes Button Perform Action
              }
          }
          

          【讨论】:

            【解决方案8】:

            让 UI 和代码看起来都不错需要一段时间。我们最终将鼠标适配器附加到 JMenu 的底层组件:

            JMenu selectData = new JMenu("Select data...");
            
            selectData.getComponent().addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    // Our code to open a window for choosing data series here...
                    // [...]
                }
            });
            
            menuBar.add(selectData);
            

            我想我们也会添加一个KeyAdapter,但还没有。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-17
              • 1970-01-01
              • 2010-11-02
              • 1970-01-01
              相关资源
              最近更新 更多