Accessing modal dialog variable after calling dispose method - java

Situation: a main form calls a modal jDialog with textboxes in which parameters are filled in by the user to create or modify an instance of a certain class, call it ClassA.
When the dialog needs to modify an existing instance, it is passed in the constructor as a parameter. Otherwise the jDialog will create a new instance of ClassA.
Problem: the mainform needs to access that new instance, and I think it is unclean code to pass the entire main form as a parameter, and let the dialog push the new instance into it by a method call, because that way a perfectly re-usable stand-alone dialog becomes only usable with one single main form that needs a certain classname and method to receive the new instance.
It is much more logical to make the main form get the new instance from the jdialog after the OK button is clicked, by calling a getClassAInstance() method (which could be called also when an existing instance was being modified). The method is called after the "setVisible(true)" method on a new instance of the jdialog in question. The dialog appears, the thread of the main form will sleep until the dialog is closed (because it is modal). The OK button calls the dispose() method of the jDialog, then the very next statement is the getClassAInstance() call on the jDialog by the mainform.
Here's the same thing in code..
ClassAInstanceMakerDialog imd = new ClassAInstanceMakerDialog(this, true);
imd.setVisible(true);
//imd.dispose(); after OK button click
System.out.println(imd.getClassAInstance()); //return a new ClassA instance
//output: whatever ClassA.toString() should return, works fine
Question: I've tried it and it seems to work perfectly fine. But, is it a good code? Is there any danger of the getClassAInstance() method returning "null", because the garbage collector collected the ClassA instance after the jDialog was disposed and before the main form could complete the call?
Please excuse me if I didn't make myself clear, I'm not a native English speaker. If you would rather see some code, let me know...

I think it's perfectly legal to access the member variable of your dialog instance that holds the ClassA instance, the dialog instance will not be garbage collected until it goes out of scope, not just because you called dispose on it.
I'd give slight preference to a solution where you define an event handler interface with a signature of
someThingHappened(ClassA toThisObject), make your mainform or anything that might be interested that ClassA thing implement that interface make it possible to add listeners to the dialog before making it visible.
That way, you would loosen the coupling between the dialog and the main form a little.

I don't think that dispose() sets the JDialog up for garbage collection, but instead just releases resources. The dialog is still re-usable as per the Window API (since JDialog inherits this method from Window):
Releases all of the native screen resources used by this Window, its subcomponents, and all of its owned children. That is, the resources for these Components will be destroyed, any memory they consume will be returned to the OS, and they will be marked as undisplayable.
The Window and its subcomponents can be made displayable again by rebuilding the native resources with a subsequent call to pack or show. The states of the recreated Window and its subcomponents will be identical to the states of these objects at the point where the Window was disposed (not accounting for additional modifications between those actions).
Note: When the last displayable window within the Java virtual machine (VM) is disposed of, the VM may terminate. See AWT Threading Issues for more information.
As long as there are valid reachable references to the JDialog object still present, it will not be garbage collected. I think that the cost of disposing the dialog is that your code will need to spend a (very) little bit of time to re-create the resources.

It is perfectly reasonable and appropriate to have an IDisposable include properties or methods which may be used after Dispose is called to return information about things which happened before Dispose was called. Rather than blindly enforcing a rule that any and all methods of a disposed object should throw an ObjectDisposedException, one should instead consider which methods and properties do or do not make sense on disposed objects. Attempting to access a disposed object should throw ObjectDisposedException in preference to re-acquiring released resources or letting escape some other exception which occurs as a consequence of the disposal. If the method or property access can succeed without any of the released resources, it should often be allowed to do so.

Related

How can I switch from JFrame to java class?

