JFrame在线程内部无法正常运行

时间:2014-10-02 10:13:03

标签: java multithreading swing

我正在尝试运行一个简单的游戏,其中有一个服务器和一个客户端互相交谈进行更新,目前我在服务器和客户端之间没有做太多的事情只是发送一些毫无意义的东西。我的问题是,当我尝试在我的'slave'(客户端)的run方法中创建一个新的clientframe时,我的'clientframe'扩展JFrame并没有正确显示。我的clientframe在使用自己的main方法运行时工作正常,但出于某种原因,当我尝试在slave类的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);
}


}

1 个答案:

答案 0 :(得分:4)

你不能做你想做的事情。

任何GUI操作都必须在GUI(主)线程上进行,并且不能在后台线程上进行。您应该使用SwingWorker,它具有在后台线程上运行后台操作的方法,然后在GUI线程上运行的末尾调用done()方法,以根据结果处理GUI更新背景计算。