简体   繁体   English

拖动鼠标时在JPanel上画线

[英]Draw the line on the JPanel when dragging the mouse

I want to draw 2 (or more ) lines on JPanel when the mouse drags.当鼠标拖动时,我想在JPanel上绘制 2(或更多)条线。 When i use super.paintComponent(g) in my code, I couldn't draw 2 lines on the panel, however when I don't use super.paintComponent(g);当我在代码中使用super.paintComponent(g)时,我无法在面板上绘制 2 条线,但是当我不使用super.paintComponent(g); , the result is ugly, like the pic below : ,结果很难看,如下图所示:

在此处输入图片说明

I understand why the lines behaved like that.我明白为什么这些线条表现得那样。

How could I draw the lines on the panel when dragging the mouse?拖动鼠标时如何在面板上绘制线条?

BTW, the line drawn by g2d.draw(line2d) sometimes it's not the smooth line (pic below)顺便说一句, g2d.draw(line2d)绘制的线有时不是平滑的线(下图)

在此处输入图片说明

My codes so far :到目前为止我的代码:

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;


public class LineDrawing extends JPanel implements MouseMotionListener, MouseListener{
    Point point1;
    Point point2;
    Line2D line2d;

  public LineDrawing(){
       super();
       addMouseListener(this);
       addMouseMotionListener(this);
    }

 @Override
  public void paintComponent(Graphics g){

    //super.paintComponent(g);

       Graphics2D g2d = (Graphics2D) g;
       if(point1!=null && point2!=null){

          g2d.setPaint(Color.RED);
          g2d.setStroke(new BasicStroke(1.5f));
          g2d.draw(line2d);

         }
      }   


  @Override
  public void mouseDragged(MouseEvent e) {

    point2 = e.getPoint();
    line2d = new Line2D.Double(point1, point2); 
    repaint();

  }

   @Override
   public void mouseMoved(MouseEvent e) {

   }

   @Override
   public void mouseClicked(MouseEvent e) {

  }

   @Override
   public void mousePressed(MouseEvent e) {
     point1 = e.getPoint();

   }

  @Override
  public void mouseReleased(MouseEvent e) {

  }

 @Override
 public void mouseEntered(MouseEvent e) {

 }

 @Override
 public void mouseExited(MouseEvent e) {

}


public static void main(String a[]){
   EventQueue.invokeLater(new Runnable(){
        @Override
        public void run() {

         JFrame frame = new JFrame();
         LineDrawing linedraw= new LineDrawing();
         frame.add(linedraw);
         frame.setSize(500,500);
         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
         frame.setVisible(true);   

                         }
                });
   }   
}

..draw 2 lines ..画2条线

That seems like the crux of the matter in this question.这似乎是这个问题的症结所在。

Keep a collection of lines in an expandable list (eg ArrayList ) when clicking/dragging, add a new line to the list and call repaint() .在单击/拖动时将一组行保留在可扩展列表(例如ArrayList )中,向列表中添加一个新行并调用repaint() In paintComponent(Graphics) , iterate the collection and draw each line.paintComponent(Graphics) ,迭代集合并绘制每条线。

BTW - I am guessing you have not minimized and restored your window while testing this.顺便说一句 - 我猜你在测试时没有最小化和恢复你的窗口。 Your lines (beautiful or ugly) would disappear!你的线条(漂亮的或丑陋的)会消失!


..they disappeared. ..他们消失了。 What's the reason?什么原因?

The methods paint() and paintComponent() are called whenever the GUI needs to redraw.每当 GUI 需要重绘时,就会调用方法paint()paintComponent() They might be invoked after another window appears in front of the app., then it is brought back to the front.它们可能会在另一个窗口出现在应用程序前面之后被调用,然后它会被带回到前面。 Another time is after being restored from minimized.另一个时间是从最小化恢复后。

The options to retain the lines include:保留行的选项包括:

  • Store the locations of the line(s) and redraw all of them whenever asked (as described above).存储线的位置并在询问时重新绘制所有线(如上所述)。 This can work for most purposes.这可以用于大多数目的。 Even if there are hundreds of lines, the GUI will redraw them in 'the blink of an eye'.即使有数百行,GUI 也会在“眨眼之间”重新绘制它们。
  • Draw each line to a BufferedImage and put the image in (an ImageIcon in) a JLabel .将每一行绘制到BufferedImage并将图像放入( ImageIcon in) JLabel This approach works well if the drawing area is of a fixed size & nothing is ever removed, and can accommodate ..millions of lines, arcs, semi-transparent areas, smaller images, text.. Using an image as a rendering surface, you would no longer need the ArrayList , since all you do is add a new line to the image, and repaint the label to see the new line and all previous lines.如果绘图区域的大小是固定的并且没有任何内容被删除,这种方法很有效,并且可以容纳..数百万条线、弧、半透明区域、较小的图像、文本..使用图像作为渲染表面,您将不再需要ArrayList ,因为您所做的只是向图像添加一个新行,然后重新绘制标签以查看新行和所有以前的行。

..the line is not the straight line. ..线不是直线。

That is because of the 'rendering hints' used when drawing the line.这是因为绘制线条时使用了“渲染提示”。 A screen made of aligned rows of pixels can only make vertical or horizontal lines perfectly.由对齐的像素行组成的屏幕只能完美地制作垂直或水平线。 To give the 'illusion' of a straight & continuous line at any other angle, requires a technique known as dithering .要在任何其他角度产生直线和连续线的“错觉”,需要一种称为抖动的技术。 Read the opening sections of Graphics2D for more explanation and description of the RenderingHints .阅读Graphics2D的开头部分,以获取有关RenderingHints更多解释和说明。

I don't know I get your question, but if you want to draw a continuous line.我不知道我明白你的问题,但如果你想画一条连续的线。 When dragging you have to update your last point possition.拖动时,您必须更新最后一个点的位置。

@Override
  public void mouseDragged(MouseEvent e) {
    point2 = e.getPoint();
    line2d = new Line2D.Double(point1, point2); 
    point1 = point2;  // add this line
    repaint();
  }

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

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