I've been trying to figure out how to go from a JFrame to my java class.
This was my code so far: (It only opens the main..which is the JFrame)
Process process = Runtime.getRuntime().exec("cmd.exe /c start java -jar \C:\Users\Admin\Documents\NetBeansProjects\Program\dist\Program.jar");
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
The main used to be the class, making it easy for me to use setvislble() for the frame, but now I need it backwards and the main is now the JFrame. I need to know how to open the class file. (Also if anyone knows how to switch besides using CMD that would be great!)
I've tried used this plus a combination of other variations but it won't work.
java -cp "C:\Users\Admin\Documents\NetBeansProjects\Program\dist\Program.jar class"
JFrame button, if my understanding is correct, does not handle infinite loops well.
The idea is not to block the EDT, but there are certainly correct ways to repeat an action (until told otherwise) in Swing, as well as ways to do long running tasks. Here is some advice I commonly give:
Don't block the EDT (Event Dispatch Thread). The GUI will 'freeze' when that happens. See Concurrency in Swing for details and the fix.
But back to the matter at hand..
..getting the user to input information in the GUI, then sending that information into a text file. The class reads the text file, gets the information and does its things..
OK that is 10 different kinds of wrong.
Let's say the GUI is called GUI.class, the other class is called Worker.class.
Worker.class
This class might have a no-args constructor as well as a constructor that accepts an InputStream (for the text file, if it is finally needed).
The Worker class might have a main(String[]) that creates an instance of a Worker object. It might use either:
An InputStream for the constructor of the Worker, from which it would configure the fields needed for the work to be done.
A no-args constructor for the Worker instance, then use setter methods for configuring it. (Maybe prompting the user through the command line to supply the information.)
Once the main has done that, call execute() on the Worker instance and call getter methods for the results, then write the results to System.out.
GUI.class
The GUI can also use a Worker instance. It would probably use the no-args variant then bind the setter methods to the input controls in the GUI. Once the user clicks the Execute button, execute() the process, then query the getter methods to display the results to the user (still in the GUI).

jDialog disposed but still in jFrame.getOwnedWindows

