How to create JFrame from another main class as separate thread - java

I want to create one Jframe from another class (main class) and then I want to display Jframe only if no error in main method. Otherwise I want to create & display dialog by passing that same jframe.
I forgot thread concept anywhere give me the solution, I tried below code, that prints "abcde" but not display the frame program complete.
Note : there is no main method in JFrame od ErrorDialog. They are just custom container.
public class Start{
public static Main mf=null;
public static void main(String args[]){
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
mf = new Main();
}
});
try {
// Some extra code
System.out.println("abcde"); // this is print and then program complete
mf.setVisible(true); // this line will not run
} catch (Exception e) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ErrorDialog(mf, true).setVisible(true);;
}
});
}
}
}

Try my suggestion its working..
Just use invokeAndWait() method insted of using invokeLater() method.
Because invokeLater() method create NullpointerException.
But invokeAndWait() must be inside try-catch block.
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
mf = new Main();
}
});
} catch (Exception e) {
System.out.println(e);
}

Related

Why does my JFrame move to the background after closing modal JDialog

Edit: Updated question including a MRE and an answer can be found here.
I'm pretty lost after stumbling across this issue and finding no way to resolve it myself.
Description:
I have an application which has a Java Swing GUI. All the communication to the GUI is done via custom Events, mostly created by the main program, which are then processed by a Controller to control the GUI.
One event I have will trigger the Controller to open a custom Modal JDialog which acts just as a "please wait while the stuff in the background is being processed". So after the background task is finished, an Event will trigger the Dialog to dispose, to make the main GUI frame accessible again.
The issue:
When the Dialog is disposed, the main Frame will magically be set to the background. Not minimized, not completely in the background of all open windows, but actually in the background of the last open window. I'm completely lost on how and why this happens.
The important parts of the Controller class look vaguely like this:
class Controller {
private ModalWaitDialog dialog;
private JFrame frame;
private void createMainFrame() {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
// create frame
frame = new JFrame();
// make the frame visible
frame.setVisible(true);
}
});
}
private void showWaitPopup(String msg) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
modalWaitDialog = new ModalWaitDialog(frame, message);
modalWaitDialog.showDialog();
}
});
}
// after this was executed, my frame will be set in the background
private void endWaitPopup() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (modalWaitDialog != null) {
modalWaitDialog.dispose();
modalWaitDialog = null;
}
}
});
}
}
I know this is not a MCVE, but maybe somebody knows how and why this happens.
Edit:
I added a WindowFocusListener to the Frame and added some print statements to the endWaitPopup, and called invokeAndWait to further see what is happening. The following is the result:
private void endWaitPopup() {
System.out.println("In EndWaitPopup");
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.out.println("EndWaitPopup... run started");
// implement as if it could be called if no wait popup is available
if (modalWaitDialog != null) {
System.out.println("Disposing the modal dialog");
modalWaitDialog.dispose();
modalWaitDialog = null;
}
System.out.println("End of EndWaitPopup");
}
});
} catch (InvocationTargetException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Output:
In EndWaitPopup
+++Focus of Frame lost+++
EndWaitPopup... run started
Disposing the modal dialog
End of EndWaitPopup

How to reload a Java Swing GUI?

I need to refresh my GUI each time a function is triggered.
This is how I defined the skeleton of the GUI:
public class GUI {
private JFrame frame;
/**
* Launch the application.
*/
public static void runGui() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI window = new GUI();
window.frame.setVisible(true);
window.frame.setSize(800, 600);
window.frame.setTitle("My Title");
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public GUI() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
//CODE
}
So, the GUI.runGui() function is called in a function like:
public void myFunction()
{
//CODE
GUI.runGui();
}
The problem is the following: every time this function is called, it generates a new instance of the GUI, so I end up having multiple instances. This is not what I want, since I just need to refresh the content of the GUI that must be only one.
I believe the problem is architectural.
Is there a way to solve this?
Look at what runGui is doing: it's creating and initializing a GUI every time you call it. Pull that one time initialization code out of runGui and into another place that you run once (like the initialize method). And in runGui access a component that you want to refresh (perhaps the content pane) as:
// This needs to become an instance method (non static) in this example in
// order to access the frame
public void runGui() {
EventQueue.invokeLater(new Runnable() {
public void run() {
// Refresh your component here. Here I'm redrawing the
// content pane
frame.getContentPane().repaint();
}
});
}
frame.repaint();
This article contains some repaint examples:
https://www.programcreek.com/java-api-examples/?class=javax.swing.JFrame&method=repaint
The solution is to get the content pane from the frame and then use .repaint(). You can do the following:
JFrame frame = new JFrame("Title");
frame.getContentPane().repaint();

Java: How will I be able to create a Stop JButton which will stop the Runnable() thread?

I have created a simple HTTP server in Java by using a ServerSocket that accepts browser requests. The server is working fine without any errors. I have created a JForm using Swing that contains buttons to start and stop the server. In the start button I have added an ActionListener that runs my ServerMain class.
btnStartServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
try {
new Thread(new Runnable() {
public void run() {
ServerMain.main(new String[0]);
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}});
How will I be able to create a Stop JButton which will stop the Runnable() thread?
Run the server in the context of a class that implements the cancel() method of Future<V>. SwingWorker<T,V> is such a RunnableFuture<V>; a complete example is seen here.
You don't want to just kill a thread (by using Thread.stop()). The reasons why are listed in this article.
I assume the code in ServerMain.main(String... args) runs some kind of while(condition) loop, like this:
public class ServerMain{
public static boolean condition = true;
public static void main(String... args){
while(condition){
//do stuff
}
//close sockets and other streams.
//Call Thread.interupt() on all sleeping threads
}
}
Your button should set this condition to false somehow:
stopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
try {
new Thread() {
public void run() {
// set condition to false;
ServerMain.condition = false;
}
}.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});

manipulating jLabel from main method in netbeans

I am trying to change the text inside a jLabel from the main method, the reason for this is because there are conditions that I need to meet for the change to happen and it is not trigger based.
Code:
public class TheMain extends javax.swing.JFrame {
public TheMain() {
initComponents();
}
public void changeLabel1(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jLabel1.setText("looo");
}
});
}
public void changeLabel2(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jLabel2.setText("looo");
}
});
}
public static void main(String args[]) {
TheMain some = new TheMain();
if(condition){
some.changeLabel1();
}else{
some.changeLabel2();
}
}
}
I tried printing some stuff inside changelabel1 and changelabel2 just to check if they are successfully called and it did print but I'm guessing it is not possible to implement the UI changes inside them, or am I mistaken?
if(condition){
some.changeLabel1();
}else{
some.changeLabel2();
}
The above logice needs to be defined in TheMain class because that is where the label variables will be defined.
The main() method is just used to create the GUI. There should be no application logic in the main() method.

