about override run() method of GUI in main method - java

The issue is when I close my GUI windows I wanna run a last method ( for example printList() ) but I couldn't manage to do it. This is my main method
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
patientTest2 screen = new patientTest2();
screen.setVisible(true);
screen.setResizable(false);
} catch (FileNotFoundException ex) {
Logger.getLogger(patientTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
patientTest2 is my JFrame class. I assume that if I put printList() before } catch (FileNotFoundException ex) { it should work and finally print my list to a file but it doesn't. I will be glad if you can help me and explain why of course_?

You should add a listener that extends WindowAdapter to your frame, and override the method windowClosing(WindowEvent e). In this method, you will be able to call any methods you want to call before the window is closed.

You need to
change the default close operation to JFrame.DO_NOTHING_ON_CLOSE (if the window is a JFrame)
add a WindowListener to your top-level window
listen for window closing events, calling your method
and then finally exit the JVM with the appropriate exit code (usually 0 if no errors).

If you want to have something that runs when you Java VM gets shut down, then you should have a look at
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
//The stuff you want to do at shutdown.
}
}));
Please read the here for further information.
You also should set the DefaultCloseOperation of your Window if you want to close your Programm (and shutdown your Java VM) when the JFrame is closed.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
This is I think what you were asking for. Hope this helps.

Related

UI thread can not start after IDE changed

I changed my IDE from Eclipse to IntelliJ IDEA. The new one started complaining about my code.
public class Controller {
private OknoGlowne frame;
private MenuListener menuListen = new MenuListener(this);
private TabListener tabListener = new TabListener(this);
public OknoGlowne getFrame() {
return frame;
}
public Controller(){
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame = new OknoGlowne();
frame.setVisible(true); //error
frame.addMenuListener(menuListen);
frame.addTabListener(tabListener);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
So I commented this line. And add new line to constructor of UI frame.
public OknoGlowne() {
jPanel.setVisible(true);
}
App start but UI doesn't show any more. IDEA create frame in different way than Eclispe. I have to switch.
Main
public class Runner {
public static void main(String[] args) {
new Controller();
}
}
This doesn't really have anything to do with your IDEs. I bet if you ran it 100 times in eclipse, or from the command line, you'd get different results depending on how busy your system is.
The reason you aren't seeing the JFrame pop up is because you're using invokeLater() instead of invokeAndWait().
The invokeLater() method immediately returns, at which point you're in a race condition: will the event thread display the EDT first, or will the main thread exit first? If the main thread exits first, then your program will exit before any windows are shown.
To prevent this, you have to use invokeAndWait() instead of invokeLater().

When is Applet.stop() called?

I experiment with my applet using Eclipse and its Applet Viewer. The Applet Viewer appears on the top of Eclipse and during Applet execution I click on Eclipse icon to maximize it from task bar. Then Applet Viewer loses the focus and Applet.stop() gets called.
When I minimize Eclipse, Applet Viewer goes to front again, gains focus and Applet.start() gets called. This ends up in a complete mess.
Is it normal behavior for a browser to call Applet.stop once user changes to another Tab or minimizes the browser Can I disable that, I want stop never been called.
Maybe I am missing something in threads.
My code is something like this:
public class AppletApp extends JApplet {
public void init() {
super.init();
System.out.println("AppletApp.init()");
}
public void start() {
System.out.println("AppletApp.start()");
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
getContentPane().add(new JLabel("Test Label"));
}
});
} catch (InterruptedException e) {
} catch (InvocationTargetException e) {}
Runnable runnable = new Runnable() {
#Override
public void run() {
//For DJ Browser Component
NativeSwing.initialize();
NativeInterface.open();
//connect to server and start message exchange
Client.init(userInterface);
userInterface.authenticate();
NativeInterface.runEventPump();
}
};
Thread t = new Thread(runnable);
t.start();
}
public void stop() {
System.out.println("AppletApp.stop()");
}
public void destroy() {
System.out.println("AppletApp.destroy()");
}
}
Is it normal behavior for a browser to call Applet.stop once user
changes to another Tab or minimizes the browser?
Yes it is normal. From the javadoc:
Called by the browser or applet viewer to inform this applet that it
should stop its execution. It is called when the Web page that
contains this applet has been replaced by another page, and also just
before the applet is to be destroyed.
When you switch tab, I consider that the containing web page has been replaced hence it is logical that stop() is invoked.
Can I disable that, I want stop never been called.
No you can't, you don't have control on that. However, you could rely on the init() and the destroy() methods instead of start() and stop(). start() and stop() are meant for resuming/pausing anything that consumes resources which are not necessary if not visible (for example an animation is pointless if not visible).