I have a JFrame (EC_GUI.main) and then I create several JDialogs to which I add a JPanel, passing the JFrame as owner.
I am now in the process of detecting if any of these JDialogs are opened through the jFrame.getOwnedWindows(), since I can't get them through one of this
EC_GUI.main.getComponentCount() 1
javax.swing.JRootPane[,0,0,755x1005,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=]
EC_GUI.main.getRootPane().getComponentCount() 2
javax.swing.JPanel[null.glassPane,0,0,755x1005,hidden,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777217,maximumSize=,minimumSize=,preferredSize=]
javax.swing.JLayeredPane[null.layeredPane,0,0,755x1005,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,optimizedDrawingPossible=true]
EC_GUI.main.getContentPane().getComponentCount() 1
ec.gui.dialogs.template.EC_BorderPanel[,0,0,755x1005,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.border.EmptyBorder#44e6097c,flags=9,maximumSize=,minimumSize=,preferredSize=]
But I do get them if I query the ownedWindows
EC_GUI.main.getOwnedWindows().length 1
ec.gui.dialogs.visivilityfield.EC_VrPresetDialog$1[dialog0,385,254,502x511,invalid,hidden,layout=java.awt.BorderLayout,MODELESS,title=Virtual Reality Presets,defaultCloseOperation=DO_NOTHING_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,502x511,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
I noticed that even if I call jDialog.dispose() I still have a reference so if I open and close, let's say 3 times, one of my JDialogs, I get
EC_GUI.main.getOwnedWindows().length 3
ec.gui.dialogs.visivilityfield.EC_VrPresetDialog$1[dialog1,385,254,502x511,invalid,hidden,layout=java.awt.BorderLayout,MODELESS,title=Virtual Reality Presets,defaultCloseOperation=DO_NOTHING_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,502x511,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
ec.gui.dialogs.visivilityfield.EC_VrPresetDialog$1[dialog2,385,254,502x511,invalid,hidden,layout=java.awt.BorderLayout,MODELESS,title=Virtual Reality Presets,defaultCloseOperation=DO_NOTHING_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,502x511,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
ec.gui.dialogs.visivilityfield.EC_VrPresetDialog$1[dialog3,385,254,502x511,invalid,hidden,layout=java.awt.BorderLayout,MODELESS,title=Virtual Reality Presets,defaultCloseOperation=DO_NOTHING_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,502x511,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
Is this normal?
You read through the JavaDocs you will not that, when configured correctly, dispose will release the native resources that the window is using, this does not "dispose" of the object, you can re-show the window by calling setVisible.
You could check the isDisplayable (which will let you know if the window still has a reference to it's native peer) or the more reliable isVisible option...
If the dialog has no other strong references, it will, eventually be garbage collected.

How to delete a class object? [duplicate]

This question already has answers here:
Deleting an object in java?
(7 answers)
Closed 9 years ago.
I have an object called CounterGUI. It creates a GUI. I create it in another class, say MyProgram.
Once MyProgram creates a CounterGUI object, how do I delete the object? Say if I do this:
CounterGUI first = new CounterGUI(); //displays the GUI
first = null;
I thought setting the object to null would delete everything (including the GUI), but it doesn't. How do I completely delete it?
I don't see how this is a duplicate question, the previous answers were to set it to null or a new object, but that doesn't work here.
Assuming that CounterGUI is a java.awt.Window, then:
The way to make the window disappear is to call setVisible(false).
The way to disconnect it entirely from the native windowing is to call dispose().
Once the Window has been disposed, making it unreachable (e.g. by assigning null to all of your variables that reference it) will make it eligible for garbage collection.
Simply assigning null while the Window is visible will have no effect. The a visible Window object is connected to various things that prevent it from being garbage collected.
Java uses automatic garbage collection. When you set an object to null and it is the last reference remaining, the JVM will reclaim the memory used.
In your case, however, it may be that a thread is created (with GUIs this is often the case) and a reference to the current object is given to it. In this case, setting the reference to null has no effect as something else still has access to the object.
In order to properly close your GUI, you have to invoke a close method. For a JFrame, you can try this:
myGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
which will close the application when the user clicks the close button. If you want to control closing by the program, then you can try:
private void closeItDown() {
WindowEvent event = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
}
...and calling this method. You don't have to set anything to null, the JVM will garbage collect for you at this point, maybe. Not guaranteed, but possibly at this point, perhaps later, or now... or whenever :)
Deleting an object by setting its reference to null make it eligible for garbage collection and JVM will take care of removal of all those object. If you wants to force the garbage collector to run you can issue System.gc() or Runtime.gc () but it is still not a guarantee that it will be collected back to JVM. You can find further information on how garbage collector works here
If you wants to remove your GUI window you can use dispose() method.
you want to make disappear GUI then dispose()
you dont have to worry about this , Garbage collector will automatically take it out of memory or
you can invoke it yourself
System.gc()
but it is bad practice as well as not guaranteed that it will surely being collected.

GWT: finalize object and remove its event handlers

In GWT I have class MyClass that registers some event handlers. There is an object (object1) of MyClass that, at a specific moment, I want to finalize and make its handlers stop listening, because after that I am going to create a different MyClass object (object2).
How can I do that? I already tried with object1 = null, but its handerls keep listening (at least for a while).
The handlers might still exist because the gc didn't get around destroying them.
If it is important that the listeners don't continue to exist then they need to be deregistered.
One way to do this is by deregistering the HandlerRegistration. For example a addClickHandler returns a HandlerRegistration which can be deregistered. When and how to do this depends on your GUI classes. You could put the deregistration in your finalize method but you will probably find that these methods are called very sporadically because of the gc and of course because this is not java but javaScript. So concider putting them in a detach or destroy method of your gui element onDetach or onUnload.

In swing-java, where does the Graphics instance come from?

When an update request is delivered to swing (either system triggered e.g. because of a resize or a block by another window, or app-triggered e.g. by a call to repaint() method), how is this request actually handled? What procedure takes place in that RepaintManager thing?
From your comment:
Do you know what happens in peer.getGraphics()?
That depends on which peer implementation is used.
One implementation is WComponentPeer (used when running on Windows), which seems to use two ways for getting the Graphics object:
If the component has a parent of type Window (or is one itself) which in turn has a back buffer immage associated, that image's Graphics object is returned. This depends on the type of image but is most likeley a SunGraphics2D instance, created in createGraphics().
Otherwise a ScreenUpdateManager instance is retrieved and createGraphics(...) is called on it which in turn returns a new SunGraphics2D instance.
Please note that this is just one possible way and it highly depends on the OS, the JVM and UI toolkit used.

Categories