更改JPanel图形g的颜色并绘制线条

3
我是一名有用的助手,可以为您翻译文本。

我有一个类似于画图的程序。我正在尝试实现更改笔颜色的功能,但当我改变颜色时,当前绘制的所有内容都会被更改为红色。例如,在我的程序中,我如何使它不会重新绘制当前已绘制的所有内容到当前更改的颜色?下面的代码将编译并运行。

JPanel绘图区的类

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
//refer to http://jkost.ergoway.gr/jnkjavaconnection/freedraw.html for the algorithm.
public class STDrawingArea extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    ArrayList<Rectangle> dPoint = new ArrayList<Rectangle>();
    Point point = new Point(-1,-1);
    private Color currentColor;

    public STDrawingArea()
    {
         setBorder(BorderFactory.createLineBorder(Color.black));
         setBackground(Color.WHITE);

         addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) 
            {
                dPoint.add(new Rectangle(point.x,point.y,e.getX(),e.getY()));
                point.x = e.getX();
                point.y = e.getY();
                repaint();
            }

             });

         addMouseListener(new MouseAdapter(){
             public void mousePressed(MouseEvent e)
             {
                 System.out.println("mousePressed X: "+e.getX()+"mousePressed Y: "+e.getY());
                 dPoint.add(new Rectangle(e.getX(),e.getY(),-1,-1));
                 point.x = e.getX();
                 point.y = e.getY();
             }
         });

         addMouseListener(new MouseAdapter(){
             public void mouseReleased(MouseEvent e)
             {
                 System.out.println("mouseReleased X: "+e.getX()+"mouseReleased Y: "+e.getY());
                 repaint();
             }
         });
    }

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

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
       g.setColor(getCurrentColor());
        for (int i=0; i < dPoint.size(); i++) {  
            Rectangle r = dPoint.get(i);
            if (r.width != -1)
            {
              g.drawLine(r.x, r.y, r.width, r.height);  
            }
           }  
            /* Draw current point.*/ 
            g.drawLine(point.x, point.y, point.x, point.y);  
    }

    //set current drawing color
    public void changePenColor(Color color)
    {
        if (color == null)
        setCurrentColor(Color.BLACK);
        else
        setCurrentColor(color);
    }

    //clear drawings method
    public void clearDrawings()
    {
        if(!(dPoint==null))
        {
             dPoint.clear();
             repaint();
        }

    }

    private void setCurrentColor(Color currentColor) {
        this.currentColor = currentColor;
    }

    private Color getCurrentColor() {
        return currentColor;
    }
}

测试主类。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class STTestMain extends JFrame {
    STDrawingArea drawingArea = new STDrawingArea();
    public STTestMain()
    {
        //JFrame settings
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Spelling Trainer");
        setResizable(false);
        setVisible(true);


        //Panel of buttons
        JPanel buttonContainer = new JPanel();
        JButton btnPenColor = new JButton("Red Pen");

        buttonContainer.add(btnPenColor);
        //Drawing Area instantiation


        //Adding things to JFrame
        getContentPane().add(drawingArea);
        getContentPane().add(buttonContainer,BorderLayout.PAGE_END);
        pack();


        //button listener
        btnPenColor.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                drawingArea.changePenColor(Color.RED);
            }
        });
    }


    public static void main(String args[])
    {
        STTestMain test = new STTestMain();
    }

}
3个回答

9

一种方法:

  • 使用您的ArrayList在绘制当前曲线时进行绘制,但是
  • 使用BufferedImage来绘制您完成的曲线
  • 您需要在mouseReleased上执行此操作,并使用当前颜色将当前曲线绘制到BufferedImage中。
  • 在绘制到BufferedImage后,您还需要重新初始化点的ArrayList。
  • 不要忘记在使用完毕后处理BufferedImage的Graphics对象。
  • 在super.paintComponent之后但在绘制当前曲线之前,在paintComponent方法中绘制BufferedImage。
  • 这样,当您更改绘图的颜色时,只会影响当前的曲线。

编辑
您在评论中提到您不熟悉BufferedImage,并正在寻找另一种方法。我想您可以创建一个类,该类包含一个带有颜色的Points的ArrayList,然后在每个mouseReleased上创建此类的对象并将其添加到绘图面板中的ArrayList中。然后,您的paintComponent方法可以遍历该ArrayList,使用其关联的颜色绘制Points列表,但我的直觉告诉我,您是一个聪明的人,您很快就能学会如何使用BufferedImage。我真的认为这是最好的解决方案。如果您尝试并失败了,请向我们展示您的代码,我们可能能够帮助您。

