简体   繁体   中英

JFrame not running properly inside a thread

I am trying to run a simple game where there is a server and a client talking to each other to do updates, at the moment I am not doing much between the server and the client just sending some meaningless stuff. My problem is that my 'clientframe' which extends JFrame , is not displaying properly when I try to make a new clientframe inside the run method of my 'slave' (the client) which is a thread. My clientframe works fine when it is run with its own main method but for some reason is draws a black screen with a small white rectangle in the top corner when I try to make a new clientframe inside the run method of the slave class. I realise this is not enough code to run it, and I have spent hours trying to debug it but I am stuck, thank you!

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);
}


}

You can't do what you're trying to do like this.

Any GUI operation must occur on the GUI (main) thread, and can't happen on a background thread. You should use SwingWorker , which has a means of running background operations on a background thread, and then invoking a done() method at the end that runs on the GUI thread to deal with GUI updates based on the result of the background computation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM