Java 远程鼠标移动不平稳

Java 远程鼠标移动不平稳,java,sockets,mouseevent,awtrobot,Java,Sockets,Mouseevent,Awtrobot,我正在使用mouselistener和robot类在一台计算机上移动鼠标,并让它在另一台计算机上移动光标这是我正在进行的远程桌面项目的前身。我已经偶然发现了一个问题,那就是鼠标的抖动。我已经检查了我的代码一百次了,但我似乎无法找出哪里出了问题 下面是将鼠标移动发送到客户端的3个服务器文件 TC_ServerListener.java import java.awt.BorderLayout; import java.io.IOException; import java.net.ServerSo

我正在使用mouselistener和robot类在一台计算机上移动鼠标,并让它在另一台计算机上移动光标这是我正在进行的远程桌面项目的前身。我已经偶然发现了一个问题,那就是鼠标的抖动。我已经检查了我的代码一百次了,但我似乎无法找出哪里出了问题

下面是将鼠标移动发送到客户端的3个服务器文件

TC_ServerListener.java

import java.awt.BorderLayout;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;


public class TC_ServerListener {
    private JFrame mainTCframe = new JFrame();
    private JDesktopPane mainDesktopPane = new JDesktopPane();

    public static void main(String args[]){
        new TC_ServerListener().startServer();
    }

