-1

我正在尝试制作一个绘画程序,而这个类是您拖动鼠标进行绘画的主要区域。问题是剪辑必须是矩形的,因此剪辑矩形内的任何其他线(剪辑越大,您移动的速度越快)将被新剪辑覆盖,但新剪辑并非全部需要。

我对解决方案的想法是:

以某种方式将剪辑设置为一条线(但我认为必须在重绘方法中设置剪辑,而不是在绘制组件中设置 setClip())

将当前图像保存在绘制组件上并将其设置为背景

可能在没有线条的区域将剪辑的占用率设置得较低?

感谢您查看它,这是代码(为了便于阅读,省略了一些部分),如果您知道解决方案,我很想听听。谢谢!

public class Canvas extends JPanel implements MouseMotionListener, MouseListener{

    int sizeX, sizeY;
    String title;
    int[] backColor = new int[3];
    int brushSize=20;
    Point currentP = new Point();
    Point pastP = new Point();
    Point paintP = new Point();
    int diffX, diffY;
    boolean initialize=true;
    boolean initClip=true;




    Canvas(){
        backColor[0] = newProject.colorA;
        backColor[1] = newProject.colorB;
        backColor[2] = newProject.colorC;


        if(backColor[0]>=255){
            backColor[0]=255;
        }
        if(backColor[1]>=255){
            backColor[1]=255;
        }
        if(backColor[2]>=255){
            backColor[2]=255;
        }
        sizeX = newProject.sizeX;
        sizeY = newProject.sizeY;

        //System.out.println(sizeX + " " + sizeY);
        setSize(sizeX,sizeY);
        setBackground(Color.white);
    }

public void paintComponent(Graphics g){

        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(brushSize));
        if(initialize){
        g.setColor(new Color(backColor[0], backColor[1], backColor[2]));
        g.fillRect(0, 0, sizeX, sizeY);
        g.setColor(Color.red);
        g.drawRect(0,0,50,50);
        System.out.println("Initialize");

        }
        else{

        g2.drawLine(currentP.x, currentP.y, pastP.x,pastP.y);
        }

        //System.out.println("Paint");
}
@Override
public void mouseDragged(MouseEvent e) {
    if(initClip)                       //if mouse has been released since last dragged
        currentP = e.getPoint();   //This causes PastP and CurrentP to be equal 
        initClip=false;            //since pastP is set equal to CurrentP afterward
    pastP = currentP;
    currentP = e.getPoint();
    diffX=Math.abs(currentP.x-pastP.x);  //find the differences to find how big of 
    diffY=Math.abs(currentP.y-pastP.y);  //a clip it needs
    if(diffX==0){                        //if no movement, set it to brush size so the
        diffX=brushSize;             //clip shows up
    }
    if(diffY==0){
        diffY=brushSize;
    }
    initialize=false;


    if(currentP.x-pastP.x>0){    //figures out which direction it moved
        paintP.x=pastP.x;    //sets the clip variable to the correct corner
    }
    else{
        paintP.x=currentP.x;
    }

    if(currentP.y-pastP.y>0){
        paintP.y=pastP.y;
    }
    else{
        paintP.y=currentP.y;
    }
    System.out.println(paintP);
    repaint(paintP.x, paintP.y, diffX, diffY);  //repaint with point PaintP and the
                                                //difference it moved

}

@Override
public void mouseReleased(MouseEvent arg0) {
    initClip=true;


}
4

1 回答 1

2

我不知道你为什么要打扰。每次paintComponent被绘制系统调用时,您都应该重新绘制整个组件。

相反,只需绘制您需要绘制的内容,然后在其上绘制选择...

在此处输入图像描述

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawSelection {

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

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

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

    public class TestPane extends JPanel {

        private BufferedImage background;
        private Rectangle clipRect;

        public TestPane() {
            try {
                background = ImageIO.read(new File("/path/to/your/image"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            MouseAdapter ma = new MouseAdapter() {

                private Point cp;

                @Override
                public void mousePressed(MouseEvent e) {
                    cp = e.getPoint();
                    clipRect = null;
                    repaint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    cp = null;
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    Point p = e.getPoint();
                    int x = Math.min(p.x, cp.x);
                    int y = Math.min(p.y, cp.y);
                    int width = Math.max(p.x, cp.x) - x;
                    int height = Math.max(p.y, cp.y) - y;
                    clipRect = new Rectangle(x, y, width, height);
                    repaint();
                }


            };

            addMouseListener(ma);
            addMouseMotionListener(ma);

        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (background != null) {
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g2d.drawImage(background, x, y, this);
            }
            if (clipRect != null) {

                g2d.setColor(UIManager.getColor("List.selectionBackground"));
                g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                g2d.fill(clipRect);

            }
            g2d.dispose();
        }
    }

}

如果要优化绘制过程,为什么不将图像的部分绘制到后备缓冲区并简单地绘制缓冲区,然后在paintComponent?

于 2013-10-23T01:59:04.847 回答