Can anyone guide me on why 'frame.dispose();' doesn't dispose the frame? The other method is called but 'frame.dispose();' is just ignored. This java class is used to check whether a stored answer that is made from another java class (RecoveryQuestion.check()) is the same as the user's input. Public variables such as StoredQuestion and StoredPassword are in the RecoveryQuestion class as well. Furthermore, I'm using Intelli J IDEA GUI form and I don't know how to extract the code, however, the form runs smoothly as intended except with the frame.dispose();
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.io.IOException;
public class ForgotPassword {
private JPanel panel1;
private JTextField answer;
private JLabel Question;
private JButton Submit;
private JFrame frame = new JFrame("Password Reset");
public ForgotPassword() {
Submit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(RecoveryQuestion.StoredPassword.equals(answer.getText())) {
//frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
frame.dispose();
FirstRun.main(null);
}
else JOptionPane.showMessageDialog(null,"Incorrect Answer");
}
});
}
public void setUI() {
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setContentPane(new ForgotPassword().panel1);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(400,250));
frame.pack();
frame.setResizable(false);
}
public static void main(String[] args) {
try{
RecoveryQuestion.Check();
} catch(IOException e1) {}
new ForgotPassword().setUI();
}
private void createUIComponents() {
// TODO: place custom component creation code here
Question = new JLabel();
Question.setText(RecoveryQuestion.StoredQuestion);
}
}
Every call to new ForgotPassword() does just that -- it creates a completely new and unique ForgotPassword instance. Look at your code above, and count how many times that you call this -- I see two times, suggesting that your problem is that you're displaying a JFrame from one of these instances, and trying to dispose of it in another -- two different JFrames that are unrelated to each other.
Suggestions:
Your code is very convoluted with instances creating instances of them self within their self. Simplify.
Create only one ForgotPassword in your GUI and pass it where needed
Side issue: shouldn't this sort of window be a dialog window (i.e., a JDialog) and not an application window (i.e., a JFrame)?
If your code did work as intended, then calling .dispose() on this JFrame should cause the JVM to exit (the entire program to end) since you're setting its default close operation to EXIT_ON_CLOSE.
Side issue 2: your posted code is not a valid MCVE meaning we cannot easily copy the code, paste it into our IDE and compile and run it without modification, making it more difficult for us to fully understand your code and forcing me to guess at your problem. In the future (and now), please consider posting one of these. Note that we do not want to see your entire program, nor should you post a link to a code repository. Instead keep it small, keep it simple, and make it functioning.
Related
I have a java swing application which has a processWindowEvent method.
below is the snippet
#Override
protected void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
//exit application with proper error message
}
}
Now when my swing application is launched in windows.
close with the cross in swing UI. ==> proper error message is shown
close the application from taskbar ==>proper error message is shown
but now if the same step is done in mac.
close with the cross in swing UI. ==> proper error message is shown
close the application from taskbar ==>does not come inside above method. So no proper message.
I wanted to know what is the default method which will be called in mac when java swing app is closed from taskbar(the dock)
A world without com.apple.eawt.*
You need to look towards java.awt.Desktop instead.
For example...
Desktop.getDesktop().setQuitHandler(new QuitHandler() {
#Override
public void handleQuitRequestWith(QuitEvent e, QuitResponse response) {
// Do some stuff
//response.cancelQuit();
//response.performQuit();
}
});
Desktop.getDesktop().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
Original Answer
Welcome to the wonderful world of "Apple does everything differently"
Basically what's happening is, when you "Quit" the program, Apple is calling System.exit(0), basically the same thing that would occur if your used CMD+Q
Now, Apple provides an API which provides functionality which you can use to "configure" your App with MacOS and perform some functionality which is unique to Apple, the problem is, it's a complete pain in the ... code to find useful information about and use.
What you're looking for is com.apple.eawt.ApplictionsetQuitStrategy. This defaults to calling System.exit(0), but you can change it to "close all windows" instead.
In this case, it would allow you to trap the WindowEvent and do what ever it is you want to do
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.out.println("Closing");
System.exit(0);
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
try {
Class quitStrategies = Class.forName("com.apple.eawt.QuitStrategy");
Object quitStrategy = null;
for (Object o : quitStrategies.getEnumConstants()) {
if ("CLOSE_ALL_WINDOWS".equals(o.toString())) {
quitStrategy = o;
}
}
if (quitStrategy != null) {
Class appClass = Class.forName("com.apple.eawt.Application");
Class params[] = new Class[]{};
Method getApplication = appClass.getMethod("getApplication", params);
Object application = getApplication.invoke(appClass);
Method setQuitStrategy = application.getClass().getMethod("setQuitStrategy", quitStrategies);
setQuitStrategy.invoke(application, quitStrategy);
}
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
}
}
My general advice is, build a nice "Mac" utilities class which encapsulates the functionality you want to play with and call that.
Also beware, this functionality may disappear suddenly in future releases.
It should be noted that if you intend to have a "one for all" application, you will need to use reflection, as the required API is not available in the standard API, but if you wanted to make a "Apple" only release, you should have a look at this for more information about how you can compile the code on MacOS, because using...
Application.getApplication().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
is hell of a lot easier to write and understand
To catch window close event you need to add WindowListener and override method windowClosing. Use this code:
JFrame frame = new JFrame(...);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener( new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
JFrame frame = (JFrame)e.getSource();
....................
}
}
I have been designing a Swing-based tabletop RPG program to facilitate text-based roleplay with GUI control elements.
To facilitate this, each running client gets a main desktop ("GM Desktop" on the hosting client and "Player Desktop" on the remote clients) with all of the important JFrames. Additionally, both GM and Players can open "Perspective Desktops" for characters, providing them with a separate JDesktopPane that contains the "Role Play Chat Window" that gives that character's perspective, along with additional JInternalFrames such as the "Character Sheet Window", etc.
The user navigates between desktops using a JTabbedPane.
The issue that I am having is that SOME of the windows I want to be able to move between desktops. For example, if the OOC (Out-of-Character) Chat receives a message while the user is in a Perspective Desktop, I want there to be an option for the OOC Chat Window to automatically relocate to the current desktop so the user sees the message immediately. Similarly I want the player to be able to "call" certain windows into the current desktop using the menu bar.
However, when I attempt to move a JInternalFrame from one JDesktopPane to another, I receive an exception.
com.finnickslab.textroleplayonline.exceptions.CommandEventHandlingException
An exception was thrown during command handling. CommandEvent type: UI_OOC_CHAT (26).
Cause Exception: java.lang.IllegalArgumentException
illegal component position
java.awt.Container.addImpl(Unknown Source)
javax.swing.JLayeredPane.addImpl(Unknown Source)
javax.swing.JDesktopPane.addImpl(Unknown Source)
java.awt.Container.add(Unknown Source)
com.finnickslab.textroleplayonline.ui.GameDesktop.receiveTransfer(GameDesktop.java:80)
com.finnickslab.textroleplayonline.ui.GameDesktop.access$0(GameDesktop.java:74)
com.finnickslab.textroleplayonline.ui.GameDesktop$2.run(GameDesktop.java:69)
com.finnickslab.textroleplayonline.ui.UI.invokeEvent(UI.java:818)
com.finnickslab.textroleplayonline.ui.GameDesktop.transfer(GameDesktop.java:62)
com.finnickslab.textroleplayonline.ui.UI$HostCommandHandler.handle(UI.java:605)
com.finnickslab.textroleplayonline.comm.Server$3.run(Server.java:324)
All JInternalFrames in my program descend from the same subclass of JInternalFrame ("InternalWindow").
The exception makes it look a little convoluted but it boils down to calling JDesktopPane.remove(JInternalFrame) then JDesktopPane.add(JInternalFrame).
And then I receive that exception as soon as the "add" method is called on GameDesktop line 80.
/**
* Transfers the specified InternalWindow from this GameDesktop to
* the specified GameDesktop. Use this method to prevent
* automatic removal of listeners performed with the
* {#link GameDesktop.remove(InternalWindow)} method.
*/
public synchronized void transfer(
final InternalWindow window,
final GameDesktop gd) {
final GameDesktop desktop = this;
contents.remove(window);
UI.invokeEvent(new Runnable() {
#Override
public void run() {
desktop.remove((JInternalFrame) window);
desktop.validate();
desktop.repaint();
gd.receiveTransfer(window);
}
});
}
private synchronized void receiveTransfer(InternalWindow window) {
contents.add(window);
window.changeDesktop(this);
window.center();
this.add((JInternalFrame) window); // LINE 80
this.validate();
this.repaint();
window.resetPosition();
}
The "UI.invokeEvent(Runnable)" method is a convenience method I wrote for SwingUtilities.invokeAndWait(Runnable). It checks to see if the current thread is the EDT and, if it is, executes the run() method immediately. Otherwise, it uses invokeAndWait(Runnable) to schedule the runnable on the EDT.
Any ideas of how to fix this problem would be appreciated.
EDIT:
All my research on this error suggests that it has something to do with the Z-axis position of the component. I tried changing the add call to specify the z position
super.add(window, getComponentCount());
but no change. Still getting the same IllegalArgumentException.
See if you get the same error when running this. If not, the problem is not with switching the parent of the internal frame, it's with the synchronization.
public class IFSwitch extends JDesktopPane {
final JDesktopPane pane1 = this;
public IFSwitch() {
JFrame frame1 = new JFrame("Frame1");
JFrame frame2 = new JFrame("Frame2");
// JDesktopPane pane1 = new JDesktopPane();
JDesktopPane pane2 = new JDesktopPane();
final JInternalFrame if1 = new JInternalFrame();
frame1.add(pane1);
frame2.add(pane2);
pane1.add(if1);
if1.setBounds(10, 10, 100, 100);
frame1.setBounds(100, 100, 200, 200);
frame2.setBounds(500, 500, 200, 200);
frame1.setVisible(true);
frame2.setVisible(true);
if1.setVisible(true);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
pane2.add(if1);
pane1.remove(if1); // You don't even need this line.
pane1.repaint();
}
public static void main(String[] args) {
new IFSwitch();
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyCalculatorGUI extends JFrame implements ActionListener {
JButton tripled, doubled;
JTextField input, output;
JPanel p1, p2;
MyCalculatorGUI() {
Container c = getContentPane();
tripled = new JButton("Triple");
tripled.addActionListener(this);
doubled = new JButton("Doubled");
doubled.addActionListener(this);
input = new JTextField("Input a number here.");
output = new JTextField("Result..");
p1.add(doubled);
p1.add(tripled);
p2.add(input);
p2.add(output);
c.add(p1);
c.add(p2);
setVisible(true);
setSize(400,400);
}
public void actionListener(ActionEvent e) {
}
public static void main(String[] args) {
MyCalculatorGUI output = new MyCalculatorGUI();
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Eclipse is having a problem with my code where it is MyCalculatorGUI, it says the local variable is not used. Can somebody help me fix this?? I have recently just moved to Eclipse and everything I have tried to fix this isn't working for me.
I think you have created an object and not using it anywhere in main method
MyCalculatorGUI output = new MyCalculatorGUI();
This is just a warning by Eclipse. It cannot see that your actual logic happens inside the constructor - so it thinks you create a new object of your class MyCalculatorGUI inside the main method, but never use it. This could be a sign for unnecessary memory usage/consumption which might be a problem in large projects...
IF you change the line to just new MyCalculatorGUI(); the warning will disappear.
This is not an error, it's just a warning.
It simply means that you have created a variable which is never accessed later in the code. If you don't need it, then don't create it. If you do then just make use of it ;)
MyCalculatorGUI output = new MyCalculatorGUI(); //either delete this line
output.someMethod(); //or use the instance in some way
The warning should dissapear afterwards.
You don't use the variable you created in the main method, so either don't create it, use it or add the following above the main method: #SuppressWarnings("unused")
It's not a problem, it's just an Eclipse information to inform you that your local variable is not used. You can compile with 0 problem!
To resolve the warning you have two solutions:
First:
Implement the variable:
MyCalculatorGUI myCalculator = new MyCalculatorGUI();
Second:
Use the SupressWarnings on the top of your function like that:
#SuppressWarnings("unused")
MyCalculatorGUI() {
Container c = getContentPane();
tripled = new JButton("Triple");
tripled.addActionListener(this);
doubled = new JButton("Doubled");
doubled.addActionListener(this);
input = new JTextField("Input a number here.");
output = new JTextField("Result..");
p1.add(doubled);
p1.add(tripled);
p2.add(input);
p2.add(output);
c.add(p1);
c.add(p2);
setVisible(true);
setSize(400,400);
}
I've programmed a DLL in C. The first function sends a pointer of the callback function that is called when new data is available.
So I use JNA to wrap this function.
In order to avoid the end of the app, I use an InputStreamReader that wait data from the standard input. And when new data are available the callback is called and data are printed in the console.
But, if I use a JFrame to avoid the end of the program before closing the window, it doesn’t work properly. In fact, if I don’t resize the JFrame window, the callback is called about 30 times and after that nothing (even if new data are available). If I resize the window, the callback if never called (even if new data are available).
Please could you help me?
Thanks
Edit : This is my main method.
package jsigmausblib;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import javax.swing.JFrame;
public class JSigmaUSBLib {
public static void main(String[] args) {
NativeSigmaUSBLibInterface nsuli = (NativeSigmaUSBLibInterface) Native.loadLibrary("SigmaUSBLib1.0", NativeSigmaUSBLibInterface.class);
ReadCallback rc = new ReadCallback() {
#Override
public void callbackFunction(Pointer readData, byte len) {
System.out.println("ok"+readData.getByte(0));
}
};
SigmaUSBLibConfigStruct.ByValue config = new SigmaUSBLibConfigStruct.ByValue();
nsuli.SigmaUSBLibInit(rc , config);
JFrame frame = new JFrame("Debug");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(80, 60);
frame.setVisible(true);
}
}
Is it possible to implement a wrapper application for other (Java) applications using Java?
The purpose is to enforce usage policies for documents independent of the application used to work with a specific document.
E.G. I have an encrypted file that needs to be decrypted and opened in some kind of editor. So the wrapper application would decrypt the file and start the editor within itself to enforce an read-only policy by denying the write-access to the application, for example. Therefore the Runtime.getRuntime().exec(<command>) method doesn't fit well :)
There are also some ways to intercept method invocations within the same application but none that would wrap a whole other application.
I've also read about altering the JVM itself to intercept the file access. That sounds pretty good. But I need to dynamically change the policy depending on a user. That might not work as far as I know by now.
I guess there might not be any way to do this using Java code, but I'd appreciate any kind of hints and help.
I've also read about altering the JVM itself to intercept the file access. That sounds pretty good. But i need to dynamically change the policy depending on a user.
Set a custom SecurityManager that overrides checkWrite(String) to throw an exception.
Here is a simple example that prevents child frames from exiting the VM (checkExit(int)).
import java.awt.GridLayout;
import java.awt.event.*;
import java.security.Permission;
import javax.swing.*;
/** NoExit demonstrates how to prevent 'child' applications from
* ending the VM with a call to System.exit(0). */
public class NoExit extends JFrame implements ActionListener {
JButton frameLaunch = new JButton("Frame");
JButton exitLaunch = new JButton("Exit");
/** Stores a reference to the original security manager. */
ExitManager sm;
public NoExit() {
super("Launcher Application");
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
sm = new ExitManager( System.getSecurityManager() );
System.setSecurityManager(sm);
setLayout(new GridLayout(0,1));
frameLaunch.addActionListener(this);
exitLaunch.addActionListener(this);
add( frameLaunch );
add( exitLaunch );
pack();
setSize( getPreferredSize() );
setLocationByPlatform(true);
}
public void actionPerformed(ActionEvent ae) {
if ( ae.getSource()==frameLaunch ) {
TargetFrame tf = new TargetFrame();
} else {
// change back to the standard SM that allows exit.
System.setSecurityManager(
sm.getOriginalSecurityManager() );
// exit the VM when *we* want
System.exit(0);
}
}
public static void main(String[] args) {
NoExit ne = new NoExit();
ne.setVisible(true);
}
}
/** Our custom ExitManager does not allow the VM to exit, but does
* allow itself to be replaced by the original security manager. */
class ExitManager extends SecurityManager {
SecurityManager original;
ExitManager(SecurityManager original) {
this.original = original;
}
/** Deny permission to exit the VM. */
public void checkExit(int status) {
throw( new SecurityException() );
}
/** Allow this security manager to be replaced,
if fact, allow pretty much everything. */
public void checkPermission(Permission perm) {
}
public SecurityManager getOriginalSecurityManager() {
return original;
}
}
/** This example frame attempts to System.exit(0) on closing, we must
* prevent it from doing so. */
class TargetFrame extends JFrame {
TargetFrame() {
super("Close Me!");
add(new JLabel("Hi!"));
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.out.println("Bye!");
System.exit(0);
}
});
pack();
setSize( getPreferredSize() );
setLocationByPlatform(true);
setVisible(true);
}
}
The Eclipse RPC may be a good option to look at. It provides editor views which can easily be changed to enable / disable save, and other functionality at run time. Since Eclipse is written in Java, most Java code you already have will play nice with the framework.