Exit option with my menu in my window - java

The code is here:
I don't think the System.exit(); is working properly.
Am I using the wrong method or what?
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu mnRWindow = new JMenu("RWindow");
menuBar.add(mnRWindow);
JMenuItem mntmMore = new JMenuItem("More");
mnRWindow.add(mntmMore);
JMenuItem mntmExit = new JMenuItem("Exit");
mntmExit.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.exit(DISPOSE_ON_CLOSE);
}
});
mnRWindow.add(mntmExit);

Don't use a MouseListener with a JMenuItem.
A JMenuItem is designed to be used with an ActionListener. Read the section from the swing tutorial on How to Use Menus for more information and working examples.
Also, DISPOSE_ON_CLOSE is NOT a value you should be using for the System.exit(...) method. That variable should only be used with the setDefaultCloseOperation(...) method of the frame. Just use a "0" for the value.

Related

Dynamic resizing of JMenu after adding items at runtime

As in title, I struggle to get my JMenu to resize when programatically adding components. In my application I need JMenu with JCheckBoxes. Whenever I tick one of them, JSlider should appear just below. Below is the code that makes that happen. The problem I have is that when there's lot of sliders visible, items in JMenu get clumped - see image below.
How can I force redraw/resize/expansion of JMenu to perserve original checkboxes/sliders height?
Also note - JMenu stays visible at all times when selecting checkboxes. It closes only when I click outside of it. But after such 'restart' menu grows and problem is no longer present.
Many thanks in advance!
public class Window extends JFrame implements ActionListener {
private JPanel panel;
private JMenuBar menuBar;
private JMenu menu;
private JSlider slider1;
private JCheckBoxMenuItem checkBox1;
private JCheckBoxMenuItem checkBox2;
private JCheckBoxMenuItem checkBox3;
public Window() {
super("Example");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setMinimumSize(new Dimension(300,300));
panel = new JPanel();
panel.setMinimumSize(new Dimension(300,300));
menuBar = new JMenuBar();
menu = new JMenu("Options");
checkBox1 = new JCheckBoxMenuItem("option 1");
checkBox2 = new JCheckBoxMenuItem("option 2");
checkBox3 = new JCheckBoxMenuItem("option 3");
checkBox1.addActionListener(this);
//prevent JMenu from closing after selecting CheckBox
checkBox1.setUI(new BasicCheckBoxMenuItemUI() {
#Override
protected void doClick(MenuSelectionManager msm) {
checkBox1.doClick(0);
}
});
slider1 = new JSlider();
slider1.setVisible(false);
menu.add(checkBox1);
menu.add(slider1);
menu.add(checkBox2);
menu.add(checkBox3);
menuBar.add(menu);
setJMenuBar(menuBar);
add(panel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(checkBox1)) {
slider1.setVisible(checkBox1.isSelected());
}
}
}
Here's screen from my main application:
Hiding and reshowing the popup menu will cause it to be resized:
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(checkBox1)) {
slider1.setVisible(checkBox1.isSelected());
menu.setPopupMenuVisible(false);
menu.setPopupMenuVisible(true);
}
}
Call revalidate() it is supposed to do the trick, call it on the newly added components. https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Component.html#revalidate()
But i would say a use case like this is not what menus are meant for? why not use a dialog for dynamic components?
For background https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Component.html#revalidate() call it o the newly added component and see https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Component.html#invalidate() and https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Container.html#isValidateRoot()

How to fix the display of elements using Swing in Java

I'm working on an application using Swing in Java, however, I have a weird problem in the display, my code works perfectly fine, but the output is weird. When I run the program. The JFrame looks empty or something is missing (JMenuBar, JMenuItem, etc are invisible), then I maximize the screen, and all other stuff becomes visible, then I minimize the screen and it looks visible. I'm pretty sure that the code works fine, it's just a display problem. Can anyone help so that the first display looks fine?
Here is the code
JFrame frame = new JFrame("Menu");
frame.setVisible(true);
frame.setSize(400,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menubar = new JMenuBar();
frame.setJMenuBar(menubar);
JMenu file = new JMenu("File");
menubar.add(file);
JMenuItem exit = new JMenuItem("Exit");
file.add(exit);
JMenu help = new JMenu("Help");
menubar.add(help);
JMenuItem about = new JMenuItem("About");
help.add(about);
class exitaction implements ActionListener {
public void actionPerformed (ActionEvent e) {
System.exit(0);
}
}
exit.addActionListener(new exitaction());
}
Put the code below at the end. It'll work fine.
The method setVisible is an action, just like show() before JDK 1.5.
frame.setVisible(true);

I want JMenu to show the items when the program starts

