简体   繁体   中英

Java - Swing GUI doesn't load

I've been trying to learn java for a few weeks now, and I'm working on a pretty simple autoclicker. The clicker itself works, but my problem is that my GUI never shows up. The GUI runs just fine when I run the GUI file itself, but when I'm trying to run it from my main program (different file) it never shows. The clicker works fine all the time though. I'm sure the problem is something really simple that I have simply missed, but this is now my 4th day without any clue on what might be wrong with it, so decided I'd ask here.

Beware - the code is really messy atm, because I've been trying pretty much everything possible to get it working.

This is the code in the main program trying to run the GUI.

package autoclicker;

import java.awt.AWTException;

/**
 * The main program for the autoclicker.
 */
public class AutoClicker {
    public static void main(String[] args) throws AWTException {
        Click click = new Click(true);
        click.clicker();
        try {
            Swingerinos sw = new Swingerinos();
            sw.initialize();
        }
        catch (AWTException e) { e. printStackTrace(); System.exit(-1); }
    }
}

And this is the whole GUI file.

package autoclicker;

import java.awt.*;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;


public class Swingerinos extends Click implements WindowListener,ActionListener {

    private int numClicks = 0;
    TextField text;

    private JFrame frame;
    /**
     * @wbp.nonvisual location=181,19
     */
    private final JLabel lblAutoclicker = new JLabel("AutoClicker");

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Swingerinos window = new Swingerinos();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Swingerinos() throws AWTException {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    public void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 109);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        frame.getContentPane().add(panel, BorderLayout.WEST);

        JButton btnNewButton = new JButton("Toggle On / Off");
        text = new TextField(20);
        text.setLocation(100, 100);
        btnNewButton.addActionListener( this);
        btnNewButton.setToolTipText("Toggles the  autoclicker on / off.");
        panel.add(btnNewButton);
        panel.add(text);
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        toggle();
        numClicks++;
        text.setText(""+numClicks);
    }


    public void windowClosing(WindowEvent e) {
        System.exit(0);
    }

    public void windowOpened(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

}

I know the GUI file is really messy (there's 2x initialize(), one in the main program and one in the GUI file, and lots of other stuff, but I'm just too confused as for what to do now.

EDIT: I added the whole main program code, also this is the code for the autoclicker.

package autoclicker;

import java.awt.*;
import java.awt.event.InputEvent;

public class Click {
    private boolean active;
    private Robot robot;

    public Click(boolean active, Robot robot) {
        this.active = active;
        this.robot = robot;
    }

    public Click() throws AWTException {
        this(false, new Robot());
    }

    public Click(boolean active) throws AWTException {
        this(active, new Robot());
    }

    //TODO: add click.toggle() to somewhere and control da clicker
    public void toggle() {
        active = !active;
    }

    public void clicker() {
        while (active) {
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
            robot.setAutoDelay(10000);
        }
    }
}

Expanding JB Nizet's comment(s) into an answer.

The immediate cause:

When the JVM calls your code, it is run on the main thread. It calls main(String[]) , as you know. You posted two main methods, only one of which is relevant to your nothing-is-happening problem: AutoClick#main(String[]) . Let's go through it:

Click click = new Click(true);
click.clicker();

This first of the above two lines obviously calls the constructor of Click , which sets the active variable to true . So far so good. The second line is much more interesting. It calls Click#clicker() . Let's look at that method:

public void clicker() {
    while (active) {
        // <snip>
    }
}

This method is the problem. Since you haven't started any other threads, the main thread is the only one you have at that moment, the only thread on which you can execute code. When this loop is executed it only finishes when the active variable is set to false . As long as it is true, it will keep looping. This means that Click#clicker() only returns if active is set to false . But, you never do that in the loop itself, meaning you need a thread different from the thread executing the loop to change active . So, how many threads do we have? 1, the main thread. See the problem? Because the loop never ends, the main thread never reaches the statements in the main method after click.clicker() .

Simple solution

You could just set a fixed number of iterations:

public void clicker() {
    int i = 0;
    while (i < 100) { // iterate 100 times
        // <snip>
        ++i;
    }
}

Or using a for-loop (recommended):

public void clicker() {
    for (int i = 0; i < 100; ++i) {
        // <snip>
    }
}

This eliminates the need for the active variable and hence the need for another thread.

A somewhat more complicated solution

If you really want the active variable, you'll need to have multiple threads. This is conveniently known as "multithreading" 1 , a very complicated topic. Luckily, we only need a bit of it, so it is only a bit complicated.

Don't just call the method Click#clicker() like you would normally. This creates your current problem. You'll need a worker thread, which can call the method. The easiest way to create a new thread is to call the constructor of the class Thread which takes a single argument of type Runnable. Like this:

Thread worker = new Thread(new Runnable() {
    public void run() {
        click.clicker();
    }
});

This returns relatively quickly and leaves the Click#clicker() method running on another thread. Your main thread is now free to execute the other statements and even call click.toggle() after a while.

As JB Nizet pointed out, there are some other problems with your code. For example, Swingerinos shouldn't extend Click, but have an instance variable of type Click ( http://en.wikipedia.org/wiki/Composition_over_inheritance ) (as JB Nizet pointed out). Also, you shouldn't need to implement WindowListener to just call System.exit() when the window closes if you already call frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); . To get all kinds of feedback (not limited to but including this kind of issues, style and design) on working code 2 I highly recommend the StackExchange website codereview.stackexchange.com

1: I by no means consider myself even remotely an expert on threading, so I won't go into it. If you want to know more about it, google it - there's lots of texts on multithreading - or ask another question - if you have a specific problem.
2: this is important: broken code is off-topic on Code Review.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM