簡體   English   中英

JFrame在線程內無法正常運行

[英]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.

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