簡體   English   中英

Java-Swing GUI無法加載

[英]Java - Swing GUI doesn't load

我已經嘗試學習Java幾周了,並且正在開發一個非常簡單的autoclicker。 答題器本身可以工作,但是我的問題是我的GUI無法顯示。 當我運行GUI文件本身時,GUI運行得很好,但是當我嘗試從主程序(不同文件)運行它時,它永遠不會顯示。 答題器一直都能正常工作。 我確定問題確實很簡單,我只是想念而已,但是現在已經是我第四天了,不知道它可能出什么問題了,所以決定在這里提出。

當心-代碼真的是凌亂的atm,因為我一直在盡一切可能使它工作。

這是試圖運行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); }
    }
}

這是整個GUI文件。

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) {}

}

我知道GUI文件確實很亂(有2個initialize(),一個在主程序中,一個在GUI文件中,還有許多其他內容,但是我對於現在該做什么感到很困惑。

編輯:我添加了整個主程序代碼,這也是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);
        }
    }
}

將JB Nizet的評論擴展為答案。

直接原因:

JVM調用您的代碼時,它在主線程上運行。 如您所知,它將調用main(String[]) 您發布了兩種主要方法,其中只有一種與發生問題無關: AutoClick#main(String[]) 讓我們來看一下:

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

以上兩行的第一行顯然調用了Click的構造函數,該構造函數將active變量設置為true 到現在為止還挺好。 第二行更加有趣。 它調用Click#clicker() 讓我們看一下該方法:

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

這個方法就是問題所在。 由於您尚未啟動任何其他線程,因此主線程是當時唯一的線程,也是您可以執行代碼的唯一線程。 當執行此循環時,僅當active變量設置為false時,它才結束。 只要它是正確的,它將保持循環。 這意味着Click#clicker()僅在active設置為false返回。 但是,您永遠不會在循環本身中執行此操作,這意味着您需要一個與執行循環的線程不同的線程來更改active 那么,我們有多少個線程? 1,主線程。 看到問題了嗎? 因為循環永遠不會結束,所以主線程在click.clicker()之后永遠不會到達main方法中的語句。

簡單的解決方案

您可以設置固定的迭代次數:

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

或使用for循環(推薦):

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

這消除了對active變量的需要,從而消除了對另一個線程的需要。

稍微復雜一點的解決方案

如果您確實需要active變量,則需要具有多個線程。 這被方便地稱為“多線程” 1 ,這是一個非常復雜的主題。 幸運的是,我們只需要一點它,所以它只是有點復雜。

不要像通常那樣僅調用Click#clicker()方法。 這會造成您當前的問題。 您將需要一個工作線程,該線程可以調用該方法。 創建新線程的最簡單方法是調用Thread類的構造函數,該類采用一個Runnable類型的參數。 像這樣:

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

這會相對快速地返回,並使Click#clicker()方法在另一個線程上運行。 現在,您的主線程可以自由執行其他語句,甚至可以在一段時間后調用click.toggle()

正如JB Nizet指出的那樣,您的代碼還有其他一些問題。 例如,Swingerinos不應擴展Click,而應具有類型為Clickhttp://en.wikipedia.org/wiki/Composition_over_inheritance )的實例變量(如JB Nizet所指出的)。 另外,如果您已經調用frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);則在關閉窗口時也不需要實現WindowListener來僅調用System.exit() frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 為了獲得有關工作代碼 2的各種反饋(不限於但包括此類問題,樣式和設計),我強烈建議StackExchange網站codereview.stackexchange.com

1:我絕不認為自己是線程專家,因此我不會介紹它。 如果您想了解更多有關它的信息,請在Google上搜索-關於多線程的很多文章-或提出另一個問題-如果您有特定問題。
2:這很重要:損壞的代碼不在“代碼審查”上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM