我环顾四周,尝试使用其他查询,但我似乎无法让它工作。
我试图保留一个图像从一个JPanel绘制通过g.绘制/填充方法。
我试图将绘图保存在缓冲图像中,但是当我在消息对话框中显示它时,我得到的只是背景,没有任何绘图
这两个方法是重要的代码(来自DrawingPanel类):
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
BufferedImage image = new BufferedImage(this.getWidth(),
this.getHeight(), BufferedImage.TYPE_INT_RGB);
// call the Panels's paint method, using
// the Graphics object of the image.
this.paint(image.getGraphics());
return image;
}
他们在这里被称为:
@Override
public void actionPerformed(ActionEvent ae) {
BufferedImage bi = dp.getScreenShot();
dp.loadDrawing(bi);
}
这是整个程序,它应该运行。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TestClass extends JFrame implements ActionListener {
DrawingPanel dp;
public TestClass() {
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel top = new JPanel();
JButton load = new JButton("Load Image");
load.addActionListener(this);
top.add(load);
dp = new DrawingPanel();
dp.setBackground(Color.CYAN);
add(top, BorderLayout.NORTH);
add(dp, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
new TestClass();
}
@Override
public void actionPerformed(ActionEvent ae) {
BufferedImage bi = dp.getScreenShot();
dp.loadDrawing(bi);
}
private class DrawingPanel extends JPanel implements
MouseListener, MouseMotionListener {
private int xPos, yPos;//mouse positions
private DrawingPanel() {
addMouseListener(this);
addMouseMotionListener(this);
}
@Override
public void mousePressed(MouseEvent me) {
xPos = me.getX();
yPos = me.getY();
}
@Override
public void mouseDragged(MouseEvent me) {
int x = me.getX(), y = me.getY();
Graphics g = getGraphics();
g.setColor(Color.BLACK);
g.drawOval(xPos, yPos, 30, 30);
xPos = x;
yPos = y;
}
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
BufferedImage image = new BufferedImage(this.getWidth(),
this.getHeight(), BufferedImage.TYPE_INT_RGB);
// call the Panels's paint method, using
// the Graphics object of the image.
this.paint(image.getGraphics());
return image;
}
//unused abstract method
@Override
public void mouseClicked(MouseEvent me) {
}
@Override
public void mouseReleased(MouseEvent me) {
}
@Override
public void mouseEntered(MouseEvent me) {
}
@Override
public void mouseExited(MouseEvent me) {
}
@Override
public void mouseMoved(MouseEvent me) {
}
}
}
我需要能够从面板中存储图形并检索它。
非常感谢帮助。
每次尝试通过调用getGraphics
从Component
获得的Graphics
对象中绘制某些内容迟早会失败。这个Graphics
对象只是作为实际屏幕的“路径”(仅在组件实际绘制在屏幕上时有效)。它不是“缓冲区”,也不会“存储”任何绘制的内容。
如果你想创建一个简单的绘画程序,你应该绘制到一个BufferedImage
。当DrawingPanel
要绘制时,你只绘制这个BufferedImage
。这里的额外好处是,当你想要制作屏幕截图时,你基本上只需要返回这个BufferedImage
的副本。
我在您的DrawingPanel
类中勾勒了基本方法,并带有一些内联注释。它可以被清理和美化,并且有一些方面需要考虑(例如,当DrawingPanel
调整大小时应该发生什么?),但它显示了它通常应该如何工作:
private class DrawingPanel extends JPanel implements
MouseListener, MouseMotionListener {
// The image that will store what was drawn. In the
// mouseDragged method, the painting operations will
// go directly to this image. When this panel is
// painted, then ONLY this image will be painted.
private BufferedImage bufferedImage;
private int xPos, yPos;//mouse positions
private DrawingPanel() {
addMouseListener(this);
addMouseMotionListener(this);
}
// Make sure that the "bufferedImage" is non-null
// and has the same size as this panel
private void validateImage()
{
if (bufferedImage == null)
{
bufferedImage = new BufferedImage(
getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = bufferedImage.getGraphics();
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
g.dispose();
}
if (bufferedImage.getWidth() != getWidth() ||
bufferedImage.getHeight() != getHeight())
{
BufferedImage newBufferedImage = new BufferedImage(
getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = newBufferedImage.getGraphics();
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
g.drawImage(bufferedImage, 0,0,null);
g.dispose();
bufferedImage = newBufferedImage;
}
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
validateImage();
// Paint the bufferedImage which stores
// what was drawn until now
g.drawImage(bufferedImage, 0, 0, null);
}
@Override
public void mousePressed(MouseEvent me) {
xPos = me.getX();
yPos = me.getY();
}
@Override
public void mouseDragged(MouseEvent me) {
int x = me.getX(), y = me.getY();
validateImage();
// Paint directly into the bufferedImage here
Graphics g = bufferedImage.getGraphics();
g.setColor(Color.BLACK);
g.drawOval(xPos, yPos, 30, 30);
repaint();
xPos = x;
yPos = y;
}
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
// This basically returns a "copy" of the
// bufferedImage that stores what was drawn
BufferedImage image = new BufferedImage(
getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.drawImage(bufferedImage, 0, 0, null);
g.dispose();
return image;
}
//unused abstract method
@Override
public void mouseClicked(MouseEvent me) {
}
@Override
public void mouseReleased(MouseEvent me) {
}
@Override
public void mouseEntered(MouseEvent me) {
}
@Override
public void mouseExited(MouseEvent me) {
}
@Override
public void mouseMoved(MouseEvent me) {
}
}
通过调用组件上的getGraphics()
来获取Graphics对象,用它绘制的图像将不会持久。为什么不用它的Graphics对象绘制到BufferedImage,然后简单地保存该BufferedImage。这将大大简化事情,并且您的程序可以工作。
例如:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class TestClass2 extends JPanel {
private DrawingPanel drawingPanel = new DrawingPanel();
public TestClass2() {
JPanel northPanel = new JPanel();
northPanel.add(new JButton(new GetImageAction("Get Image")));
northPanel.add(new JButton(new ClearImageAction("Clear Image")));
setLayout(new BorderLayout(5, 5));
add(drawingPanel, BorderLayout.CENTER);
add(northPanel, BorderLayout.NORTH);
}
private class GetImageAction extends AbstractAction {
public GetImageAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_G);
}
@Override
public void actionPerformed(ActionEvent evt) {
BufferedImage img = drawingPanel.getMainImage();
ImageIcon icon = new ImageIcon(img);
JOptionPane.showMessageDialog(TestClass2.this, icon);
}
}
private class ClearImageAction extends AbstractAction {
public ClearImageAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
@Override
public void actionPerformed(ActionEvent evt) {
drawingPanel.clearImage();
drawingPanel.repaint();
}
}
private static void createAndShowGui() {
TestClass2 mainPanel = new TestClass2();
JFrame frame = new JFrame("TestClass2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class DrawingPanel extends JPanel {
public static final int BI_WIDTH = 400;
public static final int BI_HEIGHT = BI_WIDTH;
private static final Color BACKGROUND = Color.CYAN;
public static final Color DRAW_COLOR = Color.black;
public static final int OVAL_WIDTH = 30;
private BufferedImage mainImage;
public DrawingPanel() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
clearImage();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (mainImage != null) {
g.drawImage(mainImage, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(BI_WIDTH, BI_HEIGHT);
}
public BufferedImage getMainImage() {
return mainImage;
}
public void clearImage() {
mainImage = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g = mainImage.getGraphics();
g.setColor(BACKGROUND);
g.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
g.dispose();
}
private class MyMouseAdapter extends MouseAdapter {
@Override
public void mousePressed(MouseEvent mEvt) {
draw(mEvt);
}
@Override
public void mouseDragged(MouseEvent mEvt) {
draw(mEvt);
}
private void draw(MouseEvent mEvt) {
Graphics2D g2 = mainImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(DRAW_COLOR);
g2.drawOval(mEvt.getX() - OVAL_WIDTH / 2, mEvt.getY() - OVAL_WIDTH / 2, OVAL_WIDTH, OVAL_WIDTH);
g2.dispose();
repaint();
}
}
}