Java. Swing. Странное не отображение GUI

223
27 ноября 2021, 11:10

Столкнулся с небольшой аномалией. Имеется клиент серверное приложение для игры в крестики-нолики. GUI сделано на Swing. Проблема состоит в отображении GUI сервера. Но странное поведение заключается в том что при создании экземпляра класса сервера с простенького класса который только и умеет что его и создавать, проблем с отображением нет. Но при создании точно таково же экземпляра но уже с чуть более сложного класса, то кроме формы ничего нет.

Прилагаю:

*Простой класс для создания сервера:

public class TestServ {
public static void main (String[] args) {
    Server server = new Server(9966);
}

} *Создание сервера с кнопки:

public class NetSetting extends JFrame {
public NetSetting(){
    setTitle("Net Setting");
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setBounds(300, 100, 300, 430);
    JButton bStartServer = new JButton("Создать Игру");
    JButton bConectToServer = new JButton("Подключиться к Игре");
    setLayout(null);
    add(bStartServer);
    add(bConectToServer);
    bConectToServer.setBounds( 50, 240,200, 80);
    bStartServer.setBounds( 50, 80,200, 80);
    setVisible(true);
    setResizable(false);
    bStartServer.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
               setVisible(false);
               Server server = new Server(9966);
        }
    });
    bConectToServer.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            IpSetting ipSetting = new IpSetting();
            setVisible(false);
        }
    });
 }
}

*Код Сервера:

 package com.company.project.net;