Java: Let other threads know if GUI is ready to use

I'm writing an application which parses XML files (continuously) and show the data in a GUI (Swing). The ParseThread is in the CoreProject, and the GUI is in the GUIProject.
The start of the ParseThread is connected to a JCheckBoxMenuItem with an ItemListener. The value of setSelected() is set directly after adding to the Menu. At this time the GUI does not contain the Component which the ParseThread needs to show the parsed Data.
My Solution is, that the ParseThread should wait until the GUI is build completely.
I thought of something like an EventQueue but I have no Idea how to code one.
My Solution is, that the ParseThread should wait until the GUI is build completely. I thought of something like an EventQueue but I have no Idea how to code one.
you have got issue with Concurency in Swing, your hard and long running task should be moved to the Background task, for Swing there are two possibilities
(easy & simple) use Runnable#Thread, output to Swing GUI must be wrapped into invokeLater(), including thread safe methods as are setText, append e.i.
use SwingWorker
EDIT
please to check my visulaizations for Runnable#Thread this is the same thing as you connect server, parse long file e.i.,
with invokeLater() I cannot be sure that the component exists until the call
create GUI,
show GUI,
some (Swing / Util) Timer or user action to invoke code that is/are redirected out of Swing EventDispatchThread, for this reason there are Runnable#Thread or SwingWorker
I'm suggest two easiest of possible ways
Ok, I got my problem...
The GUI is created like this:
EventQueue.invokeAndWait(new Runnable() {
#Override
public void run() {
try {
Mainframe frame = new Mainframe();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
And at construction of the Object Mainframe this code will be executed:
final JCheckBoxMenuItem chckbxmntmParsing = new JCheckBoxMenuItem("Parsing");
chckbxmntmParsing.setName("mainframe.menu.data.parsing");
localeChangedListener.add(chckbxmntmParsing);
chckbxmntmParsing.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (chckbxmntmParsing.isSelected()) {
parseManager.startParsing();
} else {
parseManager.stopParsing();
}
}
});
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
boolean enabled = false;
String prop = PropertyManager.get().getProperty("parser.continuousparsing.enabled");
if (prop != null) {
if (prop.trim().equals("true") || prop.trim().equals("1")) {
enabled = true;
}
}
chckbxmntmParsing.setSelected(enabled);
}
});
So the ParseThread will start after GUI is build.
Sorry for stealing your time

Wait for Swing Interface to close before proceeding

