I've already this project, but I'm having more problems. The dialog for SetMusicDialog opens, but it won't close when I try to exit out. I have a System.exit, but I'm not sure why the window won't close.
import java.awt.*;
import java.io.*;
public class SetMusicDialog extends Dialog
{
public static String sng;
public SetMusicDialog()
{
super ((Dialog)null, "Set Music");
Panel mpanel;
Font l = new Font("Helvetica", Font.ITALIC, 12);
setFont(l);//sets font
setBackground(Color.cyan);
Panel f = new Panel();
f.add("West", new Button("Death Grips"));
f.add("East", new Button("Siren"));
add("South",f);
pack(); // make it just fit
resize(preferredSize());
move(200,200);
}
public boolean handleEvent1 (Event evt)
{
switch (evt.id)
{
case Event.WINDOW_DESTROY:
System.exit(0);
dispose();
return true;
case Event.ACTION_EVENT:
if("Death Grips".equals(evt.arg))
{
sng= "breakmirrors.wav";
}
else if("Siren".equals(evt.arg))
{
sng= "bip.wav";
}
dispose();
}
return false;
}
}
You can add this:
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
System.exit(0);
}
});
windowClosed won't detect if the user tries to close the window. It will only run if the window has been closed. So use windowClosing.
Also, by using WindowAdapter you do not need to write all the methods of WindowListener.
I added this code in your constructor, and it works properly.
If you are using AWT, you should create a WindowListener as MadProgrammer stated. Basically, a WindowListener is a class that has methods that are run when certain window-related actions occur. To write code that will run when a Dialog (which extends Window) is closed:
//d is a dialog
d.addWindowListener(new WindowListener() {
//You'll need to implement all the abstract methods. leave them empty.
#Override
public void windowClosed(WindowEvent e) {
//Your code
}
});
Basically, you're anonymously implementing the abstract class WindowEvent. Make sure you implement all the other methods too, or you will get compiler errors. Your IDE should automatically implement all the methods.
Related
I have created a class that extends from WindowAdapter so that every time I want to close a window, it asks you if you really want to close the window. The problem comes when I click "No". How can I handle it so that the window event doesn't "remain" there and the frame keeps trying to dispatch it?
I only do a return, and I can't come up with anything. Here's the code:
public class ExitController extends WindowAdapter{
#Override
public void windowClosing(WindowEvent windowEvent) {
if(JOptionPane.showConfirmDialog(null,"Are you sure to close this window?",
"Really Closing?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)
== JOptionPane.YES_OPTION){
System.exit(0);
} else {
return;
}
}
}
Check out Closing an Application.
It gives some basic code for this. The basic code would set the default close operation of the frame to DO_NOTHING_ON_CLOSE.
Then in the WindowListener when the user confirms the close it will reset the default close operation to EXIT_ON_CLOSE instead of using System.exit(0);
You can also use the CloseListener class which is a more complex version (because it provides more functionality) of youe ExitController class.
The problem is in JFrame.processWindowEvent:
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e); // --> this will call your listener
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
switch(defaultCloseOperation) {
case HIDE_ON_CLOSE:
setVisible(false);
break;
case DISPOSE_ON_CLOSE:
dispose();
break;
case DO_NOTHING_ON_CLOSE:
default:
break;
case EXIT_ON_CLOSE:
// This needs to match the checkExit call in
// setDefaultCloseOperation
System.exit(0);
break;
}
}
}
Independently of what your listener does, the JFrame evaluates its defaultCloseOperation and closes or hides itself.
Therefore you need also to initialize the right default close operation of the frame on which you install your listener to prevent the default operation:
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new ExitController ());
You could provide a method in ExitListenerto facilitate this:
public class ExitController extends WindowAdapter {
public void installOn(JFrame frame) {
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(this);
}
I've searched similar threads but I can't seem the find the solution that fits. (I'm new to java)
I have made an texteditor and i need to make the option to save before exit. A possible window that pops up and asks the user if they want to save or not...
The main frame has set this:
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
And this is my inner class that handles the event that is generated when the user selects Exit from the file menu.
private class ExitListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
Thanks!
So in your frame class you should override the method processWindowEvent.
#Override
protected void processWindowEvent(WindowEvent e) {
if(e.getID() == WindowEvent.WINDOW_CLOSING){
System.out.println("Windows is closing");
}
super.processWindowEvent(e);
}
I am working on a project in which I would like to close a generic JOptionPane programmatically (by not physically clicking on any buttons). When a timer expires, I would like to close any possible JOptionPane that may be open and kick the user back to the login screen of my program. I can kick the user back just fine, but the JOptionPane remains unless I physically click a button on it.
I have looked on many sites with no such luck. A doClick() method call on the "Red X" of the JOptionPane does not seem possible, and using JOptionpane.getRootFrame().dispose() does not work.
Technically, you can loop through all windows of the application, check is they are of type JDialog and have a child of type JOptionPane, and dispose the dialog if so:
Action showOptionPane = new AbstractAction("show me pane!") {
#Override
public void actionPerformed(ActionEvent e) {
createCloseTimer(3).start();
JOptionPane.showMessageDialog((Component) e.getSource(), "nothing to do!");
}
private Timer createCloseTimer(int seconds) {
ActionListener close = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window[] windows = Window.getWindows();
for (Window window : windows) {
if (window instanceof JDialog) {
JDialog dialog = (JDialog) window;
if (dialog.getContentPane().getComponentCount() == 1
&& dialog.getContentPane().getComponent(0) instanceof JOptionPane){
dialog.dispose();
}
}
}
}
};
Timer t = new Timer(seconds * 1000, close);
t.setRepeats(false);
return t;
}
};
This code gotten from
https://amp.reddit.com/r/javahelp/comments/36dv3t/how_to_close_this_joptionpane_using_code/ seems to be the best approach to me. It involves Instantiating the JOptionPane class rather that using the static helper methods to do it for you. The benefit is you have a JOptionPane object that you can dispose when you want to close the dialog.
JOptionPane jop = new JOptionPane();
jop.setMessageType(JOptionPane.PLAIN_MESSAGE);
jop.setMessage("Hello World");
JDialog dialog = jop.createDialog(null, "Message");
// Set a 2 second timer
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
} catch (Exception e) {
}
dialog.dispose();
}
}).start();
dialog.setVisible(true);
I had posted this in a wrong place (GameDev) and got no response there. So I'm posting it again here.
I'm making an applet game and it is rendering, the game loop is running, the animations are updating, but the keyboard input is not working. Here's an SSCCE.
public class Game extends JApplet implements Runnable {
public void init(){
// Initialize the game when called by browser
setFocusable(true);
requestFocus();
requestFocusInWindow(); // Always returning false
GInput.install(this); // Install the input manager for this class
new Thread(this).start();
}
public void run(){
startGameLoop();
}
}
And Here's the GInput class.
public class GInput implements KeyListener {
public static void install(Component c){
new GInput(c);
}
public GInput(Component c){
c.addKeyListener(this);
}
public void keyPressed(KeyEvent e){
System.out.println("A key has been pressed");
}
......
}
This is my GInput class. When run as an applet, it doesn't work and when I add the Game class to a frame, it works properly.
Thanks
Solved now. See my solution
One possible solution is to use the JApplet's contentPane, to set the focus on it rather than on the JApplet itself. But my preference is to use Key Bindings instead. You may need to use a Swing Timer for this to work:
My SSCCE:
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
#SuppressWarnings("serial")
public class AppletKeyListen extends JApplet {
#Override
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setFocusable(true);
int timerDelay = 100;
Timer myTimer = new Timer(timerDelay , new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
boolean focusObtained = requestFocusInWindow();
System.out.println("focusObtained for JApplet: " + focusObtained);
Container contentPane = getContentPane();
contentPane.setFocusable(true);
focusObtained = contentPane.requestFocusInWindow();
System.out.println("focusObtained for contentPane: " + focusObtained);
}
});
myTimer.setRepeats(false);
myTimer.start();
// boolean focusObtained = requestFocusInWindow();
// System.out.println("focusObtained: " + focusObtained);
//
// Container contentPane = getContentPane();
// contentPane.setFocusable(true);
//
// focusObtained = contentPane.requestFocusInWindow();
// System.out.println("focusObtained: " + focusObtained);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}
If you're running in a browser, you probably need to click on the applet to give it focus. For security reasons most browsers won't let an applet just grab the keyboard focus without the user clicking it.
So, I would add a mouse listener instead of doing the focus grabbing directly in init():
addMouseListener(new MouseAdapter() {
public void onMousePress(MouseEvent e) {
requestFocus();
}
});
Now that I have two options,
Use JWS
Don't make an applet mode
Now I had tried to make a new class called GApplet. It loads a game into a new JFrame which worked from the applet. Now I can access the fullscreen mode from web too. Here's a link to the class.
The GApplet class
And now it's working like the webstart and is actually an applet.
In a Swing (J)Dialog, setModal sets the modality - that is, whether the dialog should block input to other windows or not. Then, setVisible docs say for modal dialogs:
If the dialog is not already visible, this call will not return until the dialog is hidden by calling setVisible(false) or dispose.
Indeed, setVisible does return right away if the dialog is not modal. Sample code:
JDialog jd = new JDialog();
jd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
/**
* If set to false, setVisible returns right away.
* If set to true, setVisible blocks until dialog is disposed.
*/
jd.setModal(false);
System.out.println("setting visible");
jd.setVisible(true);
System.out.println("set visible returned");
I want to make a dialog that doesn't block input to other windows, but still does block the caller. What is a good way to do this, now that setVisible doesn't block when the dialog is not modal?
Is there some rationale why setVisible's behavior depends on the modality?
I need to make a dialog that doesn't block input to other windows, but does block the caller so that I know when the dialog has been closed.
I usually solve this not by blocking the caller, but by using a callback of some sort - a simple interface that the dialog invokes when it's done. Let's say your dialog has an "OK" and a "Cancel" button and you need to distinguish which one is pressed. Then you could do something like this:
public interface DialogCallback {
void ok();
void cancel();
}
public class MyModelessDialog extends JDialog {
private final DialogCallback cbk;
private JButton okButton, cancelButton;
public MyModelessDialog(DialogCallback callback) {
cbk = callback;
setModalityType(ModalityType.MODELESS);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onOK();
}
};
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
};
// Treat closing the dialog the same as pressing "Cancel":
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
onCancel();
}
};
}
private void onOK() {
cbk.ok();
}
private void onCancel() {
cbk.cancel();
}
}
Then you just pass in an instance of DialogCallback to the constructor:
MyModelessDialog dlg = new MyModelessDialog(new DialogCallback() {
public void onOK() {
// react to OK
}
public void onCancel() {
// react to Cancel
}
});
EDIT
Is there some rationale why setVisible's behavior depends on the modality?
Well, that's just how how modal windows are supposed to work, no? A modal window should block the current workflow when displayed, and a non-modal/modeless should not. See e.g. the Wikipedia pages on modal windows or dialog boxes.
Just put this.setModal(true) but not set the parent dialog on the constructor:
MyDialog dlg = new JDialog();
this.setModal(true);
When you call setVisible(true), it wont stop
The direct approach is by:
JDialog dialog = new JDialog(owner, ModalityType.DOCUMENT_MODAL);
I have found another way to do this. In the constructor of my progress bar, which extends javax.swing.JDialog, I added:
setModalityType(ModalityType.APPLICATION_MODAL);
I then overrode the setVisible method:
#Override
public void setVisible(boolean b) {
if (b) {
new Thread(new Runnable() {
#Override
public void run() {
showProgress();
}
}).start();
} else {
super.setVisible(false);
}
}
In the run(), you can see a call to showProgress(). This simply is:
public void showProgress() {
super.setVisible(true);
}
What happens here, is the setVisible() method of JDialog blocks. So I overrode it, and called setVisible() of the JDialog, in a thread. Resulting in it not blocking.