我正在创建一个Swing白板应用程序,其中有一个输入设备和一个输出设备。 使用输入设备的人可以在屏幕上作画,然后该屏幕显示在输出设备(以及输入设备)上。
绘图/绘画在输入设备(也就是客户端)上工作得很好,但是我无法将坐标正确地发送到服务器(输出设备)。
第一个问题是服务器中的BufferedReader不能立即接收数据。 即使我在输入设备上绘图,服务器也会在30秒后绘制线条。
第二个问题是服务器无法接收到所有的坐标,即使它们是由客户机发送的,因此行是不完整/中断的。
这是我在mouseDragged actionlistener中的代码。
g2.drawLine(oldX, oldY, currentX, currentY);
sendData();
public void sendData() {
// I am using a PrintWriter as the 'out'
out.println(oldX + " " + oldY + " " + currentX + " " + currentY);
}
下面是接收数据的服务器中的代码
while (true) {
if (in.readLine() != null) {
String message = in.readLine();
System.out.println(i + ": " + message);
drawOnImage(message);
i++;
}
}
文件中的完整代码如下。
客户端
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import javax.swing.JComponent;
public class DrawArea extends JComponent {
// Image in which we're going to draw
private Image image;
// Graphics2D object ==> used to draw on
private Graphics2D g2;
// Mouse coordinates
private int currentX, currentY, oldX, oldY;
Socket socket;
BufferedReader in;
PrintWriter out;
public DrawArea() throws IOException {
setDoubleBuffered(false);
socket = new Socket("localhost", 7777); // connecting to correct port.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream());
System.out.println("Connected");
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// save coord x,y when mouse is pressed
oldX = e.getX();
oldY = e.getY();
}
});
ArrayList<String> coords = new ArrayList();
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
// coord x,y when drag mouse
currentX = e.getX();
currentY = e.getY();
if (g2 != null) {
// draw line if g2 context not null
g2.drawLine(oldX, oldY, currentX, currentY);
sendData();
coords.add(oldX + "," + oldY + " " + currentX + "," + currentY);
System.out.println(coords.size());
System.out.println(oldX + "," + oldY + " " + currentX + "," + currentY);
// refresh draw area to repaint
repaint();
// store current coords x,y as olds x,y
oldX = currentX;
oldY = currentY;
}
}
});
}
public void sendData() {
out.println(oldX + " " + oldY + " " + currentX + " " + currentY);
}
@Override
protected void paintComponent(Graphics g) {
if (image == null) {
// image to draw null ==> we create
image = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) image.getGraphics();
// enable antialiasing
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// clear draw area
clear();
}
g.drawImage(image, 0, 0, null);
}
public void clear() {
g2.setPaint(Color.white);
// draw white on entire draw area to clear
g2.fillRect(0, 0, getSize().width, getSize().height);
g2.setPaint(Color.black);
repaint();
}
服务器端
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server implements Runnable {
static ServerSocket serverSocket;
static Socket socket;
BufferedReader in; // reading. receiving data.
TestDraw drawOutput; // this is the canvas on which the lines are drawn
public Server(TestDraw drawOutput) {
this.drawOutput = drawOutput;
}
@Override
public void run() {
try {
System.out.println("Running");
serverSocket = new ServerSocket(7777);
socket = serverSocket.accept();
System.out.println("A Client Connected");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
draw = false;
int i = 1;
while (true) {
if (in.readLine() != null) {
String message = in.readLine();
System.out.println(i + ": " + message);
drawOnImage(message);
i++;
}
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
void drawOnImage(String message) {
String[] splitted = message.split(" ");
int pointOneX = Integer.parseInt(splitted[0]);
int pointOneY = Integer.parseInt(splitted[1]);
int pointTwoX = Integer.parseInt(splitted[2]);
int pointTwoY = Integer.parseInt(splitted[3]);
drawOutput.g2.drawLine(pointOneX,pointOneY,pointTwoX,pointTwoY);
drawOutput.repaint();
}
}
PrintWriter
和网络套接字在内部缓冲区中累积数据。 需要“刷新”缓冲区,以确保数据尽快发送。
一种方法是在构造PrintWriter时设置“AutoFlush”属性。 这将确保在每次调用println
时刷新缓冲区。
out = new PrintWriter(socket.getOutputStream(), true);
另一种方法是在你认为需要的时候自己调用flush,例如:
out.println(oldX + " " + oldY + " " + currentX + " " + currentY);
out.flush();