Java Threading Issue with run()

I have 2 classes defined below:
public class TextsManager extends Thread {
LinkedList<String> lstOfPendingStr = new LinkedList<String>();
boolean stopLoop = false;
JTextArea txtArea;
public void run()
{
while (!stopLoop)
{
while (!lstOfPendingStr.isEmpty())
{
String tmp = lstOfPendingStr.getFirst();
this.txtArea.append(tmp);
lstOfPendingStr.removeFirst();
}
try {
Thread.sleep(0); // note: I had to force this code
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void AddNewStr(String newStr)
{
this.lstOfPendingStr.add(newStr);
}
}
And
public class ClientApp {
private JFrame frame;
private JTextField textField;
private JTextArea textArea;
static private TextsManager txtManager;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClientApp window = new ClientApp();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ClientApp() {
initialize();
/*
* Client app
*/
txtManager = new TextsManager(textArea);
txtManager.start();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
textArea = new JTextArea();
textField = new JTextField();
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
txtManager.AddNewStr(textField.getText() + "\n");
textField.setText("");
}
}
});
}
}
The program will read User Input from textField, pass it into TextsManager.lstOfPendingStr. Then, on each loop inside TextsManager.run(), it will check for existed members in lstOfPendingStr and output them via txtArea.
The problem is that if I removed the code Thread.sleep(0) inside run(), the run() then apparently stopped working. Despite lstOfPendingStr had been successfully updated with new elements, codes inside the loop while(!lstOfPendingStr.isEmpty()) would not ever to be called.
I put hard codes such as System.out.println or Thread.sleep(0) (as in the provided code) inside the while(!stopLoop), then it worked fine.
Although, I managed to solve the problem by forcing the thread to sleep for a few miliseconds, I want to know the reason behind this issue.
I appreciate your wisdom.
Regard :)
You have a couple of problems.
You are calling methods on lstOfPendingStr from two threads, but initialized it with LinkedList, which is not thread-safe. You should use a thread safe class, LinkedBlockingQueue seems the best options as far as I understood from your code.
Inside the thread you are calling JTextArea#append(). As all AWT/Swing methods, you can not call them from arbitrary threads, but only from the AWT thread. Wrap the call inside an invokeLater block.
The fact that sleep appears to make your code work is just a sign of the concurrency problems.

Categories

Resources