[英]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,而應具有類型為Click
( http://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.