Rabbitmcv
Rabbitmcv

Reputation: 15

JFrame GUI Freeze + Phantom

Okay I understand that I should not have this loop

while (pidInfo.contains(<processname>)){
    pidInfo ="";
    check<processname> =Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
    input =  new BufferedReader(new InputStreamReader(check<processname>.getInputStream()));

    while ((line = input.readLine()) != null) {
        pidInfo+=line; 
    }

    input.close();

    if (pidInfo.contains(<processname>)){
        System.out.println("<processname> RUNNING");
    }
    else if (closeReason == 2){
        System.out.println("<processname> STOPPED VIA PROG & USER");
        status = "Not Running";
        int ll = JOptionPane.showOptionDialog(null, "<processname>", "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, null, null);
        if (ll == JOptionPane.OK_OPTION){
            //frame.setAlwaysOnTop(true);
            frame.dispose();
        }
    }
    // TODO: Other exit
} 

based on other questions BUT

I don't understand why when I launch this frame (this is the 2nd one) from the first one it freezes but if I launch the 2nd frame separately it displays.

I hope to takeaway from this question 2 things

1: How to code the thing (threadworker?) that runs the loop in the background.

2: Why it doesn't freeze when I launch it from the first frame (see below)

Thank you in advance & here is the first frame code

if(pidInfo.contains(<processname>)) {
    frame.setAlwaysOnTop(false);
    status = "Running - In Game";

    System.out.println("<processname>1st RUNNING");
    int a = JOptionPane.showOptionDialog(null, "SUCCESS!", "Success", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, null, null);
    if (a == JOptionPane.OK_OPTION) {
        frame.dispose();
        new 2ndFrameRunning();
    }
}

The 2ndFrameRunning is the 2nd frame, it has been changed from its actual name so that's why it is kind of breaking the java grammar rules.

No Errors as well just the "phantom" freeze.

EXAMPLE CODE

Frame 1: Named "menu.java"

/* Stack Overflow
* By Rabbitmcv
*/
package main;
// Imports
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.awt.*;
import javax.swing.*;

public class Menu implements ActionListener{
    // Func
    // Creates the JFrame
    JFrame frame = new JFrame();
    // Public Vars
    boolean isGameRunning = false;
    String status = "Not Running - In Main Menu";
    // All code goes here
        public Menu(){
            // Vars
            // Frame Vars
            frame.setResizable(false);
            frame.setSize(800, 600);
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
            frame.setAlwaysOnTop(true);
            // JPanels
            JPanel defaultPanel = new JPanel();
            // DefaultPanel J...
            JLabel title = new JLabel("FirstLabel");
            JLabel risk = new JLabel("SecondLabel");
            JLabel titleSub = new JLabel("StackOverflow");
            JButton start2frame = new JButton("start2frame");
            // DefaultPanel Button Code
            start2frame.addActionListener(new ActionListener(){
                @Override
                public void actionPerformed(ActionEvent arg0){
                    System.out.println("start2frame button pressed");
                    try{
                        String line;
                        String pidInfo ="";

                        Process checkcs =Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe");

                        BufferedReader input =  new BufferedReader(new InputStreamReader(checkcs.getInputStream()));

                        while ((line = input.readLine()) != null) {
                            pidInfo+=line; 
                        }

                        input.close();

                        if(pidInfo.contains("explorer.exe")) // The process name here has been changed from the real process for StackOverflow.
                        {
                            frame.setAlwaysOnTop(false);
                            status = "Running - In Game";
                            frame.setTitle("StackOverflow - "+status);
                            System.out.println("1st Game RUNNING");
                            // TODO: hackRunning 
                            int a = JOptionPane.showOptionDialog(null, "SUCCESS", "Success", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, null, null);
                            if (a == JOptionPane.OK_OPTION){
                                frame.dispose();
                                new second();
                            }
                        }
                        else{
                            isGameRunning = false;
                            status = "Not Running - ERROR: Game NOT RUNNING";
                            frame.setTitle("StackOverflow - "+status);
                            System.out.println("game NOT RUNNING");
                            frame.setAlwaysOnTop(false);
                            int a = JOptionPane.showOptionDialog(null, "Game is not running", "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, null, null);
                                    if (a == JOptionPane.OK_OPTION){
                                        frame.setAlwaysOnTop(true);
                                    }
                        }
                    }
                    catch(Exception e){
                        System.out.println("Failed to check process");
                        e.printStackTrace();
                    }
                }
            });
            // Set Layouts 
            defaultPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
            defaultPanel.setLayout(new GridLayout(0, 1));
            // Adds the J... to a Jpanel (IN ORDER FROM TOP TO BOTTOM)
            defaultPanel.add(title);
            defaultPanel.add(risk);
            defaultPanel.add(titleSub);
            defaultPanel.add(start2frame);
            // Center Labels
            title.setHorizontalAlignment(JLabel.CENTER);
            risk.setHorizontalAlignment(JLabel.CENTER);
            titleSub.setHorizontalAlignment(JLabel.CENTER);
            // Add the JPanel to the JFrame
            frame.add(defaultPanel);
            // Vis
            frame.revalidate();
            frame.setTitle("StackOverflow - "+status);
            frame.setVisible(true);
    }

        public static void main (String args[]){
            new Menu();
        }
    @Override
    public void actionPerformed(ActionEvent e) {
        // AUTO: Because of actionlistener

    }

}

FRAME 2 Named "second.java"

/* StackOverflow - 2nd
* By Rabbitmcv
* If one runs this one sans the first program it shows non-frozen... but if you run it from menu.java it will freeze... probably something with threads.
*/
package main;

// Import
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.awt.*;
import javax.swing.*;
// This file has been renamed to 2.java
public class second implements ActionListener{
    // Frame
    JFrame frame= new JFrame();
    // Panel
    JPanel panel = new JPanel();
    // Int
    // closeReason: 0 = user, 1 = program, 2 = user init via prog (non-error)
    int closeReason = 0;
    // String
    String status = "Running";
    public second(){
        // Set Settings
        frame.setResizable(false);
        frame.setSize(800, 600);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
        frame.setAlwaysOnTop(true);
        // Crap

        frame.setTitle("StackOverflow- Running");
        // Settings
        // Add J...
        JLabel label = new JLabel("Game "+status);
        JButton closeGameButton = new JButton("Click here to close game");
        // Adds the J... to a Jpanel (IN ORDER FROM TOP TO BOTTOM)
        panel.add(label);
        panel.add(closeGameButton);
        // Button Func.
        closeGameButton.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent arg0){
                try {
                    System.out.println("CloseGameButton Pressed");
                    Process killGame = Runtime.getRuntime().exec("taskkill /F /IM explorer.exe"); // My process has been changed to explorer.exe !!!! THIS WILL STOP WINDOWS EXPLORER. Feel free to change it to another process
                    closeReason = 2;
                    int exitCode = killGame.waitFor();
                    if (exitCode != 0){
                        throw new IOException("Failed to kill game; game not running");
                    }
                    frame.setTitle("StackOverflow - Not Running - Closed by user");
                    frame.setAlwaysOnTop(false);
                    int a = JOptionPane.showOptionDialog(null, "game has been closed", "game Closed", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, null, null);
                    if (a == JOptionPane.OK_OPTION){
                        frame.setAlwaysOnTop(true);
                        frame.setTitle("StackOverflow - Not Running - Closed by user");
                    }
                } catch (Exception e) {
                    frame.setAlwaysOnTop(false);
                    System.out.println("Failed to kill game");
                    int a = JOptionPane.showOptionDialog(null, "game is not running", "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, null, null);
                    if (a == JOptionPane.OK_OPTION){
                        frame.setAlwaysOnTop(true);
                    }
                    e.printStackTrace();
                }
            }
        });
        // END BUTTON FUNC
        // Set layouts
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 30, 10));
        panel.setLayout(new GridLayout(0, 1));
        // Center Labels
        label.setHorizontalAlignment(JLabel.CENTER);
        // Add the JPanel to the JFrame
        frame.add(panel);
        // end
        frame.revalidate();
        System.out.println("far");
        frame.setVisible(true);

        try{
            String line;
            String pidInfo ="";

            Process checkcs =Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe");

            BufferedReader input =  new BufferedReader(new InputStreamReader(checkcs.getInputStream()));

            while ((line = input.readLine()) != null) {
                pidInfo+=line; 
            }

            input.close();

            if (pidInfo.contains("explorer.exe")){ // Changed to explorer.exe
                System.out.println("game running - pid");
                status = "Running";
                while (pidInfo.contains("explorer.exe")){ // Changed to explorer.exe
                    pidInfo ="";
                    checkcs =Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
                    input =  new BufferedReader(new InputStreamReader(checkcs.getInputStream()));

                    while ((line = input.readLine()) != null) {
                        pidInfo+=line; 
                    }

                    input.close();

                    if (pidInfo.contains("explorer.exe")){ // This checks if the process is still going on... changed to explorer.exe
                        System.out.println("game RUNNING");
                    }
                    else if (closeReason == 2){
                        System.out.println("game STOPPED VIA PROG & USER");
                        status = "Not Running";
                        int ll = JOptionPane.showOptionDialog(null, "game has stopped running", "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, null, null);
                        if (ll == JOptionPane.OK_OPTION){
                            //frame.setAlwaysOnTop(true);
                            frame.dispose();
                        }
                    }
                    // TODO: Other exit
                }
            }
        }
        catch(Exception e){
            System.out.println("Failed to check process");
            e.printStackTrace();
        }
    }
    public static void main (String args[]){
        new second(); //StackOverflow
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub

    }
}

If you don't like that you can just download the .zip w/ all the files

https://drive.google.com/open?id=0BzuCgrBgpuD1V3dKLUFfQU12UWc

Upvotes: 0

Views: 113

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347294

As I said in my comments, when...

public static void main (String args[]){
    new second(); //StackOverflow
}

is called (ie by the JVM because you've executed the class from the command line), it is running in the "main" thread of the JVM.

This means that the code in the constructor IS NOT been executed within the context of the Event Dispatching Thread and therefore does not block the UI.

When you call frame.setVisible, the underlying API will create the Event Dispatching Thread and all UI based code will be executed on a separate thread, leaving what you started in the constructor to execute within the context of the "main" thread.

When the ActionListener for the closeGameButton is called, that WILL block the Event Dispatching Thread until killGame completes regardless of how you started the code.

You can make second act the same way by changing

public static void main (String args[]){
    new second(); //StackOverflow
}

to

public static void main (String args[]){
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            new second(); //StackOverflow
        }
    });
}

Which is how you should start ALL your Swing applications

I would suggest you start by taking a look at Concurrency in Swing and Worker Threads and SwingWorker

Upvotes: 1

Related Questions