Adding a JScrollPane to a JMenu - java

I have a JMenu which will include JMenuItems that are generated on start-up from a database. As such, it's quite likely that the menu will be too large and run off the screen.
As such, I am trying to add a JScrollPane to the JMenu.
Example, to the effect of;
JMenu employeesMenu = new JMenu("Employees");
JScrollPane emScroll = new JScrollPane();
JList contents = new JList();
contents.add(new JRadioButton("1"));
contents.add(new JRadioButton("2"));
contents.add(new JRadioButton("3"));
// ... etc
emScroll.add(contents);
employeesMenu.add(emScroll);
Now, my understanding is that a JMenu's contents are stored in a JList inside a JPopupMenu. So my question now is, what is a way of forcing that JList into a JScrollPane? Alternatively, is it possible to use a JScrollBar instead? Any input appreciated.

Maybe you can use Darryl's Menu Scroller approach. It adds arrow buttons at the top/bottom of the menu when required.

The below shows how to add JScrollPane to a JMenu. JLabel components are used as menu items below, as JMenuItem seems that can't be used in a JScrollPane. A mouseListener is added to each JLabel to mimic the JMenuItem behaviour, i.e., changing colors on mouse entering/exiting, as well as taking action on clicking an item (in this case, the text of the label is printed out, which can be used to decide what follows next). One may need to adjust the scrollPane.setPreferredSize, as well as the colours when the mouse enters/exits an item (even though, for convenience, the default colours used by the current LookAndFeel for the JMenuItem are used), as required.
The reason for using <html> tags in the text of the JLabel is to allow the background colour (when you move your mouse over the items) to fill the width of each item in the JScrollPane, rather than applying background colour only up to where the text ends. The <html> tags are removed when reading the text of the selected item/label.
MenuExample.java
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class MenuExample {
Random rand = new Random();
Color menuBackCol;
Color mItemBackCol;
Color mItemForegCol;
Color mItmSelBackCol;
Color mItmSelForegCol;
MenuExample() {
menuBackCol = UIManager.getColor("Menu.background");
mItemBackCol = UIManager.getColor("MenuItem.background");
mItemForegCol = UIManager.getColor("MenuItem.foreground");
mItmSelBackCol = UIManager.getColor("MenuItem.selectionBackground");
mItmSelForegCol = UIManager.getColor("MenuItem.selectionForeground");
Box box = new Box(BoxLayout.Y_AXIS);
for (int i = 0; i < 250; i++) {
box.add(Box.createRigidArea(new Dimension(0, 2))); // creates space between the components
JLabel lbl = new JLabel("<html>  " + i + ": " + rand.nextInt(10000) + "</html>");
lbl.setOpaque(true);
lbl.setBackground(mItemBackCol);
lbl.addMouseListener(
new LabelController(lbl, mItemBackCol, mItemForegCol, mItmSelBackCol, mItmSelForegCol));
box.add(lbl);
}
JScrollPane scrollPane = new JScrollPane(box);
scrollPane.getVerticalScrollBar().setUnitIncrement(20); // adjusts scrolling speed
scrollPane.setPreferredSize(new Dimension(100, 300));
scrollPane.setBorder(BorderFactory.createEmptyBorder());
scrollPane.getViewport().setBackground(menuBackCol);
JMenuBar mb = new JMenuBar();
JMenu menu = new JMenu("Menu");
JMenu submenu = new JMenu("Sub Menu");
submenu.add(scrollPane);
menu.add(new JMenuItem("Item 1"));
menu.add(new JMenuItem("Item 2"));
menu.add(new JMenuItem("Item 3"));
menu.add(submenu);
mb.add(menu);
JFrame f = new JFrame("Menu with ScrollBar Example");
f.setJMenuBar(mb);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(640, 480);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String args[]) {
new MenuExample();
}
}
LabelController.java
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LabelController implements MouseListener {
JLabel lbl;
Color mItemBackCol;
Color mItemForegCol;
Color mItmSelBackCol;
Color mItmSelForegCol;
public LabelController(JLabel lbl, Color mItemBackCol, Color mItemForegCol, Color mItmSelBackCol,
Color mItmSelForegCol) {
this.lbl = lbl;
this.mItemBackCol = mItemBackCol;
this.mItemForegCol = mItemForegCol;
this.mItmSelBackCol = mItmSelBackCol;
this.mItmSelForegCol = mItmSelForegCol;
}
#Override
public void mouseClicked(MouseEvent e) {
String selectedText = lbl.getText().replaceAll("<[^>]*>", "").replace(" ","").trim();
System.out.println(selectedText);
javax.swing.MenuSelectionManager.defaultManager().clearSelectedPath(); // close the menu
lbl.setBackground(mItemBackCol);
lbl.setForeground(mItemForegCol);
}
#Override
public void mouseEntered(MouseEvent e) {
lbl.setBackground(mItmSelBackCol);
lbl.setForeground(mItmSelForegCol);
}
#Override
public void mouseExited(MouseEvent e) {
lbl.setBackground(mItemBackCol);
lbl.setForeground(mItemForegCol);
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
}

Related

Adding JPanel into another JPanel using JButton with addActionListener

The commented codes are the problem. When I am using them, panels are added successfully, but I don't need these commented code anymore but same code is not working after I remove or comment those blocks.
Those codes that I have commented need to be removed. Without those commented codes, program runs but does not add panels. I use IntelliJ for my Java Project.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Test extends JFrame{
JPanel panel;
JButton send;
JTextField text;
JPanel chatArea;
boolean typing;
Test(){
setSize(365,515);
setLocation(50,100);
setLayout(null);
panel = new JPanel();
panel.setLayout(null);
panel.setBounds(0,0,350,60);
panel.setBackground(new Color(90000000));add(panel);
JLabel name = new JLabel("IRONMAN");
name.setFont(new Font("SAN_SERIF", Font.PLAIN,14));
name.setForeground(Color.white);
name.setBounds(110,35,120,20);panel.add(name);
text = new JTextField();
text.setBounds(15,430,260,40);
text.setFont(new Font("SAN_SERIF",Font.PLAIN,14));
text.setForeground(Color.BLUE);
// Timer timer = new Timer(1, event -> {
// if (!typing){
// name.setText("IRONMAN");
// }
// });
// timer.setInitialDelay(2000);
// text.addKeyListener(new KeyAdapter() {
// #Override
// public void keyPressed(KeyEvent e) {
// name.setText("IRONMAN typing...");
// timer.stop();
// typing = true;
// }
// #Override
// public void keyReleased(KeyEvent e) {
// typing = false;
// if (!timer.isRunning()){
// timer.start();
// }
// }
// });
add(text);
chatArea = new JPanel();
chatArea.setBounds(5,65,340,350);
add(chatArea);
send = new JButton("Send");
send.setBounds(280,430,65,30);
send.setBackground(new Color(200,120,255));
send.setForeground(new Color(7,95,75));
send.addActionListener(e -> {
String message = "STARK: "+text.getText();
JPanel p2 = formatLabel(message);
chatArea.add(p2);
text.setText("");
});
add(send);
}
private JPanel formatLabel(String message) {
JPanel p3 = new JPanel();
JLabel label1 = new JLabel("<html><p style = \"width : 150px\">" + message + "</p></html>");
label1.setBackground(new Color(200,120,255));
label1.setForeground(new Color(7,95,75));
label1.setFont(new Font("SAN_SERIF",Font.PLAIN,18));
label1.setOpaque(true);
label1.setBorder(new EmptyBorder(15,15,15,70));
p3.add(label1);
return p3;
}
public static void main(String[] args) {
Test t = new Test();
t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.setVisible(true);
}
}
First off all some general comments:
label1.setBorder(new EmptyBorder(15,15,15,70));
Don't be afraid to use whitespace. For example
label1.setBorder(new EmptyBorder(15, 15, 15, 70));
It is easier for our eyes to see text with whitespace.
setLayout(null);
Don't use a null layout. Swing was designed to be used with layout managers. You can easily use the default BorderLayout of the JFrame. Add:
the top panel to BorderLayout.PAGE_START
the chat panel to BorderLayout.PAGE_CENTER
the bottom panel to BorderLayout.PAGE_END
after I remove or comment those blocks.
That code is not the solution or the problem.
The problem is that a component has a size of (0, 0) so there is nothing to paint.
In your existing code try resizing the frame by making it wider. The panel will appear. This is because the resizing will cause the layout manager to be invoked which will give the panel a size so it can be painted.
In your code you need to use:
chatArea.add(p2);
chatArea.revalidate();
The revalidate() will automatically invoke the layout manager.

How to use DefaultEditorKit in an AbstractAction

My notepad program that I'm writing uses AbstractActions for each item in the JMenuBar, and I want to keep it consistent that way throughout my code. And now I'm implementing Cut, Copy, Paste into the program but I'm unsure of how to do that with Action.
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.text.DefaultEditorKit;
public class Home {
static Action Cut = new AbstractAction("Cut-Action") {
public void actionPerformed(ActionEvent e) {
// Where I want to use cut
new DefaultEditorKit.CutAction();
}
};
static public JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Edit");
menu.add(Cut); // Adds the cut action
// adds the non-action method
JMenuItem item = new JMenuItem(new DefaultEditorKit.CutAction());
item.setText("Cut-NonAction");
menu.add(item);
menuBar.add(menu);
return menuBar;
}
public static void main(String[] args) {
JFrame frame = new JFrame("Home");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = createMenuBar();
frame.add(menuBar, BorderLayout.NORTH);
JTextPane txt = new JTextPane();
JScrollPane s = new JScrollPane(txt);
frame.add(s, BorderLayout.CENTER);
frame.setSize(400, 300);
frame.setVisible(true);
}
}
How would I be able to use the cut action in my abstract action??
I figured it out with a little bit of trial and error.
I changed this code:
public void actionPerformed(ActionEvent e) {
new DefaultEditorKit().CutAction();
}
to:
public void actionPerformed(ActionEvent e) {
Action cut = new DefaultEditorKit.CutAction();
cut.actionPerformed(e);
}
How would I be able to use the cut action in my abstract action??
Why are you trying to do this? The is not the way to use the Actions from the editor kit.
This is the proper way to use the actions:
JMenuItem item = new JMenuItem(new DefaultEditorKit.CutAction());
Or if you happen to need the CutAction on a menu and on a toolbar you would use code like:
Action cut = new DefaultEditorKit.CutAction();
cut.putValue(Action.NAME, "Cut");
JMenuItem cutMenuItem = new JMenuItem( cut );
JButton cutButton = new JButton( cut );
Now the same Action is shared which means you can enable/disable the Action and both components will be affected. Read the section from the Swing tutorial on How to Use Actions for more information and examples.

ColorChooser by clicking JMenu Item

I tried codes from different site's and one from here about a color. How do I get color chooser to work with the press of a jmenu item?
I looked at ColorChooser Example and also Oracle Color Chooser Example and then implementing into the original class using the following code:
JMenuItem clr = new JMenuItem("Font Color");
clr.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
ColorChooserDemo ccd = new ColorChooserDemo();
ccd.setVisible(true);
}
});
But this seems do do nothing when I press the menu item.
The class code is from the oracle webpage. These are the following class I use (shortened of course to the problem at hand). I'm making a notepad program as i'm getting back into programming and refreshing my memory of how to do things in java. Problem at hand is, I am unable to get the color chooser to come up when I click on the jmenuitem clr (which is font color) the following code show's what I have so far:
Color Chooser Class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
/* ColorChooserDemo.java requires no other files. */
#SuppressWarnings("serial")
public class ColorChooserDemo extends JPanel
implements ChangeListener {
protected JColorChooser tcc;
protected JLabel banner;
public ColorChooserDemo() {
super(new BorderLayout());
//Set up color chooser for setting text color
tcc = new JColorChooser();
tcc.getSelectionModel().addChangeListener(this);
tcc.setBorder(BorderFactory.createTitledBorder(
"Choose Text Color"));
add(tcc, BorderLayout.PAGE_END);
}
public void stateChanged(ChangeEvent e) {
Color newColor = tcc.getColor();
FirstWindow.ta1.setForeground(newColor);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("ColorChooserDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new ColorChooserDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Main Class:
import java.awt.EventQueue;
public class Main{
protected static Object fw;
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
try
{
FirstWindow fw = new FirstWindow();
fw.setVisible(true);
} catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}
FirstWindow class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
public class FirstWindow extends JFrame {
private static final long serialVersionUID = 1L;
protected JColorChooser tcc;
protected static JTextArea ta1;
public FirstWindow() {
super("Note Pad");
Font font = new Font("Verdana", Font.BOLD, 12);
//Setting the size of the note pad
setSize(650, 745);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//Create the MenuBar
JMenuBar mb = new JMenuBar();
setJMenuBar(mb);
//Create the panel to hold everything in
JPanel p = new JPanel();
//Create the Text Area
final JTextArea ta1 = new JTextArea();
ta1.setFont(font);
ta1.setMargin(new Insets(5,5,5,5));
ta1.setLineWrap(true);
ta1.setWrapStyleWord(true);
//Create the Scroll Pane to hold the Text Area
final JScrollPane sp = new JScrollPane(ta1);
sp.setPreferredSize(new Dimension(625,675));
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
//Create the menu's
JMenu format = new JMenu("Format");
//Create menu item for picking font color
JMenuItem clr = new JMenuItem("Font Color");
clr.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
ColorChooserDemo ccd = new ColorChooserDemo();
ccd.setVisible(true);
}
});
//adding the menu items to the file menu tab
//adding menu items to the edit tab
//adding menu items to the format tab
format.add(clr);
//adding the menus to the menu bar
mb.add(format);
//adding the scroll pane to the panel
p.add(sp);
add(p, BorderLayout.CENTER);
}
}
Probably the easiest way to show the ColorChooser is the following:
In the ColorChooserDemo class, you have the method private static void createAndShowGUI(), which you should declare public.
Then, replace the ActionListener for the menu item to the following:
clr.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
ColorChooserDemo.createAndShowGUI();
}
});
Your ColorChooserDemo class extends JPanel, not JFrame. You first need a JFrame, then add the panel, then show the JFrame. This is what happens in the createAndShowGUI() method.
Edit:
I understood that you only wanted to know how to show the ColorChooserDemo when selecting a menu item.
However, to actually set the color, you might want to skip using your own ColorChooserDemo class, and replace the ActionListener code with the following:
clr.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
Color c = JColorChooser.showDialog(ta1, "ColorChooserDemo", null);
ta1.setForeground(c);
}
});
An SSCE is easier not only for us to provide a solution, as Andrew suggested, but it may also help you figure out and understand what to do. Anyway, here's a quick example of opening a colour chooser after pressing a JMenuItem:
item.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JColorChooser jColorChooser = new JColorChooser();
JDialog jDialog = new JDialog();
jDialog.setContentPane(jColorChooser);
jDialog.pack();
jDialog.setVisible(true);
}
});
LE: (sorry, new to colour choosers myself) or just use JColorChooser.showDialog()

