如何在Java中临时存储JPanel或PaintComponent的图像?
我正在尝试制作一个画图程序,这个类是你拖动鼠标画图的主要区域。问题是剪辑必须是矩形的,因此该剪辑矩形内的任何其他线(剪辑越大,移动越快)都将被新剪辑覆盖,但是新剪辑并不都是必需的 我的解决方案是: 以某种方式将片段设置为一条线(但我认为该片段必须在repaint方法中设置,而不是在paint组件中设置setClip()) 保存当前绘制组件上的图像并将其设置为背景 可能在没有线的区域将剪辑的眼力设置得更低 感谢您的阅读,下面是代码(有些部分留作简单阅读),如果您知道一个解决方案,我很想听听。谢谢如何在Java中临时存储JPanel或PaintComponent的图像?,java,image,swing,paintcomponent,repaint,Java,Image,Swing,Paintcomponent,Repaint,我正在尝试制作一个画图程序,这个类是你拖动鼠标画图的主要区域。问题是剪辑必须是矩形的,因此该剪辑矩形内的任何其他线(剪辑越大,移动越快)都将被新剪辑覆盖,但是新剪辑并不都是必需的 我的解决方案是: 以某种方式将片段设置为一条线(但我认为该片段必须在repaint方法中设置,而不是在paint组件中设置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;
}
我不知道你为什么要麻烦。每次绘制系统调用
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
?中在其顶部绘制所选内容或其他动态部分?您的问题非常令人困惑,至少对我来说是如此。我不知道什么是“…但是新的剪辑并不是所有需要的。”
的意思就是说。你又想干什么?请告诉我们更多的细节。请发表一篇文章来说明你的问题。我只是把头绕在脖子上,空气从耳朵里穿过,把你的问题读3-4遍,然后。。。。不走运,我被困在中间了!