import javax.swing.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class Server {
    private final int serverPort;
    private ServerSocket serverSocket;

    public Server(int port) {
        serverPort = port;
        Socket socket = null;
        try {
            serverSocket = new ServerSocket(serverPort);
            System.out.println(InetAddress.getLocalHost());
            System.out.println("Сервер создан. Ждем кому надрать задницу...");
            while(true) {
                socket = serverSocket.accept();
                System.out.println("Бедолага подключился.");
                Runnable threadData = new ClientHandler(socket);
                new Thread(threadData).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                serverSocket.close();
                System.out.println("serverSocket.Server closed.");
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }}

*Код ClientHandler:

package com.company.project.net;
import javax.swing.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class ClientHandler extends JFrame implements Runnable {
    private Socket socket;
    private DataOutputStream out;
    private DataInputStream in;
    JBigMapNetServ jBigMapNetServ;
    public int clientX;
    public int clientY;

    public ClientHandler(Socket socket) {
        setBounds(300, 100, 644, 667);
        setTitle("XO Pro Server");
        setResizable(false);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        try {
            this.socket = socket;
            out = new DataOutputStream(socket.getOutputStream());
            in = new DataInputStream(socket.getInputStream());
            jBigMapNetServ = new JBigMapNetServ(in, out);
            add(jBigMapNetServ);
            setVisible(true);
        } catch (IOException e) {
            System.out.println(e.fillInStackTrace());
        }
    }
    @Override
    public void run() {

        while (true) {
            try {
                clientX = in.readInt();
                clientY = in.readInt();
                jBigMapNetServ.turnClient(clientX, clientY);

            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("Опонент тыкнул по координатам: " + clientX + " " + clientY);
        }
    }



}

Код панели:

 package com.company.project.net;
import javax.swing.*;
import java.awt.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
public class JBigMapNetServ extends JPanel {
    private static final int SIZE = 3;
    private static final int DOTS_TO_WIN = 3;
    private static final char DOT_EMPTY = '•';
    private static final char DOT_X = 'X';
    private static final char DOT_O = 'O';
    private int width;
    private int height;
    private int bCellWidth;
    private int bCellHeight;
    private int sCellWidth;
    private int sCellHeight;
    private int clBX;
    private int clBY;
    private int clSX;
    private int clSY;
    private int x;
    private int y;
    private int cX;
    private int cY;
    private JSmallMap[][] smallMaps;
    DataInputStream in;
    DataOutputStream out;
    private boolean enabled = true;
    public JBigMapNetServ(DataInputStream in, DataOutputStream out) throws IOException {
        this.in = in;
        this.out = out;
        initMap();
        smallMaps = new JSmallMap[3][3];
        setLayout(new GridLayout(3, 3));
        for (int i = 0; i < smallMaps.length; i ++){
            for (int j = 0; j < smallMaps.length; j ++){
                smallMaps[i][j] = new JSmallMap(in, out);
                add(smallMaps[i][j]);
            }
        }
        setVisible(true);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
               // if (getEnabled()) {
                    width = getWidth();
                    height = getHeight();
                    bCellWidth = width / SIZE;
                    bCellHeight = height / SIZE;
                    sCellWidth = bCellWidth / SIZE;
                    sCellHeight = bCellHeight / SIZE;
                    x = e.getX();
                    y = e.getY();
                    clBX = x / bCellWidth;
                    clBY = y / bCellHeight;
                    clSX = (x / sCellWidth) % SIZE;
                    clSY = (y / sCellHeight) % SIZE;
                    System.out.println("Mouse Position: " + x + " " + y + " | " + clBX + " " + clBY + " | " + clSX + ' ' + clSY);
                    if (!smallMaps[clBY][clBX].getMapFull()) {
                        if (smallMaps[clBY][clBX].getАvailable()) {
                            if (smallMaps[clBY][clBX].mapValue[clSX][clSY] == DOT_EMPTY) {
                                playerTurn(DOT_X);
                                for (int i = 0; i < SIZE; i++) {
                                    for (int j = 0; j < SIZE; j++) {
                                        smallMaps[i][j].setАvailable(false);
                                    }
                                }
                                repaint();
                                try {
                                    out.writeInt(x);
                                    out.flush();
                                    out.writeInt(y);
                                    out.flush();
                                   // setEnabled(false);
                                } catch (IOException ex) {
                                    ex.printStackTrace();
                                }
                            }
                        }
                    }
                }
            //}
            //   cX = in.readInt();
            //   cY = in.readInt();
        });

    }
    public boolean getEnabled(){
        return enabled;
    }
    public void setEnabled(boolean status){
        enabled = status;
    }
    public void turnClient(int x, int y){
        cX = x;
        cY = y;
        width = getWidth();
        height = getHeight();
        bCellWidth = width / SIZE;
        bCellHeight = height / SIZE;
        sCellWidth = bCellWidth / SIZE;
        sCellHeight = bCellHeight / SIZE;
        clBX = cX / bCellWidth;
        clBY = cY / bCellHeight;
        clSX = (cX / sCellWidth) % SIZE;
        clSY = (cY / sCellHeight) % SIZE;
        playerTurn(DOT_O);
        repaint();
        //setEnabled(true);
    }
    private void playerTurn(char DOT_PLAYER) {
        smallMaps[clBY][clBX].mapValue[clSX][clSY] = DOT_PLAYER;
        if (smallMaps[clSY][clSX].getMapFull()) {
            for (int i = 0; i < SIZE; i++) {
                for (int j = 0; j < SIZE; j++) {
                    smallMaps[i][j].setАvailable(true);
                }
            }
        }
        else {
            for (int i = 0; i < SIZE; i++) {
                for (int j = 0; j < SIZE; j++) {
                    if (i == clSY & j == clSX)
                        smallMaps[i][j].setАvailable(true);
                    else smallMaps[i][j].setАvailable(false);
                }
            }
        }


    }

    private void initMap() {
        char[][] mapValue = new char[SIZE][SIZE];
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                mapValue[i][j] = DOT_EMPTY;
            }
        }
    }
}

*Класс маленькой панели