I've created a menubar and added a menu with several items. When I do doClick() on the JMenu(archiveMenu) it highlights the button for the menu but it doesnt show any of the items that are added to it. I've tried doing doClick() before the adding of actionListeners to the items and setVisible(true) but nothing works.
I think it has something to do with the fact that they have seperate actionListeners but I'm so far in to the program that changing to a single actionListener would lead to a huge amount of work. I appreciate any help, thanks!
It looks like this:
// MENU BAR
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu archiveMenu = new JMenu("Archive");
menuBar.add(archiveMenu);
JMenuItem newItem = new JMenuItem("New Map");
JMenuItem loadItem = new JMenuItem("Load places");
JMenuItem saveItem = new JMenuItem("Save");
JMenuItem exitItem = new JMenuItem("Exit");
newItem.addActionListener(new NewMapLis());
loadItem.addActionListener(new LoadLis());
saveItem.addActionListener(new SaveLis());
exitItem.addActionListener(new ExitLis());
archiveMenu.add(newItem);
archiveMenu.add(loadItem);
archiveMenu.add(saveItem);
archiveMenu.add(exitItem);
archiveMenu.doClick();
What is happening is that when doClick() is called the window is not fully loaded yet.
you need to perform it after loading.
for example, you could call it when the frame is opened:
myFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowOpened(WindowEvent e) {
archiveMenu.doClick();
}
});

invisible JMenuBar, Accelerator not working

My Program has a JMenuBar with JMenuItems.
They have a ActionListener, and I set a Shortcut with setAccelerator.
Now I am hiding the menu bar when the window become unfocused, to get more space for a displayed image.
But after the first hiding of the menubar, the hotkeys just stop working.
How can I fix that?
I created a little example code to illustrate that strange behavior:
import javax.swing.*;
import java.awt.event.*;
class Example extends JFrame{
public static void main(String[] args) {
new Example(); //main is static
}
static JMenuBar menubar; //be accessable for the ActionListener
Example() {
//JPanel
this.setSize(50,50);
this.setVisible(true);
//Menubar, static
menubar = new JMenuBar();
this.setJMenuBar(menubar);
//Menu
JMenu filemenu = new JMenu("File");
menubar.add(filemenu);
//Item
JMenuItem menuitem = new JMenuItem("Do Something...");
filemenu.add(menuitem);
menuitem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_DOWN_MASK)); // Shift + D
menuitem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Action!");
}
});
JButton button = new JButton("Show/Hide menubar");
this.add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Toggle Bar!");
menubar.setVisible(!menubar.isVisible()); //Toggle
}
});
}
}
For reference:
I'm using Java 1.7.0_60-ea (Java 7) on a Mac.
But this error occurs independent of using the Mac native menu bar or the normal java menu bar inside the JFrame.
You could try to add global keybindings. How to add keybindings is explained here.
Here is an example of what you could do:
//Any component that is always visible in the window (like the image)
JComponent c;
//Get input and action map
InputMap imap = c.getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap amap = c.getActionMap();
//Put keybinding and action
imap.put(KeyStroke.getKeyStroke("shift D"), "doSomething");
amap.put("doSomething", anAction);
Note that it only works in the focused window. But should work regardless of the menubar being visible or not.

Add accelerator description to JMenuItem in GUI, without actually adding an accelerator

I'm trying to set some text to be displayed where the accelerator binding is usually displayed, for a JMenuItem.
The demarcated Ctrl+Z text in the following image is an example of what I'm trying to set, for another JMenuItem.
I don't actually want to set an accelerator for this JMenuItem, though.
I've poked around the source for several classes, like JMenuItem and BasicMenuItemUI, to no avail.
What's the simplest way to achieve this?
Thanks in advance :)
I assume the reason you want this is so you can prevent the menu from triggering the undo action a second time, when the key combination is already bound on a component on the frame, but this shouldn't be necessary. If the component consumes the key event, the menu won't detect it.
Here's an example with a JTextArea to see what I mean:
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JMenuBar menu = new JMenuBar();
frame.setJMenuBar(menu);
JMenu menuEdit = new JMenu("Edit");
menu.add(menuEdit);
JMenuItem menuEditUndo = new JMenuItem("Undo");
menuEdit.add(menuEditUndo);
menuEditUndo.setAccelerator(KeyStroke.getKeyStroke("control Z"));
menuEditUndo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("menu");
}
});
JTextArea textArea = new JTextArea(20, 40);
textArea.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "undo");
textArea.getActionMap().put("undo", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("text");
}
});
frame.add(new JScrollPane(textArea));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Both the text area and the menu item have bound to the same key combo, but pressing Ctrl+Z while the text area has focus prints only "text" and never "menu". I.e., the action does not happen twice. Although this uses a JTextArea, it should be true of any component.

Categories

Resources