繁体   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