java 拖动鼠标时在JPanel上画线
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10210437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Draw the line on the JPanel when dragging the mouse
提问by TU_HEO DAKAI
I want to draw 2 (or more ) lines on JPanel
when the mouse drags. 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);
, the result is ugly, like the pic below :
我想JPanel
在鼠标拖动时绘制 2(或更多)条线。当我super.paintComponent(g)
在我的代码中使用时,我无法在面板上绘制 2 行,但是当我不使用时super.paintComponent(g);
,结果很难看,如下图所示:
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);
}
});
}
}
回答by Andrew Thompson
..draw 2 lines
..画2条线
That seems like the crux of the matter in this question.
这似乎是这个问题的症结所在。
Keep a collection of lines in an expandable list (e.g. ArrayList
) when clicking/dragging, add a new line to the list and call repaint()
. In paintComponent(Graphics)
, iterate the collection and draw each line.
ArrayList
在单击/拖动时将一组行保留在可扩展列表中(例如),向列表中添加一个新行并调用repaint()
. 在 中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. 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.
每当 GUI 需要重绘时都会调用paint()
和方法paintComponent()
。它们可能会在另一个窗口出现在应用程序前面之后被调用,然后它会被带回到前面。另一个时间是从最小化恢复后。
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'.
- Draw each line to a
BufferedImage
and put the image in (anImageIcon
in) aJLabel
. 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 theArrayList
, 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.
- 存储线的位置并在询问时重新绘制所有线(如上所述)。这可以用于大多数目的。即使有数百行,GUI 也会在“眨眼之间”重新绘制它们。
- 将每条线绘制到 a
BufferedImage
并将图像放入 (anImageIcon
in) a 中JLabel
。如果绘图区域的大小是固定的并且没有任何内容被删除,这种方法很有效,并且可以容纳数百万条线、弧、半透明区域、较小的图像、文本......使用图像作为渲染表面,您将不再需要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
。
回答by jellyfication
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();
}