如何在 JComponent 上永久绘画
How to paint permanently on JComponent
我正在尝试在 Java 中创建绘图应用程序。
- 我有一个扩展 JComponent 的 "canvas" class。
- 我有一个 Shape 类型的 ArrayList,它包含整个绘图的所有形状。
paintComponent() 方法内部:
- 每个循环都被清除
- ArrayList 中的每个形状都用 g.draw() 或 g.fill()
绘制
- 如果我想添加一个形状或绘制一个形状,我将它添加到 ArrayList。
问题是在 ArrayList 中有相当多的形状后,paintComponent() 方法的执行变慢了。
例如自定义画笔。
- 将笔刷拖到 canvas 上时,我必须向 ArrayList
添加类型为 "CustomBrush extends Shape" 的新形状
- 因此,只需一笔画,我就可以在 ArrayList 中得到数百个形状
问题是:
- 我如何"pack"将 100 个 Shape 对象合并为一个,以便单个笔触成为我的 ArrayList 中的一个对象?
- 然而,最终目标是加快 paintComponent() 方法的速度,以便它更快地绘制所有绘制的形状。
谢谢!
这是一个示例代码:
public class GraphicPanel extends JComponent{
private ArrayList<Shape> shapeBuffer;
public void paintComponent( Graphics gPlain ){
Graphics2D g = (Graphics2D)gPlain;
for( Shape s : shapeBuffer ){
if( filled.next() ){
g.fill( s );
}
else{
g.draw( s );
}
}
}
将背景绘制到 BufferedImage,然后使用 g.drawImage(...)
在 paintComponent(...)
方法中将 BufferedImage 绘制到您的 GrahpicPanel。您可以通过调用 getGraphics()
或 createGraphics()
(对于 Graphics2D 对象)获取 BufferedImage 的 Graphics 上下文。不要忘记处置以这种方式获得的 Graphics 对象(但永远不要处置 JVM 给你的 Graphics 对象)。
此外,不要忘记在覆盖中调用 super.paintComponent(g)
!
例如:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;
public class MyPaint extends JComponent {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final Stroke STROKE = new BasicStroke(4f);
private static final Color[] COLORS = { Color.RED, Color.GREEN,
Color.yellow, Color.orange, Color.blue, Color.cyan };
private BufferedImage img = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
private Rectangle rect = null;
public MyPaint() {
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, null);
}
if (rect != null) {
g.setColor(Color.LIGHT_GRAY);
((Graphics2D) g).draw(rect);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
private Random random = new Random();
private Point p;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
p = e.getPoint();
}
@Override
public void mouseReleased(MouseEvent e) {
if (p != null) {
Rectangle rect2 = createRect(e.getPoint());
Graphics2D g2 = img.createGraphics();
g2.setStroke(STROKE);
Color c = COLORS[random.nextInt(COLORS.length)];
g2.setColor(c);
g2.fill(rect2);
g2.setColor(c.darker());
g2.draw(rect2);
g2.dispose();
}
p = null;
rect = null;
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
rect = createRect(e.getPoint());
repaint();
}
private Rectangle createRect(Point p2) {
int x = Math.min(p.x, p2.x);
int y = Math.min(p.y, p2.y);
int width = Math.abs(p.x - p2.x);
int height = Math.abs(p.y - p2.y);
Rectangle rect2 = new Rectangle(x, y, width, height);
return rect2;
}
}
private static void createAndShowGui() {
MyPaint mainPanel = new MyPaint();
JFrame frame = new JFrame("MyPaint");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
笔触和颜色是形状的属性。您可以像这样定义自己的形状 class。这样,您就可以维护列表中的形状。
package com.ggl.testing;
import java.awt.Color;
import java.awt.Shape;
public class MyShape {
private int brushSize;
private Color interiorColor;
private Shape shape;
public MyShape() {
this.brushSize = 1;
this.interiorColor = Color.blue;
}
public MyShape(int brushSize, Color interiorColor, Shape shape) {
this.brushSize = brushSize;
this.interiorColor = interiorColor;
this.shape = shape;
}
public int getBrushSize() {
return brushSize;
}
public void setBrushSize(int brushSize) {
this.brushSize = brushSize;
}
public Color getInteriorColor() {
return interiorColor;
}
public void setInteriorColor(Color interiorColor) {
this.interiorColor = interiorColor;
}
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
}
如果我遗漏了任何属性,请随时将它们添加到您的形状中 class。
我正在尝试在 Java 中创建绘图应用程序。
- 我有一个扩展 JComponent 的 "canvas" class。
- 我有一个 Shape 类型的 ArrayList,它包含整个绘图的所有形状。
paintComponent() 方法内部:
- 每个循环都被清除
- ArrayList 中的每个形状都用 g.draw() 或 g.fill() 绘制
- 如果我想添加一个形状或绘制一个形状,我将它添加到 ArrayList。
问题是在 ArrayList 中有相当多的形状后,paintComponent() 方法的执行变慢了。
例如自定义画笔。
- 将笔刷拖到 canvas 上时,我必须向 ArrayList 添加类型为 "CustomBrush extends Shape" 的新形状
- 因此,只需一笔画,我就可以在 ArrayList 中得到数百个形状
问题是:
- 我如何"pack"将 100 个 Shape 对象合并为一个,以便单个笔触成为我的 ArrayList 中的一个对象?
- 然而,最终目标是加快 paintComponent() 方法的速度,以便它更快地绘制所有绘制的形状。
谢谢!
这是一个示例代码:
public class GraphicPanel extends JComponent{
private ArrayList<Shape> shapeBuffer;
public void paintComponent( Graphics gPlain ){
Graphics2D g = (Graphics2D)gPlain;
for( Shape s : shapeBuffer ){
if( filled.next() ){
g.fill( s );
}
else{
g.draw( s );
}
}
}
将背景绘制到 BufferedImage,然后使用 g.drawImage(...)
在 paintComponent(...)
方法中将 BufferedImage 绘制到您的 GrahpicPanel。您可以通过调用 getGraphics()
或 createGraphics()
(对于 Graphics2D 对象)获取 BufferedImage 的 Graphics 上下文。不要忘记处置以这种方式获得的 Graphics 对象(但永远不要处置 JVM 给你的 Graphics 对象)。
此外,不要忘记在覆盖中调用 super.paintComponent(g)
!
例如:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;
public class MyPaint extends JComponent {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final Stroke STROKE = new BasicStroke(4f);
private static final Color[] COLORS = { Color.RED, Color.GREEN,
Color.yellow, Color.orange, Color.blue, Color.cyan };
private BufferedImage img = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
private Rectangle rect = null;
public MyPaint() {
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, null);
}
if (rect != null) {
g.setColor(Color.LIGHT_GRAY);
((Graphics2D) g).draw(rect);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
private Random random = new Random();
private Point p;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
p = e.getPoint();
}
@Override
public void mouseReleased(MouseEvent e) {
if (p != null) {
Rectangle rect2 = createRect(e.getPoint());
Graphics2D g2 = img.createGraphics();
g2.setStroke(STROKE);
Color c = COLORS[random.nextInt(COLORS.length)];
g2.setColor(c);
g2.fill(rect2);
g2.setColor(c.darker());
g2.draw(rect2);
g2.dispose();
}
p = null;
rect = null;
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
rect = createRect(e.getPoint());
repaint();
}
private Rectangle createRect(Point p2) {
int x = Math.min(p.x, p2.x);
int y = Math.min(p.y, p2.y);
int width = Math.abs(p.x - p2.x);
int height = Math.abs(p.y - p2.y);
Rectangle rect2 = new Rectangle(x, y, width, height);
return rect2;
}
}
private static void createAndShowGui() {
MyPaint mainPanel = new MyPaint();
JFrame frame = new JFrame("MyPaint");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
笔触和颜色是形状的属性。您可以像这样定义自己的形状 class。这样,您就可以维护列表中的形状。
package com.ggl.testing;
import java.awt.Color;
import java.awt.Shape;
public class MyShape {
private int brushSize;
private Color interiorColor;
private Shape shape;
public MyShape() {
this.brushSize = 1;
this.interiorColor = Color.blue;
}
public MyShape(int brushSize, Color interiorColor, Shape shape) {
this.brushSize = brushSize;
this.interiorColor = interiorColor;
this.shape = shape;
}
public int getBrushSize() {
return brushSize;
}
public void setBrushSize(int brushSize) {
this.brushSize = brushSize;
}
public Color getInteriorColor() {
return interiorColor;
}
public void setInteriorColor(Color interiorColor) {
this.interiorColor = interiorColor;
}
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
}
如果我遗漏了任何属性,请随时将它们添加到您的形状中 class。