    public void startServer() {

        try {
            setupGUI();

            ServerSocket serverSocket = new ServerSocket(1111);
            System.out.println("Waiting for clients.");
            while (true) {
                Socket clientSocket = serverSocket.accept();
                new TC_ServerStarter(clientSocket, mainDesktopPane);
            }
        } catch (IOException ex) {
            Logger.getLogger(TC_ServerListener.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void setupGUI(){
            mainTCframe.add(mainDesktopPane,BorderLayout.CENTER);
            mainTCframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            mainTCframe.setExtendedState(mainTCframe.getExtendedState()|JFrame.MAXIMIZED_BOTH);
            mainTCframe.setVisible(true);
    }
}
TC_ServerStarter.java

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.beans.PropertyVetoException;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;


public class TC_ServerStarter extends Thread {

    int counter = 0;

    JPanel listenerPanel = new JPanel();
    JInternalFrame listenerFrame = new JInternalFrame("TestClient", true, true, true);
    Rectangle screenRect = new Rectangle();

    GraphicsEnvironment graphicsEnv;
    GraphicsDevice graphicsDev;
    Dimension dim;
    Dimension clientDim;
    Dimension serverDim;

    static DataOutputStream kbOut;
    static DataOutputStream mouseMoveOut;
    static DataOutputStream mouseClickOut;
    static DataOutputStream mouseDragOut;

    Socket clientSocket;
    JDesktopPane mainDesktopPane;

    PrintWriter writer;
    Scanner dataScanner;

    public TC_ServerStarter(Socket cs, JDesktopPane mdp) {
        clientSocket = cs;
        mainDesktopPane = mdp;

        start();
    }

    public void setupGUI() {
        listenerFrame.setLayout(new BorderLayout());
        listenerFrame.getContentPane().add(listenerPanel,BorderLayout.CENTER);
        listenerFrame.setSize(100,100);
        mainDesktopPane.add(listenerFrame);

        try {
            listenerFrame.setMaximum(true);
            } catch (PropertyVetoException ex) {
            Logger.getLogger(TC_ServerStarter.class.getName()).log(Level.SEVERE, null, ex);
        }
        listenerPanel.setFocusable(true);
        listenerFrame.setVisible(true);
    }



        @Override
        public void run() {

            try {
                setupGUI();

                String clientIP = clientSocket.getInetAddress().getHostAddress();
                System.out.println("Client connected from " + clientIP);

                writer = new PrintWriter(clientSocket.getOutputStream());
                dataScanner = new Scanner(clientSocket.getInputStream());

                int screenHeight = dataScanner.nextInt();
                int screenWidth = dataScanner.nextInt();
                System.out.println("Setting screen size: " + screenHeight + "x" + screenWidth);
                clientDim = new Dimension(screenHeight, screenWidth);

                new KvmSender(clientSocket, listenerPanel, clientDim);


            } catch (IOException ex) {
                Logger.getLogger(TC_ServerStarter.class.getName()).log(Level.SEVERE, null, ex);
              }
            }
        }
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class TC_ClientStarter extends Thread {

    private final static String SERVER_IP = "192.168.0.50";

    JPanel clientPanel = new JPanel();
    JFrame clientFrame = new JFrame();

    GraphicsEnvironment graphicsEnv;
    Rectangle screenRect;
    Dimension screenSize;

    static PrintWriter dataWriter;

    Robot tcRobot;

    Socket clientSocket;

    public void setupGUI() {

        clientFrame.add(clientPanel);
        clientFrame.setSize(200,200);
        clientFrame.setVisible(true);
        clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        clientPanel.requestFocusInWindow();
    }

    public static void main(String[] args) {
        new TC_ClientStarter().setupClient();
    }

    public void setupClient() {

        try {
            screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            screenRect = new Rectangle(screenSize.height, screenSize.width);

            clientSocket = new Socket(SERVER_IP, 1111);
            System.out.println("Connected to Commander.");

            System.out.println("Sending screen size: " + screenRect.height + "x" + screenRect.width);
            dataWriter = new PrintWriter(clientSocket.getOutputStream());
            dataWriter.println(screenRect.height);
            dataWriter.println(screenRect.width);
            dataWriter.flush();

            tcRobot = new Robot();

            setupGUI();

            new TC_ClientReceiver(clientSocket, tcRobot);


            } catch (ConnectException ece) {
            System.out.println("Failed to connect to server: " + SERVER_IP);
        } catch (IOException | AWTException eio) {
            Logger.getLogger(TC_ClientStarter.class.getName()).log(Level.SEVERE, null, eio);
        }
    }
}
KvmSender.java

import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JPanel;

class KvmSender implements KeyListener, MouseMotionListener, MouseListener {

    private Socket clientSocket;
    private JPanel listenerPanel;
    private Dimension clientDim;
    private PrintWriter clientWriter;

    public KvmSender(Socket cs, JPanel lp, Dimension cd) {
        clientSocket = cs;
        listenerPanel = lp;
        clientDim = cd;

        listenerPanel.addKeyListener(this);
        listenerPanel.addMouseListener(this);
        listenerPanel.addMouseMotionListener(this);
        try {
            clientWriter = new PrintWriter(clientSocket.getOutputStream());
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        System.out.println("Ready to send commands.");
    }

    @Override
    public void keyTyped(KeyEvent ke) {
    }

    @Override
    public void keyPressed(KeyEvent ke) {
    }

    @Override
    public void keyReleased(KeyEvent ke) {
    }

    @Override
    public void mouseDragged(MouseEvent me) {
    }

    @Override
    public void mouseMoved(MouseEvent me) {
        try {
            double scaleX = clientDim.getWidth() / listenerPanel.getWidth();
            double scaleY = clientDim.getHeight() / listenerPanel.getHeight();
            int mouseX = (int)(me.getX() * scaleX);
            int mouseY = (int)(me.getY() * scaleY);

            clientWriter.println(1);
            clientWriter.println(mouseX);
            clientWriter.println(mouseY);
            System.out.println("Sending mouse: " + mouseX + "," + mouseY);
            clientWriter.flush();

        } catch (NullPointerException ex) {
            System.out.println("Error writing mouse data to server");
        }
    }

    @Override
    public void mouseClicked(MouseEvent me) {
    }

    @Override
    public void mousePressed(MouseEvent me) {
    }

    @Override
    public void mouseReleased(MouseEvent me) {
    }

    @Override
    public void mouseEntered(MouseEvent me) {
    }

    @Override
    public void mouseExited(MouseEvent me) {
    }

}
然后是2个客户端文件

TC_ClientStarter.java

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.beans.PropertyVetoException;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;


public class TC_ServerStarter extends Thread {

    int counter = 0;

    JPanel listenerPanel = new JPanel();
    JInternalFrame listenerFrame = new JInternalFrame("TestClient", true, true, true);
    Rectangle screenRect = new Rectangle();

    GraphicsEnvironment graphicsEnv;
    GraphicsDevice graphicsDev;
    Dimension dim;
    Dimension clientDim;
    Dimension serverDim;

    static DataOutputStream kbOut;
    static DataOutputStream mouseMoveOut;
    static DataOutputStream mouseClickOut;
    static DataOutputStream mouseDragOut;

    Socket clientSocket;
    JDesktopPane mainDesktopPane;

    PrintWriter writer;
    Scanner dataScanner;

    public TC_ServerStarter(Socket cs, JDesktopPane mdp) {
        clientSocket = cs;
        mainDesktopPane = mdp;

        start();
    }

    public void setupGUI() {
        listenerFrame.setLayout(new BorderLayout());
        listenerFrame.getContentPane().add(listenerPanel,BorderLayout.CENTER);
        listenerFrame.setSize(100,100);
        mainDesktopPane.add(listenerFrame);

        try {
            listenerFrame.setMaximum(true);
            } catch (PropertyVetoException ex) {
            Logger.getLogger(TC_ServerStarter.class.getName()).log(Level.SEVERE, null, ex);
        }
        listenerPanel.setFocusable(true);
        listenerFrame.setVisible(true);
    }



        @Override
        public void run() {

            try {
                setupGUI();

                String clientIP = clientSocket.getInetAddress().getHostAddress();
                System.out.println("Client connected from " + clientIP);

                writer = new PrintWriter(clientSocket.getOutputStream());
                dataScanner = new Scanner(clientSocket.getInputStream());

                int screenHeight = dataScanner.nextInt();
                int screenWidth = dataScanner.nextInt();
                System.out.println("Setting screen size: " + screenHeight + "x" + screenWidth);
                clientDim = new Dimension(screenHeight, screenWidth);

                new KvmSender(clientSocket, listenerPanel, clientDim);


            } catch (IOException ex) {
                Logger.getLogger(TC_ServerStarter.class.getName()).log(Level.SEVERE, null, ex);
              }
            }
        }
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class TC_ClientStarter extends Thread {

    private final static String SERVER_IP = "192.168.0.50";

    JPanel clientPanel = new JPanel();
    JFrame clientFrame = new JFrame();

    GraphicsEnvironment graphicsEnv;
    Rectangle screenRect;
    Dimension screenSize;

    static PrintWriter dataWriter;

    Robot tcRobot;

    Socket clientSocket;

    public void setupGUI() {

        clientFrame.add(clientPanel);
        clientFrame.setSize(200,200);
        clientFrame.setVisible(true);
        clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        clientPanel.requestFocusInWindow();
    }

    public static void main(String[] args) {
        new TC_ClientStarter().setupClient();
    }

    public void setupClient() {

        try {
            screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            screenRect = new Rectangle(screenSize.height, screenSize.width);

            clientSocket = new Socket(SERVER_IP, 1111);
            System.out.println("Connected to Commander.");

            System.out.println("Sending screen size: " + screenRect.height + "x" + screenRect.width);
            dataWriter = new PrintWriter(clientSocket.getOutputStream());
            dataWriter.println(screenRect.height);
            dataWriter.println(screenRect.width);
            dataWriter.flush();

            tcRobot = new Robot();

            setupGUI();

            new TC_ClientReceiver(clientSocket, tcRobot);


            } catch (ConnectException ece) {
            System.out.println("Failed to connect to server: " + SERVER_IP);
        } catch (IOException | AWTException eio) {
            Logger.getLogger(TC_ClientStarter.class.getName()).log(Level.SEVERE, null, eio);
        }
    }
}
TC_ClientReceiver.java

import java.awt.Robot;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

class TC_ClientReceiver extends Thread {

    private Socket clientSocket;
    private Robot tcRobot;

    private Scanner clientScanner;

    private int mouseX, mouseY;

    public TC_ClientReceiver(Socket cs, Robot tcr) {
        clientSocket = cs;
        tcRobot = tcr;
        start();
    }

    @Override
    public void run(){

        try {
            clientScanner = new Scanner(clientSocket.getInputStream());
            System.out.println("Waiting for commands.");
            while (true) {

                int commandID = clientScanner.nextInt();
                //System.out.println("CommandID: " + commandID);
                switch (commandID) {

                    case 1:
                        System.out.println("Mouse move");
                        mouseX = clientScanner.nextInt();
                        mouseY = clientScanner.nextInt();
                        tcRobot.mouseMove(mouseX, mouseY);
                        System.out.println(mouseX + "," + mouseY);
                        break;
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(TC_ClientReceiver.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

}

我应该补充一点,我发现有人用java编写了一个remove server/client远程桌面应用程序,当我运行它时,鼠标移动是平稳的,这与我自己的代码不同。网络延迟可能是不平稳移动的根本原因。我可以想出两个理论解决方案(这里只是猜测):1。实施轻微的缓冲算法,以便随着时间的推移准确跟踪运动。缓冲区长于最慢的网络延迟。数字媒体是如何做到这一点的。2.实现一个平滑算法,该算法“填充空白”,并在更新的点之间跟踪一条平滑线。Shaving说,解决方案2可能更好。我认为java中的鼠标事件本身并不总是非常顺利的。这还不足以让它看起来很自然。令人沮丧的是,我一个接一个地为我的程序建模,而另一个程序一点也不急躁。对于捕捉鼠标然后移动鼠标,我们使用基本相同的功能,没有任何缓冲或鼠标平滑。我有一个鼠标平滑算法,我无论如何都会尝试,但它不应该需要。鼠标平滑似乎是解决方案。谢谢