编辑2
BufferedImage构造函数将需要图像宽度、高度和图像类型--这是我不完全熟悉的内容。我通常使用BufferedImage.TYPE_INT_RGB进行一般绘图,使用BufferedImage.TYPE_INT_ARGB进行需要alpha的一般绘图。然后,您将从BufferedImage中提取一个Graphics对象,例如getGraphics(),如果您只需要一个Graphics对象而不是Graphics2D对象。然后,在构造函数中初始化BufferedImage时,用Color.white填充它,就像您为JPanel所做的那样。然后处理Graphics对象。每次要绘制时,获取Graphics,与之一起绘制,就像在paintComponent方法中一样,完成后处理Graphics,最后通过drawImage方法在paintComponent中绘制BufferedImage。

编辑3
示例程序,虽然不完全符合您尝试做的事情,但说明了使用BufferedImage进行绘图的方法。此程序每次绘制新路径或曲线时更改颜色。

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.*;

public class STTestSimple {
   private static void createAndShowUI() {
      STDrawPanel drawPanel = new STDrawPanel();
      STMouseAdapter mAdapter = new STMouseAdapter(drawPanel);
      drawPanel.addMouseListener(mAdapter);
      drawPanel.addMouseMotionListener(mAdapter);

      JFrame frame = new JFrame("Drawing");
      frame.getContentPane().add(drawPanel);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setResizable(false);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

@SuppressWarnings("serial")
class STDrawPanel extends JPanel {
   private static final int ST_WIDTH = 700;
   private static final int ST_HEIGHT = 500;
   private static final Color BACKGROUND_COLOR = Color.white;
   private static final float STROKE_WIDTH = 6f;
   private static final Stroke STROKE = new BasicStroke(STROKE_WIDTH,
            BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
   private static final Color[] colors = {Color.black, Color.blue, Color.red,
      Color.green, Color.orange, Color.MAGENTA};

   private BufferedImage bImage = new BufferedImage(ST_WIDTH, ST_HEIGHT,
            BufferedImage.TYPE_INT_RGB);
   private Color color = Color.black;
   private ArrayList<Point> points = new ArrayList<Point>();
   private int colorIndex = 0;

   public STDrawPanel() {
      Graphics g = bImage.getGraphics();
      g.setColor(BACKGROUND_COLOR);
      g.fillRect(0, 0, ST_WIDTH, ST_HEIGHT);
      g.dispose();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawImage(bImage, 0, 0, null);
      Graphics2D g2 = (Graphics2D) g;
      drawCurve(g2);
   }

   private void addCurveToBufferedImage() {
      Graphics2D g2 = bImage.createGraphics();
      drawCurve(g2);
      g2.dispose();
   }

   private void drawCurve(Graphics2D g2) {
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setStroke(STROKE);
      g2.setColor(color);
      if (points != null && points.size() > 1) {
         for (int i = 0; i < points.size() - 1; i++) {
            int x1 = points.get(i).x;
            int y1 = points.get(i).y;
            int x2 = points.get(i + 1).x;
            int y2 = points.get(i + 1).y;
            g2.drawLine(x1, y1, x2, y2);
         }
      }
   }

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

   public void curveStart(Point point) {
      points.clear();
      points.add(point);
   }

   public void curveEnd(Point point) {
      points.add(point);
      addCurveToBufferedImage();
      points.clear();
      repaint();

      colorIndex++;
      colorIndex %= colors.length;
      setColor(colors[colorIndex]);
   }

   public void curveAdd(Point point) {
      points.add(point);
      repaint();
   }

   public void setColor(Color color) {
      this.color = color;
   }
}

class STMouseAdapter extends MouseAdapter {
   private STDrawPanel drawPanel;

   public STMouseAdapter(STDrawPanel drawPanel) {
      this.drawPanel = drawPanel;
   }

   @Override
   public void mousePressed(MouseEvent e) {
      drawPanel.curveStart(e.getPoint());
   }

   @Override
   public void mouseReleased(MouseEvent e) {
      drawPanel.curveEnd(e.getPoint());
   }

   @Override
   public void mouseDragged(MouseEvent e) {
      drawPanel.curveAdd(e.getPoint());
   }
}

你好,很抱歉我之前没有处理过BufferedImage的经验,因为我还比较新手,有其他方法可以实现吗? - sutoL
@kyrogue:请查看我上面回答中的编辑。 - Hovercraft Full Of Eels
我已经阅读到,BufferedImage 构造函数将接受图像类型?但是我的 JPanel 绘画不是图像,它只是自由手绘线条,请问这两者如何衔接? - sutoL
BufferedImage的构造函数需要图像的宽度、高度和图像类型——这是我不太熟悉的东西。通常我会使用BufferedImage.TYPE_INT_RGB进行一般绘图,而对于需要alpha通道的一般用途,则使用BufferedImage.TYPE_INT_ARGB。 - Hovercraft Full Of Eels
@kyrogue:我已经发布了使用BufferedImage的示例代码。希望能有所帮助。 - Hovercraft Full Of Eels

1

0

谢谢 hovercraft,看了你的代码并调试后我搞定了 lol。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JPanel;

public class STDrawingArea extends JPanel {
    /**
     * 
     */
    private static final int DA_WIDTH = 700;
    private static final int DA_HEIGHT = 500;
    private static final Color DA_BGCOLOR = Color.WHITE;
    private static final long serialVersionUID = 1L;


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

    private Color currentColor;
    BufferedImage bImage = new BufferedImage(DA_WIDTH, DA_HEIGHT, BufferedImage.TYPE_INT_RGB);

    public STDrawingArea()
    {
         setBorder(BorderFactory.createLineBorder(Color.black));

         //Basic Settings for bImage
         Graphics g2d = bImage.getGraphics();
         g2d.setColor(DA_BGCOLOR);
         g2d.fillRect(0, 0, DA_WIDTH, DA_HEIGHT);
         g2d.dispose();

         addMouseListener(new MouseAdapter(){
             public void mousePressed(MouseEvent e)
             {
                points.clear();
                points.add(e.getPoint());
             }
         });

         addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) 
            {
                points.add(e.getPoint());
                repaint();
            }

             }); 

         addMouseListener(new MouseAdapter(){
             public void mouseReleased(MouseEvent e)
             {
                 points.add(e.getPoint());
                 points.clear();
                 System.out.println("mouseReleased X: "+e.getX()+"mouseReleased Y: "+e.getY());
                 repaint();
             }
         });
    }

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

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawIntoBufferedImage();
        g.drawImage(bImage,0,0,null);
        freehandLines(g);

    }
    public void drawIntoBufferedImage()
    {
        Graphics g = bImage.getGraphics();
        freehandLines(g);
        g.dispose();
    }

    public void freehandLines(Graphics g)
    {
         if(points != null && points.size() > 1)
         {

             g.setColor(getCurrentColor());
              for(int i = 0; i < points.size()-1;i++)
               {
                   int x1 = points.get(i).x;
                   int y1 = points.get(i).y;
                   int x2 = points.get(i+1).x;
                   int y2 = points.get(i+1).y;
                   g.drawLine(x1, y1, x2, y2);
               }
         }
    }
    //clear drawings method
    public void clearDrawings()
    {
        if(points!=null)
        {
            points.clear();
            Graphics g = bImage.getGraphics();
            g.setColor(DA_BGCOLOR);
            g.fillRect(0, 0, DA_WIDTH, DA_WIDTH);
            g.dispose();
            repaint();
        }

    }

    public void setCurrentColor(Color currentColor) {
        if(currentColor == null)
        {
            currentColor = Color.BLACK;
        }else{
            this.currentColor = currentColor;
        }

    }

    public Color getCurrentColor() {
        if (currentColor == null)
        return Color.BLACK;
        else
        return currentColor;
    }
}

主类

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class STTestMain extends JFrame {
    STDrawingArea drawingArea = new STDrawingArea();
    public STTestMain()
    {
        //JFrame settings
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Spelling Trainer");
        setResizable(false);
        setVisible(true);


        //Panel of buttons
        JPanel buttonContainer = new JPanel();
        JButton btnRedPen = new JButton("Red Pen");
        JButton btnGreenPen = new JButton("Green Pen");
        JButton btnClear = new JButton("Clear");
        buttonContainer.add(btnRedPen);
        buttonContainer.add(btnGreenPen);
        buttonContainer.add(btnClear);
        //Drawing Area instantiation


        //Adding things to JFrame
        getContentPane().add(drawingArea);
        getContentPane().add(buttonContainer,BorderLayout.PAGE_END);
        pack();


        //button listener
        btnRedPen.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                drawingArea.setCurrentColor(Color.RED);
            }
        });

        btnGreenPen.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                drawingArea.setCurrentColor(Color.GREEN);
            }
        });

        btnClear.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                drawingArea.clearDrawings();
            }
        });
    }


    public static void main(String args[])
    {
        STTestMain test = new STTestMain();
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接