[英]JFrame not running properly inside a thread
我正在嘗試運行一個簡單的游戲,其中有一個服務器和一個客戶端互相交談以進行更新,此刻我在服務器和客戶端之間做的工作並不多,只是發送了一些毫無意義的東西。 我的問題是,當我嘗試在作為線程的“從屬”(客戶端)的run方法中創建新的clientframe時,擴展JFrame
“ clientframe”無法正確顯示。 當我的clientframe用其自己的main方法運行時,它可以正常工作,但是由於某種原因,當我嘗試在從屬類的run方法中創建一個新的clientframe時,會在黑角的頂部繪制一個黑屏,並帶有一個白色的小矩形。 我意識到這還不夠運行它的代碼,我花了數小時嘗試對其進行調試,但是我被卡住了,謝謝!
public final class Slave extends Thread {
private final Socket socket;
private NetworkHandler game;
private DataOutputStream output;
private DataInputStream input;
private int uid;
private int totalSent;
private List<Integer> numbers = new ArrayList<Integer>() ;
private Update lastSentUpdate;
/**
* Construct a slave connection from a socket.
*
* @param socket
*/
public Slave(Socket socket) {
this.socket = socket;
}
public void run() {
try {
output = new DataOutputStream(socket.getOutputStream());
input = new DataInputStream(socket.getInputStream());
game = new NetworkHandler(NetworkHandler.Type.CLIENT);
PlayableCharacter ch = game.getGameUtill().findCharacter(uid);
ClientFrame frame = new ClientFrame(game, uid, true, ch);
while(true){
uid = input.readInt();
// now read the other players IDs
int noPlayers = input.readInt();
List<Integer> playerIds = new ArrayList<Integer>();
for(; noPlayers>0; noPlayers--){
playerIds.add(input.readInt());
}
numbers = playerIds;
}
socket.close(); // release socket ... v.important!
} catch(IOException e) {
System.err.println("I/O Error: " + e.getMessage());
e.printStackTrace(System.err);
}
}
public List<Integer> getNumbers (){
return numbers;
}
public int getUID(){
return uid;
}
}
public class ClientFrame extends JFrame implements KeyListener {
private static final double FRAMEHEIGHTMODIFIER = 600.0 / 768;
private static final double ASPECTRATIO = 2;
private GameRunner runner;
private int clientsUID;
private RenderPanel renderPanel;
private boolean isClient;
private StatPanel statPanel;
private Dimension windowSize;
public ClientFrame(GameRunner network, int UID, boolean isClient,
PlayableCharacter character) {
super("Cat and Mouse");
this.setLocation(new Point(50, 50));
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setResizable(false);
this.setVisible(true);
System.out.println("done setup");
this.setDimensions();
this.setLayout(null);
this.addKeyListener(this);
this.addPanels(character);
this.clientsUID = UID;
this.runner = network;
this.isClient = isClient;
this.setup();
}
private void setDimensions() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize == null) {
System.out.println("screenSize is null");
}
System.out.println(screenSize.getHeight());
int windowHeight = (int) (screenSize.getHeight() * FRAMEHEIGHTMODIFIER);
int windowWidth = (int) (windowHeight * ASPECTRATIO);
System.out.printf("Width: %d | Height: %d", windowWidth, windowHeight);
windowSize = new Dimension(windowWidth, windowHeight);
this.setSize(windowSize);
this.setPreferredSize(windowSize);
System.out.println("dimensions set");
}
private void addPanels(PlayableCharacter character) {
renderPanel = new RenderPanel(windowSize, this);
// Create dimensions
int panelHeight = (int) (1.0 / 2 * windowSize.getHeight());
int statPanelWidth = (int) (1.0 / 6 * windowSize.getWidth());
int invPanelWidth = (int) (1.0 / 24 * windowSize.getWidth());
Dimension statPanelDim = new Dimension(statPanelWidth, panelHeight);
Dimension invPanelDim = new Dimension(invPanelWidth, panelHeight);
// Create locations
int invLocationX = (int) (1.0 / 60 * windowSize.getWidth());
int invPanelLocationY = (int) (3.0 / 8 * windowSize.getHeight());
int statLocationX = (int) (49.0 / 60 * windowSize.getWidth());
int statPanelLocationY = (int) (7.0 / 16 * windowSize.getHeight());
InventoryPanel invPanel = new InventoryPanel(character, invPanelDim);
invPanel.setLocation(invLocationX, invPanelLocationY);
invPanel.setSize(invPanelDim);
invPanel.setPreferredSize(invPanelDim);
statPanel = new StatPanel(character);
statPanel.setLocation(statLocationX, statPanelLocationY);
statPanel.setSize(statPanelDim);
statPanel.setPreferredSize(statPanelDim);
this.add(invPanel);
this.add(statPanel);
this.add(renderPanel);
System.out.println("panel set fine");
}
// @Override
// public void redraw(){
//
// }
/**
* NOTE: may need to check when moving if moved to another room!! TODO
*/
@Override
public void keyPressed(KeyEvent key) {
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
ArrayList<GameItem> items = new ArrayList<GameItem>();
items.add(new Food(2, 30));
items.add(new Key(3));
items.add(new Food(2, 30));
PlayableCharacter character = new PlayableCharacter(1, null, " ", 3, 5,
items);
new ClientFrame(null, 0, false, character);
}
}
您無法做這樣的事情。
任何GUI操作都必須在GUI(主)線程上進行,而不能在后台線程上進行。 您應該使用SwingWorker
,它具有一種在后台線程上運行后台操作的方法,然后在運行於GUI線程上的末尾調用done()
方法,以根據后台計算的結果來處理GUI更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.