package com.company.project.net;
import javax.swing.*;
import java.awt.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
public class JSmallMap extends JPanel {
    private static final int SIZE = 3;
    private static final int DOTS_TO_WIN = 3;
    private static final char DOT_EMPTY = '•';
    private static final char DOT_X = 'X';
    private static final char DOT_O = 'O';
    private boolean isАvailable = true;
    private boolean isMapFull = false;
    DataInputStream in;
    DataOutputStream out;
    char[][] mapValue;
    JSmallMap(DataInputStream in, DataOutputStream out) {
        this.in = in;
        this.out = out;
        initMap();
    }
    private void initMap() {
        mapValue = new char[SIZE][SIZE];
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                mapValue[i][j] = DOT_EMPTY;
            }
        }
    }
    boolean getАvailable(){
        return isАvailable;
    }
    public boolean isMapFull() {
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (mapValue[i][j] == DOT_EMPTY) return false;
            }
        }
        return true;
    }
    boolean getMapFull(){
        if (checkWin(DOT_O)){
            isMapFull = true;
        }
        if (checkWin(DOT_X)){
            isMapFull = true;
        }
        if (isMapFull){
            return true;}
        else
            return false;
    }
    void setАvailable(boolean available){
        isАvailable = available;
    }
    private boolean checkWin(char symb) {
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (checkLine(i, j, 1, 0, symb)) return true;
                if (checkLine(i, j, 0, 1, symb)) return true;
                if (checkLine(i, j, 1, 1, symb)) return true;
                if (checkLine(i, j, 1, -1, symb)) return true;
            }
        }
        return false;
    }
    private boolean checkLine(int x0, int y0, int vx, int vy, char symb) {
        if (x0 + DOTS_TO_WIN * vx > SIZE || y0 + DOTS_TO_WIN * vy > SIZE || y0 + DOTS_TO_WIN * vy < -1) return false;
        for (int i = 0; i < DOTS_TO_WIN; i++) {
            if (mapValue[y0 + i * vy][x0 + i * vx] != symb) return false;
        }
        return true;
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        int width = getWidth();
        int height = getHeight();
        int cellWidth = width / SIZE;
        int cellHeight = height / SIZE;
        if (isMapFull()) isMapFull = true;
        if (checkWin(DOT_O)){
            isMapFull = true;
            g.setColor(Color.BLUE);
            g.fillOval(0, 0, width, height);
        }
        if (checkWin(DOT_X)){
            isMapFull = true;
            g.setColor(Color.RED);
            g.fillOval(0, 0, width, height);
        }
        if (isАvailable & !isMapFull)
            setBackground(Color.WHITE);
        else
            setBackground(Color.GRAY);
        g.setColor(Color.black);
        g.drawRect(0, 0, width, height);
        g.drawRect(1, 1, width - 1, height - 1);
        g.setColor(Color.black);
        for (int i = 0; i <= SIZE; i++) {
            g.drawLine(0, i * cellHeight, width, i * cellHeight);
            g.drawLine(i * cellWidth, 0, i * cellWidth, height);
        }
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (mapValue[i][j] == DOT_X) {
                    g.setColor(Color.RED);
                    g.fillOval(i * cellWidth + 5, j * cellHeight + 5, cellWidth - 10, cellHeight - 10);
                }
                if (mapValue[i][j] == DOT_O) {
                    g.setColor(Color.BLUE);
                    g.fillOval(i * cellWidth + 5, j * cellHeight + 5, cellWidth - 10, cellHeight - 10);
                }
            }
        }
    }
}

Answer 1

Трудность заключается в том, что new Server(...), а конкретно строка socket = serverSocket.accept() ждёт ввода, и вешает главное окно, переводит его в режим ожидания, если так можно выразиться, и все последующие окна, соответственно, тоже зависшие. Поэтому не реагируют ни на что, поэтому не отрисовываются. В коде далее ты уже использовал решение, для запуска задач в отдельном потоке. Давай применим его и тут:

Немного модифицируем NetSetting:

        bStartServer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Thread() {
                    @Override
                    public void run() {
                        new Server(56254);
                    }
                }.start();
                dispose();
            }
        });

Теперь всё работает. Я не являюсь специалистом по Swing, поэтому теоретически грамотно решение обосновать не смогу. Знаю лишь, что Swing однопоточный, и что решение EventQueue.invokeLater(...) не помогло. Любые комментарии приветствуются.

И да, игра по-своему увлекательная.

READ ALSO
Неправильно выполняется сравнение дат JAVA

Неправильно выполняется сравнение дат JAVA

Всем привет! Выполняя одно задание, столкнулся с тем, что неправильно сортируются датыПробовал начать использовать тип Calendar, но также ничего...

197
Причина javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Причина javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Есть веб-приложение, крутящееся на JVM

204
Java Android аналог file_get_contents как в php

Java Android аналог file_get_contents как в php

Есть ли в Java для андроида что то похожее на file_get_contents()  как в PHPДело в том что я хочу взять код с   html страницы применить специальную кодировку...

204
Дождаться завершения работы второго потока

Дождаться завершения работы второго потока

Есть слушатель в главном потоке, он должен ждать ответа из другого потокаВот пример:

71