JFrame's getFocusOwner() not being helpful

I am working with a Swing program and having a little trouble. The program has two windows (both are JFrames). The main window is just fine and should not be relevant to this issue.
The window I am having issues with contains a JScrollPane with a JPanel in it, and has a JMenuBar. The JPanel has a bunch of JTextComponents (some JTextFields, some JTextAreas) on it.
What I want to do is have an ActionListener attached to a JMenuItem find the JTextComponent that has focus.
I have seen the previous posts at focused component reference and How to find out which object currently has focus. My issue is that calling the particular window's getFocusOwner() method merely returns the JFrame's JRootPane, which is utterly unhelpful. Both the JScrollPane and the JPanel in question are focusable according to their isFocusable() methods. This happens even if I actually enter text into one of the JTextComponents before clicking the menu item. The cursor still blinks in the text field while I open the menu, and everything. For what it's worth, getMostRecentFocusOwner() also simply returns the JRootPane.
If you use TextActions, the action knows which JTextComponent has the focus. I've modified some code that I found here to show that even if the TextActions come from one JTextArea, they still will automatically work on any and all text components that have focus:
import java.awt.GridLayout;
import javax.swing.*;
public class TextActionExample {
public static void main(String[] args) {
// Create a text area.
JTextArea ta = new JTextArea(15, 30);
ta.setLineWrap(true);
// Add all actions to the menu (split into two menus to make it more
// usable).
Action[] actions = ta.getActions();
JMenuBar menubar = new JMenuBar();
JMenu actionmenu = new JMenu("Actions");
menubar.add(actionmenu);
JMenu firstHalf = new JMenu("1st Half");
JMenu secondHalf = new JMenu("2nd Half");
actionmenu.add(firstHalf);
actionmenu.add(secondHalf);
int mid = actions.length / 2;
for (int i = 0; i < mid; i++) {
firstHalf.add(actions[i]);
}
for (int i = mid; i < actions.length; i++) {
secondHalf.add(actions[i]);
}
JTextField textField = new JTextField(20);
JPanel textFieldPanel = new JPanel();
textFieldPanel.add(textField);
JPanel mainPanel = new JPanel(new GridLayout(1, 0, 5, 5));
mainPanel.add(new JScrollPane(ta));
mainPanel.add(new JScrollPane(new JTextArea(15, 30)));
mainPanel.add(textFieldPanel);
// Show it . . .
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(mainPanel);
f.setJMenuBar(menubar);
f.pack();
f.setVisible(true);
}
}
This is very interesting stuff that I have to learn more about.
I think I have solved this, because of the fact that you lose focus when you click on a menu item, we simply have to wait for focus to return to the component before we check who has focus, I have done this using a swing timer that waits 100ms and then executes its method to check which component has focus:
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.TimerTask;
import javax.swing.*;
public class JavaApplication180 extends JFrame {
private JTextField[] JTextFields;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem item;
public JavaApplication180() {
initComponents();
createAndShowUI();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JavaApplication180();
}
});
}
private void createAndShowUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridLayout(2, 2, 10, 10));
setJMenuBar(menuBar);
addComponentsToPane();
pack();
setVisible(true);
}
private void initComponents() {
JTextFields = new JTextField[4];
menuBar = new JMenuBar();
item = new JMenuItem("Who has focus?");
item.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
TimerTask tt = new TimerTask() {
#Override
public void run() {
JOptionPane.showMessageDialog(null, getMostRecentFocusOwner().getName());
}
};
new java.util.Timer().schedule(tt, 100);
}
});
menu = new JMenu("File");
menu.add(item);
menuBar.add(menu);
}
private void addComponentsToPane() {
for (int i = 0; i < JTextFields.length; i++) {
JTextFields[i] = new JTextField();
JTextFields[i].setText(String.valueOf(i));
JTextFields[i].setName(String.valueOf(i));
getContentPane().add(JTextFields[i]);
}
}
}
I'm probably too late, but I just did the following in my JFrame constructor.
this.rootPane.setFocusable(false);
Now
getFocusOwner()
will return the current JTextComponent instead of the rootPane.
I then used this code in an ActionListener attached to my JMenuItem to select the text within it.
if (getFocusOwner() instanceof JTextField)
{
((JTextField) getMostRecentFocusOwner()).selectAll();
}
It should be noted that If you have a JScrollPane etc, you may have to use setFocusable(false) on all the components between the rootPane and the textfields.
Hope this helps anyone else with the same issue!
Source: Personal Experience
When I've needed this, I wrote a focus listener. I had a JPanel with two columns of JTextFields and the focus listener kept track of which column was last used by the user. I enablesd the user to enter some text into that last focused column with a button click. You would use just one instance of your FocusListener for all text fields and have a field referencing the most recently focused component. Your menu action can then query that field to determine which text field to use.
See http://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html

