java - 使用套接字将 JFrame 绘图从客户端发送到服务器
问题描述
我正在尝试将我的 java 文件发送到其中我有一个带有按钮的 JFrame 绘图,该按钮将背景颜色从客户端更改为服务器。服务器收到该绘图并打开它,但是当我单击按钮时没有任何变化。我究竟做错了什么?同样由于某种原因,该应用程序有时无法运行。
带图的代码
package Drawings;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.*;
public class DrawingTwo extends JFrame {
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 300;
public Color tvColor;
public Color smileColor;
public int h;
public int h2;
public int h3;
public int h4;
public int h5;
public int h6;
public String l;
public DrawComponent c;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new DrawingTwo();
}
});
}
public DrawingTwo() {
super();
setOneChanell();
Container container = getContentPane();
container.setBackground(new Color(242, 212, 252));
container.setLayout(new BorderLayout(20, 20));
container.setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
ButtonListener listener = new ButtonListener();
JLabel lb = new JLabel(l);
lb.setText(l);
container.add(lb);
JButton j2 = new JButton("2");
j2.addActionListener(listener);
container.add(j2, BorderLayout.NORTH);
c = new DrawComponent();
container.add(c, BorderLayout.CENTER);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public void setOneChanell() {
this.tvColor = new Color(255, 153, 153);
this.smileColor = new Color(255, 247, 10);
this.h = 110;
this.h2 = 55;
this.h3 = 60;
this.h4 = 60;
this.h5 = 0;
this.h6 = -180;
this.l = "Канал для веселых";
}
public void setTwoChanell() {
this.tvColor = new Color(172, 194, 157);
this.smileColor = new Color(0, 161, 219);
this.h = 115;
this.h2 = 87;
this.h3 = 50;
this.h4 = 40;
this.h5 = 0;
this.h6 = +180;
this.l = "Канал для грустных";
}
public class DrawComponent extends JComponent {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(37, 26, 210, 130);
g.setColor(tvColor);
g.fillRect(42, 30, 200, 120);
g.setColor(Color.darkGray);
g.fillRect(135, 156, 15, 20);
g.setColor(Color.darkGray);
g.fillRect(83, 170, 120, 13);
g.setColor(smileColor);
g.fillOval(100, 45, 80, 80);
g.setColor(Color.BLACK);
g.drawArc(120, 70, 10, 10, 0, 360);
g.drawArc(150, 70, 10, 10, 0, 360);
g.drawString(l, 83, 200);
g.setColor(Color.BLACK);
g.drawArc(h, h2, h3, h4, h5, h6);
}
}
public class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
if (button.getText().equals("2")) {
setTwoChanell();
button.setText("1");
} else {
setOneChanell();
button.setText("2");
}
c.repaint();
}
}
}
这是客户端文件
package ClientToServer;
import java.io.*;
import java.net.Socket;
import Drawings.DrawingTwo;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 12345);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(new DrawingTwo());
objectOutputStream.flush();
objectOutputStream.close();
}
}
这是服务器文件
package ClientToServer;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import Drawings.DrawingTwo;
import javax.swing.*;
public class Server {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(12345);
Socket client = serverSocket.accept();
ObjectInputStream inputStream = new ObjectInputStream(client.getInputStream());
DrawingTwo object = (DrawingTwo) inputStream.readObject();
object.setVisible(true);
object.setTitle("Server");
object.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.close();
inputStream.close();
serverSocket.close();
}
}
解决方案
我建议您多阅读有关套接字通信的内容。如果你有一个服务器套接字,它应该一直运行。在您的代码中,您在收到来自客户端的数据后立即关闭您的套接字连接。
另一件事是;您只使用一种类型限制了您的交流:DrawingTwo() 类。在您的服务器端,您无法接收任何其他数据。
让我们逐步看一下您的代码。
您必须为通信目的定义一个新对象
import java.io.Serializable;
public class CommunicationObject implements Serializable{
private DrawingTwo mDrawingTwo;
private boolean mSmileyFace = true;
private boolean mIsInitialConnection = true;
public DrawingTwo getmDrawingTwo() {
return mDrawingTwo;
}
public void setmDrawingTwo(DrawingTwo mDrawingTwo) {
this.mDrawingTwo = mDrawingTwo;
}
public boolean ismSmileyFace() {
return mSmileyFace;
}
public void setmSmileyFace(boolean mSmileyFace) {
this.mSmileyFace = mSmileyFace;
}
public boolean ismIsInitialConnection() {
return mIsInitialConnection;
}
public void setmIsInitialConnection(boolean mIsInitialConnection) {
this.mIsInitialConnection = mIsInitialConnection;
}
}
您在这里有 3 个字段。
- 绘图二;是你的实际布局
- 布尔笑脸;指示您的按钮的情况
- 布尔 IsInitialConnection; 决定是否初始化,以便您的服务器初始化布局或更改笑脸
您的服务器必须一直监听
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
public class Server {
static boolean isRunning = true;
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(12345);
Socket client = null;
ObjectInputStream inputStream = null;
InputStream is = null;
DrawingTwo drawingTwo = null;
CommunicationObject communicationObject = null;
while (isRunning) {
client = serverSocket.accept();
inputStream = new ObjectInputStream(client.getInputStream());
is = client.getInputStream();
communicationObject = (CommunicationObject) inputStream.readObject();
if (communicationObject.ismIsInitialConnection()) {
drawingTwo = (DrawingTwo) communicationObject.getmDrawingTwo();
drawingTwo.setVisible(true);
drawingTwo.setTitle("Server");
drawingTwo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} else {
if (communicationObject.ismSmileyFace()) {
drawingTwo.setOneChanell();
} else {
drawingTwo.setTwoChanell();
}
drawingTwo.c.repaint();
}
}
client.close();
inputStream.close();
serverSocket.close();
}
}
请注意isRunning现在总是正确的。您必须处理异常和其他情况才能停止或重新启动它。
在您的 DrawingTwo 类中为您的 JButton 创建一个吸气剂
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeListener;
public class DrawingTwo extends JFrame{
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 300;
public Color tvColor;
public Color smileColor;
public int h;
public int h2;
public int h3;
public int h4;
public int h5;
public int h6;
public String l;
public DrawComponent c;
private JButton j2;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new DrawingTwo();
}
});
}
public DrawingTwo() {
super();
setOneChanell();
Container container = getContentPane();
container.setBackground(new Color(242, 212, 252));
container.setLayout(new BorderLayout(20, 20));
container.setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
ButtonListener listener = new ButtonListener();
JLabel lb = new JLabel(l);
lb.setText(l);
container.add(lb);
j2 = new JButton("2");
j2.addActionListener(listener);
container.add(j2, BorderLayout.NORTH);
c = new DrawComponent();
container.add(c, BorderLayout.CENTER);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public void setOneChanell() {
this.tvColor = new Color(255, 153, 153);
this.smileColor = new Color(255, 247, 10);
this.h = 110;
this.h2 = 55;
this.h3 = 60;
this.h4 = 60;
this.h5 = 0;
this.h6 = -180;
this.l = "1";
}
public void setTwoChanell() {
this.tvColor = new Color(172, 194, 157);
this.smileColor = new Color(0, 161, 219);
this.h = 115;
this.h2 = 87;
this.h3 = 50;
this.h4 = 40;
this.h5 = 0;
this.h6 = +180;
this.l = "2";
}
public JButton getJButton() {
return j2;
}
public class DrawComponent extends JComponent {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(37, 26, 210, 130);
g.setColor(tvColor);
g.fillRect(42, 30, 200, 120);
g.setColor(Color.darkGray);
g.fillRect(135, 156, 15, 20);
g.setColor(Color.darkGray);
g.fillRect(83, 170, 120, 13);
g.setColor(smileColor);
g.fillOval(100, 45, 80, 80);
g.setColor(Color.BLACK);
g.drawArc(120, 70, 10, 10, 0, 360);
g.drawArc(150, 70, 10, 10, 0, 360);
g.drawString(l, 83, 200);
g.setColor(Color.BLACK);
g.drawArc(h, h2, h3, h4, h5, h6);
}
}
public class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
if (button.getText().equals("2")) {
setTwoChanell();
button.setText("1");
} else {
setOneChanell();
button.setText("2");
}
c.repaint();
}
}
}
请记住,您的按钮有 2 个功能
- 更改您已经处理过的客户端上的布局
- 将信号发送到您的服务器,以便它也可以更改它
最后是客户端类。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
public class Client {
static OutputStream outputStream;
static ObjectOutputStream objectOutputStream;
static Socket socket;
public static void main(String[] args) throws UnknownHostException, IOException {
DrawingTwo drawingTwo = new DrawingTwo();
CommunicationObject communicationObject = new CommunicationObject();
communicationObject.setmDrawingTwo(drawingTwo);
communicationObject.setmIsInitialConnection(true);
write(communicationObject);
JButton button = drawingTwo.getJButton();
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
try {
if (button.getText().equals("2")) {
communicationObject.setmIsInitialConnection(false);
communicationObject.setmSmileyFace(false);
write(communicationObject);
} else {
communicationObject.setmIsInitialConnection(false);
communicationObject.setmSmileyFace(true);
write(communicationObject);
}
} catch (Exception e) {
// TODO: handle exception
}
}
});
}
public static void write(CommunicationObject comObject) throws IOException
{
socket = new Socket("localhost", 12345);
outputStream = socket.getOutputStream();
objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(comObject);
objectOutputStream.flush();
objectOutputStream.close();
}
}
您在此处创建一个 CommunicationObject 并将您的 DrawingTwo 类分配给它。
看一下从DrawingTwo中将JButton提取到Client类中的位置,以便将 ActionListener 绑定到它。通过这个动作监听器,您现在可以与您的服务器进行通信。
注意 由于客户端和服务器都可以访问 DrawingTwo,因此您不需要通过套接字发送整个类。只需向服务器发送一条消息,它应该自己创建一个实例。
推荐阅读
- kubernetes-helm - 如何从 Kubernetes 集群中获取图表?不是来自存储库
- swift - WATCH OS:如何寻找 WKInterfaceInlineMovie
- excel - 为什么缺少对象变量或 With-block 变量?
- android - 尝试旋转布局图像时离开屏幕
- php - 警告:require_once(./mailer/class.phpmailer.php):打开流失败:
- python - 我无法加载我的模型,因为我无法放置 PosixPath
- python - Django:计算迁移中更改的对象数量
- java - 错误:无法加载资源,因为应用传输安全策略需要使用安全连接
- binutils - “objcopy -O ...”中Endianess的含义?二进制数据会被破坏吗?
- anaconda - 如何在 conda 上安装 torchtext 0.4.0