将可点击、触发操作的 JMenuItem 直接添加到 JMenuBar?

发布于 2024-08-14 01:21:07 字数 182 浏览 8 评论 0原文

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

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

我们应该调整按钮以使其看起来像 JMenuItem,还是调整 JMenuBar 以正确显示 JMenuItem?或者完全是别的什么?

Is there a way to add a JMenuItem (or similar button-type object) to a JMenuBar?

Adding a JMenuItem doesn't play well with the layout of a JMenuBar, and buttons look too button-like.

Should we be tweaking the button to look like a JMenuItem or tweaking the JMenuBar to display the JMenuItem correctly? Or something else altogether?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

美人骨 2024-08-21 01:21:07

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

我尝试提供 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);
   }

}

The following code implements camickr's solution, although I would have come up with the same thing after seeing the default way JMenuItems are rendered in a JMenuBar. It looks reasonably authentic and responds to clicks, but not to the mnemonic.

I tried giving the JMenuItems accelerators (see code) and that works but that looks really weird.

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);
   }

}
情栀口红 2024-08-21 01:21:07

JMenuItem 与
JMenuBar 的布局

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

menuItem.setMaximumSize( menuItem.getPreferredSize() );

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

JMenuItem doesn't play well with the
layout of a JMenuBar

A menubar use a BoxLayout which will try to strech the component to its maximum size. Try using:

menuItem.setMaximumSize( menuItem.getPreferredSize() );

If you need more help post your SSCCE showing the problem.

失去的东西太少 2024-08-21 01:21:07

只需调整 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 消除了文本周围的小边框。

Just tweak the 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 makes it see-through,
setBorderPainted gets rid of the border,
setFocusable gets rid of the tiny border around the text.

缺⑴份安定 2024-08-21 01:21:07

也许您忘记了 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);

Maybe you're forgetting your JMenu. You need to put the JMenuItem in a JMenu, then you add the JMenu to the JMenuBar.

To build a menu bar you need to do something like the following:

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);
吃素的狼 2024-08-21 01:21:07

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

首先,我最终将布局更改为左对齐的 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);

I had something like this happen recently I had a JMenuBar that only had 2 JMenuItems in (so note that I haven't tried this in a mixed JMenu and JMenuItem environment.

At first I ended up changing the Layout to a FlowLayout with a left alignment, but that left too much space in-between the components. I messed around with trying to do various things, but was very unsatisfied. What I ended up doing was just using a JMenu, but overriding some of it's behaviors so that it pretended to be a JMenuItem. Like so:

    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);
静谧 2024-08-21 01:21:07

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

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

它会创建一个类文件,但是嗯。

Yup. Or do it the easy way

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

It creates a class file, but meh.

喜爱皱眉﹌ 2024-08-21 01:21:07

要使按钮看起来像 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
    }
}

To get the button to look like a JMenu just add a rollover effect and remove the border of the button (See code below for example)

Required imports

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

Code

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

Edit

There is a much improved way to do this

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
    }
}
时常饿 2024-08-21 01:21:07

让 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,但目前还没有。

Getting the UI and the code both to look good took a while. We ended up attaching a mouse adapter to the JMenu's underlying component:

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);

I guess we'll add a KeyAdapter as well, but haven't yet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文