Java swing: how to align menu items in rows and columns?

I'm have no trouble when creating menu bar and its item. But now, when I get a question how to make the menu items appeared as column & rows-like table shaped, I really don't know about that.
The goals is to create this kind of menu items using java.
Check this link.
And right now, I just think that I should use a jpanel as menu item, and then applying a flowlayout and then adding many jlabel(s) as I could as menuitem inside the grid. But wouldn't it worst?
What's the best deal to create the menu items such as the image preview on the above links?
I tried google, but found no related cases. CMIIW.
The popup menu of a JMenu instance is a standard container, so you can add to it whatever you want. It has a default layout, but you can change it.
Something like in your mockup is created by this code:
import javax.swing.*;
import java.awt.*;
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Menu test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(600, 400));
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Test");
JPopupMenu popupMenu = menu.getPopupMenu();
popupMenu.setLayout(new GridLayout(5, 5));
for (int r = 0; r < 5; r++) {
for (int c = 0; c < 5; c++) {
popupMenu.add(new JMenuItem("(" + (r + 1) + ", " + (c + 1) + ")"));
}
}
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.setVisible(true);
}
});
}
}
I haven't seen a ready made component for anything like this. So I think you are on your own.
I see two possibilities:
JMenuItem is a JComponent, so you can add other components to it. You probably want to use some kind of grid based layout and add buttons or labels for the numbers.
Implement you own JMenuItem that displays your grid component instead of the normal JPopupMenu
In any case have a look at the source code of JMenu(Item) in order to understand how these components work.
The simplest solution is just set the layout of JMenu's JPopupMenu and then add items like you normally would. There's no need to create a subclass.
Example:
import javax.swing.*;
import java.awt.*;
public class menu {
public static void main(String ... args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("A regular menu");
menu.add(new JMenuItem("Menu item"));
JMenu gridMenu = new JMenu("Menu with grid");
// This does the trick:
gridMenu.getPopupMenu().setLayout(new GridLayout(2, 2));
gridMenu.add("Top left");
gridMenu.add("Top right");
gridMenu.add("Bottom left");
gridMenu.add("Bottom right");
menu.add(gridMenu);
menuBar.add(menu);
JFrame frame = new JFrame("Menus");
frame.setJMenuBar(menuBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}

Categories