I've been searching near and far for a solution to my question but I am having difficulty even defining my search terms.
I have a method that creates a Swing GUI using invokeLater where the user completes some task. Once the task is completed, the window closes and the initial calling thread (e.g. the method) should resume execution. To be more specific, here is a summary of the method:
public class dfTestCase extends JFrame{
public dfTestCase{
... //GUI code here
}
public String run()
{
CountDownLatch c = new CountDownLatch(1);
Runnable r = new Runnable()
{
public void run()
{
setVisible(true); //make GUI visible
}
};
javax.swing.SwingUtilities.invokeLater(r);
//now wait for the GUI to finish
try
{
testFinished.await();
} catch (InterruptedException e)
{
e.printStackTrace();
}
return "method finished";
}
public static void main(String args[]){
dfTestCase test = new dfTestCase();
System.out.println(test.run());
}
}
Within the GUI, I have actionListeners for buttons that will close and countDown the CountDownLatch.
While the CountDownLatch works, it is not suitable for my purposes because I need to run this GUI several times and there is no way to increment the latch. I'm looking for a more elegant solution - it is my best guess that I would need to make use of threads but am unsure how to go about this.
Any help would be much appreciated!
Update
Some clarification: What is happening is that an external class is calling the dfTestCase.run() function and expects a String to be returned. Essentially, the flow is linear with the external class calling dfTestCase.run()-->the GUI being invoked-->the user makes a decision and clicks a button-->control to the initial calling thread is returned and run() is completed.
For now my dirty solution is to just put a while loop with a flag to continuously poll the status of the GUI. I hope someone else can suggest a more elegant solution eventually.
public class dfTestCase extends JFrame{
public dfTestCase{
... //GUI code here
JButton button = new JButton();
button.addActionListener{
public void actionPerformed(ActionEvent e){
flag = true;
}
}
}
public String run()
{
Runnable r = new Runnable()
{
public void run(){
setVisible(true); //make GUI visible
};
javax.swing.SwingUtilities.invokeLater(r);
//now wait for the GUI to finish
while (!flag){
sleep(1000);
}
return "method finished";
}
public static void main(String args[]){
dfTestCase test = new dfTestCase();
System.out.println(test.run());
}
}
Modal dialogs and SwingUtilities#invokeAndWait iso invokeLater should allow you to capture user input and only continue the calling thread when the UI is disposed
For an example of using model dialogs you can check out the ParamDialog class I wrote. In particular, check out ParamDialog.getProperties(Properties);
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/ui/dialogs/

Catch exceptions in javax.swing application

I'm working with javax.swing to make an aplication which generates forms from XML Schema (using JAXFront library) and stores the data filled by the user them into XML documents.
I have put try-catch-finally blocks when I need it, but I have a little problem catching exceptions when the main thread ends (The AWT threads are still running).
I have two classes which do the main work and other classes which aren't important for the question:
Main class: It has the following structure. Initializes the application and runs the main frame
public class Main {
public static void main(String[] args) {
readArgs(); // An INI file with the app config
Model model = initializeElements(args); // My model class
try {
MyFrame mfr = new MyFrame(title,model);
mfr.visualize(); // Assembling view and setting visible
} catch( Excepion e ) {
doCleanUp();
System.exit(-1);
}
}
}
Frame Class: Generates the view and listen events
public class MyFrame extends JFrame implements ActionListener,MenuListener {
// Some attributes
// Other mthods without importance
/**
* Compose the elements, add listeners and set visible the frame
*/
public void visualize() {
generateFormPanel();
setListeners();
validate();
setVisible(true);
}
public MyFrame(String title, Modele model) {
super(title);
createElementsUsing(model);
}
public void actionPerformed(ActionEvent e) {
// Code to manage events
}
}
Well, the problem is the following:
When the visualize function is exectuted from the main method, the view is generated and showed. At that moment is when I lose the control of the exceptions catching. Then my question is if there are some way to catch the possible RuntimeExceptions throwed after this point.
I hope you understand my English and can answer the question.
Thanks in advance.
Simplest version is to set the default uncaught exception handler:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
// do something
}
});
But that catches uncaught exceptions thrown in other parts of the program aswell.
You could however catch only runtime exceptions thrown off the swing event dispatching thread using a proxy (See this page for more information, copied code from there):
class EventQueueProxy extends EventQueue {
protected void dispatchEvent(AWTEvent newEvent) {
try {
super.dispatchEvent(newEvent);
} catch (Throwable t) {
// do something more useful than: t.printStackTrace();
}
}
}
Now installing it like this:
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventQueueProxy());
After you have called visualize() the only thread running is the Swing/AWT event dispatch thread. If you want to catch any exceptions you will need to do so in any of your listener methods that are called on this thread e.g.
public void actionPerformed(ActionEvent e) {
try {
// Some code here
} catch(RuntimeException e) {
// Handling code here
}
}
To prevent boilerplate you can have this code in a super class.
Note that you can also set a default uncaught exception handler if you want to catch anything not already dealt with by the Swing/AWT thread.
Note also that in general it is best practice to not catch subclasses of RuntimeException if you can avoid it.
Try adding:
setDefaultCloseOperation(EXIT_ON_CLOSE);
to MyFrame constructor. Not sure though, but worth trying.

Categories

Resources