Столкнулся с небольшой аномалией. Имеется клиент серверное приложение для игры в крестики-нолики. 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);
}
}
}
}
}
Трудность заключается в том, что 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(...)
не помогло. Любые комментарии приветствуются.
И да, игра по-своему увлекательная.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Всем привет! Выполняя одно задание, столкнулся с тем, что неправильно сортируются датыПробовал начать использовать тип Calendar, но также ничего...
Есть веб-приложение, крутящееся на JVM
Есть ли в Java для андроида что то похожее на file_get_contents() как в PHPДело в том что я хочу взять код с html страницы применить специальную кодировку...
Есть слушатель в главном потоке, он должен ждать ответа из другого потокаВот пример: