繁体   English   中英

Java Paint未在Swing中绘制

[英]Java paint not drawing in Swing

我正在尝试制作绘画程序,但是在拖动鼠标时无法绘制线条。 看来涂料一直在刷新,因此只绘制了鼠标的当前位置。 我对此有些陌生,因此在拖动鼠标时如何将所有行显示在JPanel上? 谢谢,这是我所拥有的:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JPanel;

public class DrawingPanel extends JPanel{

    Point start;
    Point end;
    static Color c = Color.black;
    DrawingPanel(){
        addMouseMotionListener(new ml());
        addMouseListener(new ml());
    }
    public class ml implements MouseMotionListener, MouseListener{
        public void mouseMoved(MouseEvent ev){}
        public void mousePressed(MouseEvent e){
            end = e.getPoint();
        }
        public void mouseDragged(MouseEvent e){
            start = end;
            end=e.getPoint();
            repaint();
        }
        public void mouseReleased(MouseEvent e){
            start=null;
            end=null;
        }
        public void mouseClicked(MouseEvent e){}
        public void mouseEntered(MouseEvent e){}
        public void mouseExited(MouseEvent e){}
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(c);
        if(start!=null){
            Graphics2D g2 = (Graphics2D) g;
            g2.setStroke(new BasicStroke(5));
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.drawLine(start.x, start.y, end.x, end.y);


        }

    }
}

看来油漆一直保持清爽

是的,这就是绘画的工作原理,请查看AWT和Swing中的绘画以获取更多详细信息

作为一个可能的解决方案,您可以添加的每个新Point一个List ,简单地画中的每个点之间的线paintComponent通过循环方法List

您也可以创建一个Shape并在其中绘制线条,并在paintComponent方法中绘制该形状。

查看2D图形以了解更多详细信息

绘制单线示例

画线

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawLine {

    public static void main(String[] args) {
        new DrawLine();
    }

    public DrawLine() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Point startPoint, endPoint;

        private List<Point[]> lines;

        public TestPane() {

            lines = new ArrayList<>(25);

            MouseAdapter ma = new MouseAdapter() {

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

                @Override
                public void mouseReleased(MouseEvent e) {
                    endPoint = e.getPoint();
                    Point[] points = new Point[]{startPoint, endPoint};
                    lines.add(points);
                    startPoint = null;
                    endPoint = null;
                    repaint();
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    endPoint = e.getPoint();
                    repaint();
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.BLACK);
            for (Point[] p : lines) {
                g2d.drawLine(p[0].x, p[0].y, p[1].x, p[1].y);
            }
            if (startPoint != null && endPoint != null) {
                g2d.setColor(Color.RED);
                g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
            }
            g2d.dispose();
        }

    }

}

绘制多条连接线的示例

连接线

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawLine {

    public static void main(String[] args) {
        new DrawLine();
    }

    public DrawLine() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Point> points;
        private Point mousePoint;

        public TestPane() {

            points = new ArrayList<>(25);

            MouseAdapter ma = new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    points.add(e.getPoint());
                    repaint();
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                    mousePoint = e.getPoint();
                    repaint();
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.BLACK);
            Point startPoint = null;
            for (Point p : points) {
                if (startPoint == null) {
                    startPoint = p;
                } else {
                    g2d.drawLine(startPoint.x, startPoint.y, p.x, p.y);
                    startPoint = p;
                }
            }
            if (startPoint != null) {
                g2d.setColor(Color.RED);
                g2d.drawLine(startPoint.x, startPoint.y, mousePoint.x, mousePoint.y);
            }
            g2d.dispose();
        }

    }

}

您几乎做对了所有事情。 您的程序仅显示当前鼠标位置的原因是因为您没有在mousePressed上保存起始位置。 尝试更换:

public void mousePressed(MouseEvent e){
    end = e.getPoint();
}

与:

public void mousePressed(MouseEvent e){
    start = e.getPoint();
}

