So i have made a simple program with a basic menu at the top of the frame, Now i just need to put actions behind each JMenuItem. Im struggling to work the code out though, Here is what i thought would work:
JMenu file_Menu = new JMenu("File");
JMenuItem fileExit = new JMenuItem("Exit Program");
file_Menu.add(fileExit);
fileExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JFrame hello = new JFrame("POPUP");
hello.setSize(100,75);
hello.setDefaultCloseOperation(hello.EXIT_ON_CLOSE);
hello.setVisible(true);
}
});
main_Menu.add(file_Menu);
This doesn't seem to work though, I thought that this code would create a small popup window when the menu item is clicked.
Can any spot the bug because i cant seem to.
Suggestion: Instead of adding a separate ActionListener, just use AbstractAction:
JMenuItem fileExit = new JMenuItem(new AbstractAction("Exit Program") {
public void actionPerformed(ActionEvent ae) {
JFrame hello = new JFrame("POPUP");
hello.setSize(100,75);
hello.setDefaultCloseOperation(hello.EXIT_ON_CLOSE);
hello.setVisible(true);
}
});
I'd also suggest, instead of setting EXIT_ON_CLOSE on the popup menu, you set it on the main frame of your application, and have the action simply call theMainFrame.dispose().
You got it working, but you have another problem.
Don't do this:
hello.setDefaultCloseOperation(hello.EXIT_ON_CLOSE);
When you close the pop-up frame, your entire JVM terminates. Consult JFrame.setDefaultCloseOperation javadocs for a more appropriate value.
Give an instance of Action (extend from AbstractAction) to JMenuItem
Based on the code you posted it looks like it should work, but we can't see the entire context of how the menu item is being used.
Did you debug your code (with a System.out.println) to see if the ActionListener is being invoked?
If you need more help post your SSCCE that demonstrates the problem.
Fixed it.
Forgot to add the actionPerformed method.
Related
I decided to put "close" buttons on my JFrames. If I test just that JFrame by itself, it works fine, but when I try to close it after opening it through another class, it won't close.
Here is the code:
JButton btnClose = new JButton("Close");
btnClose.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
frame.dispose();
}
});
btnClose.setBounds(282, 666, 96, 50);
contentPane.add(btnClose);
I have tried using frame.dispose() and frame.close() and super.dispose() but the only one that works is system.exit(0); but then that exits the whole program.
The issue:
If I test the JFrame by itself, the frame closes fine.
If I open the program and navigate to that specific JFrame, the close button does nothing.
Please advise.
Did you add a display statement in the ActionListener to make sure the code is being executed?
If the code is being executed, then the problem is probably that the frame variable has in invalid reference.
You don't need to keep a reference to the frame. Instead use something like:
Window window = SwingUtilities.windowForComponent( e.getSource() );
window.dispose();
Use setVisible(false); on the frame. Then call dispose.
I've been validating a swing application that runs on an applet for mac osx.
During this validation I found the following issues with the modal dialogs:
When a dialog is open and is setModal(true) it blocks the content of the root window, but if you click somewhere on the root window, the dialog goes under it, but it should remain on the top of the root window.
If the dialog has a JTextInputField it does not receive focus even when you click on it.
So I created a small program to show the problem. Can you please help me to understand what is wrong here?
package com.macosx.tests;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class DialogExample extends JApplet{
private static final long serialVersionUID = 1L;
private JPanel panel;
private JButton openDialogBtn;
private void doStart() {
panel = new JPanel();
panel.setPreferredSize(new Dimension(500,500));
openDialogBtn = new JButton("open dialog");
openDialogBtn.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
ModalDialog dialog = new ModalDialog(panel, true);
dialog.setVisible(true);
}
});
panel.add(openDialogBtn);
setContentPane(panel);
}
class ModalDialog extends JDialog {
private static final long serialVersionUID = 1L;
public ModalDialog(Component parent, boolean modal) {
Dimension dimensionParentFrame = parent.getSize();
setSize(new Dimension((parent == null) ? 300 : dimensionParentFrame.width / 2, 75));
setModal(modal);
setModalityType(ModalityType.APPLICATION_MODAL);
JTextField txtField = new JTextField();
add(txtField, BorderLayout.CENTER);
}
}
#Override
public void start() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
doStart();
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Use the above to create a .jar file (test.jar). Once that is done, create a html file with the following content:
<html>
<head>
<title>Dialog test Applet</title>
</head>
<body>
<applet id="DialogTestApplet" height="800" width="600"
code="com.macosx.tests.DialogExample"
archive="test.jar">
</applet>
</div>
</body>
</html>
When this is done, run the html file. You'll see an applet with a gray background and with a button. Then try to:
click on the button to open the dialog. After that, click somewhere on the gray area: the dialog goes under the browser window but it should remain on the top, right?
click on the button to open the dialog. After that click on the textfield of the dialog and try to write something: the textdialog does not receive focus.
So, what am I doing wrong here? Can someone with a mac computer test this please?
Thanks
Specs:
java.vendor Oracle Corporation
java.version 1.7.0_07
os.name Mac OS X
os.version 10.7.4
browser firefox 15
NOTE: please note that this is only happening when the applet runs on the browser and only on mac osx.
I found another workaround. When the window is opened, show an optionpane for a few milliseconds and close it. It give the focus to the optionpane and then back to the dialog, allowing to ignore the bug.
Add this snipet of code to your dialog constructor and it should work:
addWindowListener(new WindowAdapter(){
public void windowOpened(WindowEvent e){
JOptionPane pane = new JOptionPane();
final JDialog dialog = pane.createDialog("Please Wait");
Timer timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
timer.setRepeats(false);
timer.start();
dialog.setVisible(true);
}
You should put an "owner" window on your ModalDialog. To do that, you must call super(owner) in your ModalDialog constructor and you can retrieve the parent window of your component parent with SwingUtilities.getWindowAncestor(parent).
not Mac/OSX user but this is common issue about Focus and JDialog,
there are another issues in the case that JDialog is created on Runtime,
Focus is asynchronous based on properties came from Native OS
create this JDialog only once time and re_use this container for another action
JDialog#setVisible should be wrapped into invokeLater() too
is possible to force the Focus by JTextField#setText(JTextField#getText()) wrapped into invokeLater()
there is Dialog Focus, one of great workaround by #camickr
I confirm, I have the same bug with an old applet running in JDK7 on OS X. As the poster mentioned, the bug is seen only with the applet running in the browser (ff) and not with the appletviewer.
I can verify that this is a problem for Java 1.7 Update 7+ on the Safari 6 and Firefox running on Mountain Lion. Curiously it is not a problem on earlier versions of Safari that run on Lion but it is a problem in Firefox on the older OS. I am pretty desperate to find a fix for this as a number of my applet users are on Macs. One workaround that I have found (that is not sufficient by any means) is to minify the window and then reopen it. The textfields/textareas then become editable. Hopefully, we can find a better solution that gets around this annoying requirement.
I experienced the same problem on Mac with Java 7 update 9 with Safari and Firefox. When I opened a JDialog which contained a JTextField the JTextField was inaccessible.
I did find a solution. I inserted a delay from when the user pressed the “show dialog button” to executing the code that shows the button.
For example:
ActionListener al = new ActionListener(){
public void actionPerformed(ActionEvent ae){
TitleDialog dialog = new TitleDialog(main.findParentFrame()); // My JDialog which contains a JTextField.
dialog.setVisible(true);
}
};
javax.swing.Timer timer = new javax.swing.Timer(1000, al);
timer.setRepeats(false);
timer.start();
I experienced that if the delay was to short the solution would not work.
If one uses SwingUtilities.invokeLater instead of javax.swing.Timer it will not work. Maybe the delay of SwingUtilities.invokeLater is too short.
I found one more workaround. When JDialog is invoked from JavaScript it has a focus.
Create an applet's method which will show a dialog
Call this method from JavaScript.
Hope, it helps. By the way, web start samples from Java tutorial have the same issue http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html
I want to use the workaround above (to open dialog from the dialog), but without showing any dialog.
Here is a code for not visible dialog.
final JDialog dialog = new JDialog();
dialog.setUndecorated(true);
dialog.setSize(0, 0);
dialog.setModal(true);
dialog.pack();
I have found a solution.
GetDirectory varGetDirectory = new GetDirectory(new JFrame(),true);
varGetDirectory.setVisible(true);
GetDirectory is JDialog containing a JFileChooser.
The weird thing is that all JDialog object should be called using new JFrame() as parent, otherwise clicking from one parent window, will bring the top modal JDialog backwards in the zOrder and somehow it cannot be set on top anymore.
My problem was the same as above. When I have created the JDialog from another JDialog, the new dialog appeared behind the other.
To bring it to top I have set the parent of all JDialogs as described above and it worked according to what expected.
I have to create a searching window, like a google browser window. It must have a pull down list containing similar results, which is populated from a database.
I am trying to adjust a JCombobox but this has caused me a lot of trouble. Is there a better way to do this? (Perhaps something like this already exists in Java.) If not, can anyone advise me on how to achieve my goal?
create JTextField with keyboard event to show the popup window on key realeased,
Example:
jTextField2.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
showPopup(evt);
}
});
void showPopup(java.awt.event.KeyEvent evt) {
JPopupMenu popup = new JPopupMenu();
popup.setLightWeightPopupEnabled(false);
popup.setBorder(BorderFactory.createLineBorder(Color.black));
popup.setLayout(new BorderLayout());
popup.setSize(this.getPreferredSize());
popup.setPreferredSize(this.getPreferredSize());
popup.pack();
popup.setOpaque(false);
// create panel that contains the search result
popup.add(BorderLayout.CENTER, <YOUR PANEL WITH THE RESULT>);
popup.setPreferredSize(new Dimension(jTextField2.getWidth(),250));
<SEARCH PANEL>.setPreferredSize(new Dimension(jTextField2.getWidth(),250));
popup.show(jTextField2, 0, jTextField2.getHeight());
}
i have to do searching window like google browser window. It must have pull down list with similarities results that comes from database. I trying to adjust JCombobox but this made me a lot of trouble.
Maybe not true, I'd to use AutoComplete JComboBox / JTextField
I have the main application frame. If user clicks the button he gets a new frame which has some chart in it. Now if I want to close that chart both chart and main application closes. How can I distinguish those two closings. Certainly I don't want my application to be closed after closing the frame in which I put chart.
Here's the code of the chart frame.
chartBttn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final ShowChart sc = new ShowChart("Reserve Selection", getUtilExperiments() );
sc.pack();
RefineryUtilities.centerFrameOnScreen(sc);
sc.setVisible(true);
sc.setDefaultCloseOperation(ShowChart.DISPOSE_ON_CLOSE);
}
});
You can use the dispose() method. Or you can call setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); on the JFrame.
If I understood you correctly on your new JFrame build a method for your close button or X window button with:
setVisible(false);
dispose();
Otherwise please post your code on creating the new JFrame etc.
Certainly I don't want my application to be closed after closing the frame in which I put chart.
1) don't create lots of JFrames on the fly, create JFrame only once and re-use that for next usage(s), then
call only for visibility setVisible(false/true) with setDefaultCloseOperation(JFrame.NOTHING_ON_CLOSE)
or very simple workaround
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE)
2) or JDialog with setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
3) NOTICE: but in this case isn't possible close the current JVM instance, you have to add JButton or JMenu/JMenuItem which accelerate for System.exit(1)
simply use super.dispose(); for closing previous jframe
When I set setAccelerator() to Control + A or Control + P and I run the program it doesn't detect the keystroke.
Here's the code:
menuItem = new JMenuItem("About");
menuItem.setActionCommand("About");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Event.CTRL_MASK));
menuItem.setMnemonic(KeyEvent.VK_A);
menuItem.addActionListener(this);
menu.add(menuItem);
Then when it's pressed it should invoke the Action Listener:
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("About")) {
System.out.println("About");
}
}
I'm running it in Eclipse on a Mac if that matters.
Control-A and Control-P are both keystrokes that may already be intercepted, depending on your platform and depending on what has keyboard focus. Control-A may already be intercepted and interpreted as "select all", and Control-P may already be intercepted and interpreted as "paste".
What if you select a less commonly-used keystroke instead of "Control-A", such as "Control-Shift-A" or "Control-B"? Here's a modified version of your code that uses Control-Shift-A instead of Control-A:
menuItem = new JMenuItem("About");
menuItem.setActionCommand("About");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Event.CTRL_MASK | Event.SHIFT_MASK));
menuItem.setMnemonic(KeyEvent.VK_A);
menuItem.addActionListener(this);
menu.add(menuItem);
I tested this change on my own system using the JMenu demo from the Swing tutorial, and I found (exactly as you did) that registering Control-A as the accelerator had no effect. However, registering Control-Shift-A as the accelerator worked perfectly.
not sure if it will help, but you're using Event.CTRL_MASK instead of KeyEvent.CTRL_MASK