java - 在图像上绘图

标签 java image swing paintcomponent

所以我有一个基本上类似于绘画的程序,但它是用 Java 编写的,只能绘制几种颜色。默认情况下,程序的背景是白色的,但我想做的是尝试加载图像,然后能够在该图像上绘制。我可以加载图像,但由于某些原因,当我尝试在其上绘图时它不会显示线条。这是代码。

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.*;

public class Paint {

public static void main(String[] args) {
    PaintWindow frame = new PaintWindow();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.setVisible(true);
}
}

class PaintWindow extends JFrame { 

public PaintWindow() {
    setTitle("JavShot Edit");
    setSize(668, 600);
    setLocationRelativeTo(null);

    panel = new JPanel();
    drawPad = new PadDraw();

    panel.setPreferredSize(new Dimension(75, 68));

    //Creates a new container
    Container content = this.getContentPane();
    content.setLayout(new BorderLayout());

    //sets the panel to the left, padDraw in the center
    content.add(panel, BorderLayout.WEST);
    content.add(drawPad, BorderLayout.CENTER);

    //add the color buttons:
    makeColorButton(Color.BLUE);
    makeColorButton(Color.MAGENTA);
    makeColorButton(Color.RED);
    makeColorButton(Color.GREEN);
    makeColorButton(Color.BLACK);
    makeColorButton(Color.WHITE);

    //creates the clear button
    JButton clearButton = new JButton("Clear");

    clearButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            drawPad.clear();
        }
    });

    panel.add(clearButton);
}

/*
 * makes a button that changes the color
 * @param color the color used for the button
 */
public void makeColorButton(final Color color) {
    JButton tempButton = new JButton();
    tempButton.setBackground(color);
    tempButton.setPreferredSize(new Dimension(16, 16));
    panel.add(tempButton);
    tempButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            drawPad.changeColor(color);
        }
    });
}

private JPanel panel;
private PadDraw drawPad;
}

class PadDraw extends JComponent {

//this is gonna be your image that you draw on
Image image;
//this is what we'll be using to draw on
Graphics2D graphics2D;
//these are gonna hold our mouse coordinates
int currentX, currentY, oldX, oldY;

public PadDraw() {
    setDoubleBuffered(false);
    addMouseListener(new MouseAdapter() {
        //if the mouse is pressed it sets the oldX & oldY
        //coordinates as the mouses x & y coordinates
        public void mousePressed(MouseEvent e) {
            oldX = e.getX();
            oldY = e.getY();
        }
    });

    addMouseMotionListener(new MouseMotionAdapter() {
        //while the mouse is dragged it sets currentX & currentY as the mouses x and y
        //then it draws a line at the coordinates
        //it repaints it and sets oldX and oldY as currentX and currentY
        public void mouseDragged(MouseEvent e) {
            currentX = e.getX();
            currentY = e.getY();

            graphics2D.drawLine(oldX, oldY, currentX, currentY);
            graphics2D.drawLine(oldX + 1, oldY + 1, currentX + 1, currentY + 1);
            repaint();

            oldX = currentX;
            oldY = currentY;
        }
    });
}

//this is the painting bit
//if it has nothing on it then
//it creates an image the size of the window
//sets the value of Graphics as the image
//sets the rendering
//runs the clear() method
//then it draws the image
public void paintComponent(Graphics g) {

    try {
        image = ImageIO.read(new File("C:\\Users\\user\\Desktop\\Untitled.png"));
        graphics2D = (Graphics2D)image.getGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    } catch (IOException e) { }

    if(image == null) {

        image = createImage(getSize().width, getSize().height);
        graphics2D = (Graphics2D)image.getGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        clear();
    } 

    g.drawImage(image, 0, 0, null);
}

//this is the clear
//it sets the colors as white
//then it fills the window with white
//thin it sets the color back to black
public void clear() {
    graphics2D.setPaint(Color.white);
    graphics2D.fillRect(0, 0, getSize().width, getSize().height);
    graphics2D.setPaint(Color.black);
    repaint();
}

public void changeColor(Color theColor) {
    graphics2D.setPaint(theColor);
    repaint();
}
} 

我在这里加载图像:

image = ImageIO.read(new File("C:\\Users\\user\\Desktop\\Untitled.png"));
        graphics2D = (Graphics2D)image.getGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    } catch (IOException e) { }

有人知道问题出在哪里吗?

最佳答案

绘画是一个破坏性的过程。也就是说,每次 paintComponent 被调用时,您都应该重新绘制显示屏幕所需的内容,完全从头开始。

您的方法(至少)有两个紧迫的问题

  1. 您没有调用 super.paintComponent,这将影响绘制过程更新屏幕的方式,这非常重要,因为您已经从 JComponent 进行了扩展,它是默认情况下是透明的,并且可能会损害框架正常运行的能力(到处都是令人讨厌的绘画工件)——还要记住,Graphics 是一种共享资源。所有其他要绘制的组件都将共享此资源,这意味着您可以在离开屏幕之前获得已绘制的内容。
  2. 每次调用 paintComponent 时,您都在重新加载图像。这意味着,您绘制到 graphics2D 的所有内容都将丢失。

我不会打扰 setDoubleBuffered(false) 因为这会影响组件的更新方式并可能产生不良结果。

我会将您想绘制的每个点添加到某种类型的 List 中,然后在 paintComponent 方法中绘制此列表。

不要在任何paintXxx 方法中加载资源。这些应该事先准备好。

我可以看出您正在“尝试”执行某种双缓冲,但这并不是真正应该做的。除了问题之外,你几乎没有什么进展。首先从一个简单的解决方案开始。

关于java - 在图像上绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17823356/

相关文章:

image - kml Google Earth 中的动画地标图标?

java - 将 JButton 控件添加到 JApplet 并且 JButton 填满整个屏幕

java - 模拟长时间运行的操作

java - 将 JPanel 添加到主面板

java - JMS消息监听器执行失败,没有设置ErrorHandler

java - 如何让 JLabel 文字显示 1 秒?

java - 尝试在 finally 部分中捕获

python - 无法在 Python 图像库(枕头)上加载字体

java - 如何设置Jsoup读取的数据编码?

python - 如何获取与另一个像素成一定角度的像素值?