并且:

public void mouseDragged(MouseEvent e){
    start = end;
    end=e.getPoint();
    repaint();
}

与:

public void mouseDragged(MouseEvent e){
    end = e.getPoint();
    repaint();
}

这将使它能够画一条线。 如果您需要更多行,则只需将每个完成的行添加到mouseReleased中的列表中即可。 尝试将其添加到您的DrawingPanel类中:

private ArrayList<Point> points = new ArrayList<Point>();

也可以替换为:

public void mouseReleased(MouseEvent e){
    start = null;
    end   = null;
}

与:

public void mouseReleased(MouseEvent e){
    points.add(start);
    points.add(end);
    start = null;
    end   = null;
}

并替换为:

public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.setColor(c);
    if(start!=null){
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(5));
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.drawLine(start.x, start.y, end.x, end.y);
    }
}

与:

public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(c);
    g2.setStroke(new BasicStroke(5));
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    //Draw all previous lines
    for (int i = 0; i < points.size(); i+=2) {
        g2.drawLine(points.get(i).x, points.get(i).y, points.get(i+1).x, points.get(i+1).y);
    }

    //Draw the current line if there is one
    if(start != null && end != null){
        g2.drawLine(start.x, start.y, end.x, end.y);
    }
}

现在我们将每个完成的行保存在列表中,每个偶数索引是一行的开始,每个奇数是一行的结束。 如果您希望能够绘制出与您移动鼠标完全相同的“曲线”,则必须稍稍更改此代码,但是至少这应该给您一些帮助。 如果您需要进一步的帮助,只需提出其他问题。

有多种方法可以解决您的问题。 @MattiasF和@MadProgrammer是正确的:Swing在做它应该做的事情。 您的paintComponent方法应该重新绘制整个场景,而不是添加到前一个场景。

到目前为止,建议的解决方案会导致应用程序执行矢量图形操作:您正在记住原始的绘制操作,并且在每个绘制上都执行每个绘制操作(Java2D对其进行了一些优化,因为它不会真正重绘区域屏幕上当前不可见的区域,但是要弄清楚哪些区域是可见的,哪些区域是不可见的,也需要花费时间。

优点是,如果需要更大或更小的图像,则可以完美地缩放绘图操作。 缺点是,一旦存储了许多绘图操作,它的速度可能会变慢,并且您不能(轻松)进行位图操作。

另一种方法是位图方法。 您可以在内存中建立绘图的位图,然后在paintComponent方法中将位图绘制到屏幕上。

优点是通常更快。 它还允许位图操作,并且针对此模型进行编程通常也更容易,因为您可以在需要时进行绘制,而不是在内存中构建一系列绘制操作。 缺点是它使用更多的内存(直到您执行许多绘图操作为止),并且您无法再完美地缩放图像。

为了使您的示例可以使用保存在内存中的位图,请将字段imageimageGraphics添加到您的类中,并使用以下代码替换鼠标侦听器ml以及paintComponent方法:

private BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
private Graphics2D imageGraphics = image.createGraphics();

public class ml extends MouseAdapter implements MouseMotionListener, MouseListener {

    public void mousePressed(MouseEvent e) {
        end = e.getPoint();
    }

    public void mouseDragged(MouseEvent e) {
        start = end;
        end = e.getPoint();

        imageGraphics.setColor(c);
        imageGraphics.setStroke(new BasicStroke(5));
        imageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        imageGraphics.drawLine(start.x, start.y, end.x, end.y);

        repaint();
    }

    public void mouseReleased(MouseEvent e) {
        start = null;
        end = null;
    }
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.drawImage(image, null, 0, 0);
}

您将立即看到缩放问题。 位图缓冲区为500x500像素,超出该范围的任何内容均不会绘制。 这基本上与Microsoft Paint的工作方式相同:开始绘制之前,您需要了解画布的大小。

暂无
暂无

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

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