Добавляете активируемый JMenuItem с активным действием прямо в JMenuBar? - PullRequest
4 голосов
/ 07 декабря 2009

Есть ли способ добавить JMenuItem (или подобный объект типа кнопки) в JMenuBar?

Добавление JMenuItem не очень хорошо сочетается с макетом JMenuBar, а кнопки выглядят слишком кнопочно.

Должны ли мы настраивать кнопку, чтобы она выглядела как JMenuItem, или настраивать JMenuBar для корректного отображения JMenuItem? Или что-то совсем другое?

Ответы [ 7 ]

3 голосов
/ 08 декабря 2009

Следующий код реализует решение camickr, хотя я бы придумал то же самое, увидев способ отображения по умолчанию JMenuItem s в 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 голосов
/ 07 декабря 2009

JMenuItem плохо играет с макет JMenuBar

Menubar использует BoxLayout, который попытается растянуть компонент до его максимального размера. Попробуйте использовать:

menuItem.setMaximumSize( menuItem.getPreferredSize() );

Если вам нужна дополнительная помощь, опубликуйте свою SSCCE с указанием проблемы.

1 голос
/ 04 марта 2015

Просто настройте 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 избавляется от крошечной рамки вокруг текста.

0 голосов
/ 02 июня 2015

Чтобы кнопка выглядела как 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
    }
}
0 голосов
/ 18 мая 2012

Да. Или сделай это простым способом

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

Создает файл класса, но ме.

0 голосов
/ 01 марта 2012

У меня было что-то подобное недавно, у меня был 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);
0 голосов
/ 07 декабря 2009

Может быть, вы забыли свое 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);
...