简体   繁体   English

使用JPanel在java中绘图

[英]Drawing in java with JPanel

I'm making a program where you have a server and a client, and the idea is that you draw on the client jpanel, and the coordinates will then be sent to the server, which will sort of mimic the drawing. 我正在制作一个程序,你有一个服务器和一个客户端,想法是你在客户端jpanel上绘制,然后坐标将被发送到服务器,这将模仿绘图。 I've done that, but the problem is now, that my drawing mechanism is pretty bad. 我已经这样做了,但现在的问题是,我的绘图机制非常糟糕。 Right now I'm just using an oval that gets drawn over and over again on the coordinate of the mouse, which sometimes leaves spaces between the ovals if you move the mouse too fast. 现在我只是使用一个在鼠标坐标上反复绘制的椭圆,如果你移动鼠标太快,有时会在椭圆之间留下空格。

To better illustrate, here's an SS: http://gyazo.com/6ed1017e9efd6beaa4b5d56052fda260 为了更好地说明,这是一个SS: http//gyazo.com/6ed1017e9efd6beaa4b5d56052fda260

As you can see, it's only consistent when you move the mouse relatively slow, but as soon as you move it a bit fast, it leaves spaces. 正如您所看到的,只有当您将鼠标移动得相对较慢时才会保持一致,但只要您快速移动它,它就会留下空间。

How do I prevent this from happening? 我该如何防止这种情况发生?

Right now the client just sends x and y coordinates, so here's the server side code: 现在客户端只发送x和y坐标,所以这里是服务器端代码:

package com.company;

import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server extends JPanel{
    static MouseData mouseReceive;
    static Draw draw;
    static int x;
    static int y;




    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        Server server = new Server();
        JFrame frame = new JFrame("Server");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(server);
        frame.setSize(1024, 600);
        frame.setVisible(true);
        draw = new Draw(x,y);


        ServerSocket serverSock = new ServerSocket(1234);
        Socket s = serverSock.accept();
        ObjectInputStream in = new ObjectInputStream(s.getInputStream());



        while(true) {
            mouseReceive = (MouseData) in.readObject();
            draw = new Draw(mouseReceive.mouseX,mouseReceive.mouseY);
        }
    }





    public void paint(Graphics g){
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        draw.display(g);
        repaint();

    }
}

And here's my draw class: 这是我的画班:

package com.company;

import java.awt.*;

/**
 * Created by John on 21/04/2015.
 */
public class Draw {
    int xLoc;
    int yLoc;


    Draw(int x, int y){
        xLoc = x;
        yLoc = y;
    }

    public void display(Graphics g){
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.fillOval(xLoc,yLoc,7,7);
    }


}

I tried finding someone else having the same problem on this site through the search function, but I had no luck in doing so :( If I missed it however, please direct me to that topic! If anyone could help me out, I'd appreciate it a whole lot! Have a nice day :) 我试图通过搜索功能在这个网站上找到有同样问题的人,但我没有运气这样做:(如果我错过了它,请指导我这个话题!如果有人能帮助我,我会非常感激!祝你有美好的一天:)

Presuming the Client is using a MouseListener (or MouseMotionListener ): the MouseListener can only fire as fast as a certain interval. 假设客户端正在使用MouseListener(或MouseMotionListener ):MouseListener只能以特定间隔快速触发。 For example when the mouse is constantly moved your listener will receive a MouseEvent for every interval rather than every pixel. 例如,当鼠标不断移动时,监听器将为每个间隔而不是每个像素接收一个MouseEvent。 As a result, moving the mouse fast may result in drawing items that are not adjacent to each other. 结果,快速移动鼠标可能导致绘制彼此不相邻的项目。 AFAIK, you cannot increase the speed, but you can draw lines between two sequential points making them look continuous (eg by using a List of each event location and using g.drawLine on each two adjacent points in the List). AFAIK,你不能提高速度,但你可以在两个连续点之间绘制线条,使它们看起来是连续的(例如,通过使用每个事件位置的列表并在列表中的每两个相邻点上使用g.drawLine )。

Other notes: 其他说明:

  1. You should override paintComponent rather than the paint method. 您应该覆盖paintComponent而不是paint方法。
  2. I would recommend calling super.paintComponent in this method. 我建议在这个方法中调用super.paintComponent。 This will clear the component (hence your code will then only draw the last point - see (3)) 这将清除组件(因此您的代码将只绘制最后一点 - 见(3))
  3. I would recommend keeping a List of locations to use for drawing, which you can iterate over and draw each circle (or draw a line between adjacent points) 我建议保留一个用于绘图的位置列表,您可以迭代并绘制每个圆(或在相邻点之间画一条线)
  4. Do NOT call repaint within your painting methods. 不要叫你的绘画方法中重新绘制。 The idea here is that when a new item is received from the Client, add it to the List in (3) and then call repaint. 这里的想法是,当从客户端收到新项目时,将其添加到(3)中的列表,然后调用重绘。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM