1

所以我有一个程序,它基本上类似于绘画,但用 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) { }

有谁知道问题是什么?

4

1 回答 1

4

Painting is a destructive process. That is, each time paintComponent is called, you are expected to repaint what ever it is you need to displayed the screen, entirely from scratch.

There are (at least) two immediate issues with your approach

  1. You are not calling super.paintComponent, this will effect the way in which the paint process updates the screen, this VERY important as you have extended from JComponent which is transparent by default and may compromise the ability for the framework to function correctly (leaving nasty paint artifacts all over the place) - also remember, Graphics is a shared resource. All the other components that are to be painted will share this resource, meaning that you could end up with what ever was painted before you being left on the screen.
  2. You are re-loading your image EVERY time paintComponent is called. This means, that what ever you painted to graphics2D is going to be lost.

I wouldn't bother setDoubleBuffered(false) as this will effect the way in which the component is updated and could produce undesirable results.

I would add each point you want to draw to a List of some kind and paint this list within the paintComponent method.

Don't load resources within any paintXxx method. These should be prepared before hand.

I can see that you are "trying" to perform some kind of double buffering, but this isn't really how it should be done. You are going little from it other then problems. Start with a simple solution first.

于 2013-07-24T00:49:11.187 回答