Java 如何在JComponent上永久绘制
我正在尝试用Java创建一个绘画应用程序Java 如何在JComponent上永久绘制,java,swing,arraylist,graphics,shape,Java,Swing,Arraylist,Graphics,Shape,我正在尝试用Java创建一个绘画应用程序 我有一个扩展JComponent的“canvas”类 我有一个Shape类型的ArrayList,它保存了整个图形的所有形状 在paintComponent()方法中: 每个循环都会被清除 ArrayList中的每个形状都使用g.draw()或g.fill()进行绘制 如果要添加形状或绘制形状,请将其添加到ArrayList 问题是,在ArrayList中有相当多的形状之后,paintComponent()方法的执行速度会减慢 例如,自定义笔刷
- 我有一个扩展JComponent的“canvas”类
- 我有一个Shape类型的ArrayList,它保存了整个图形的所有形状
- 每个循环都会被清除
- ArrayList中的每个形状都使用g.draw()或g.fill()进行绘制
- 如果要添加形状或绘制形状,请将其添加到ArrayList
- 在画布上拖动笔刷时,我必须向ArrayList添加一个类型为“CustomBrush extends Shape”的新形状
- 因此,只需一个笔划,我就可以在ArrayList中找到数百个形状
- 如何将100个形状对象“打包”为一个,使单个笔刷笔划成为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 );
}
}
}
公共类GraphicPanel扩展JComponent{
私人ArrayList shapeBuffer;
公共组件(图形gPlain){
Graphics2D g=(Graphics2D)gPlain;
用于(形状s:shapeBuffer){
if(filled.next()){
g、 填充;
}
否则{
g、 抽签;
}
}
}
使用g.drawImage(…)
将背景绘制到BuffereImage,然后使用g.drawImage(…)
将BuffereImage绘制到您的GrahpicPanel中。您可以通过调用getGraphics()
或createGraphics()
(对于Graphics2D对象)来获取BuffereImage的图形上下文。不要忘记处理以这种方式获得的图形对象(但永远不要处理JVM提供给您的图形对象)
另外,不要忘记调用覆盖中的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();
}
});
}
}
将背景绘制到BuffereImage,然后使用
g.drawImage(…)
在paintComponent(…)
方法中将BuffereImage绘制到GrahpicPanel中。您可以通过调用getGraphics()
或createGraphics()
(对于Graphics2D对象)来获取BuffereImage的图形上下文。不要忘记处理以这种方式获得的图形对象(但永远不要处理JVM提供给您的图形对象)
另外,不要忘记调用覆盖中的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();
}
});
}
}
笔触和颜色是形状的属性。您可以这样定义自己的形状类。这样,您就可以在列表中维护形状
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;
}
}
如果我遗漏了任何属性,请随意将它们添加到您的形状类中。笔刷和颜色是形状的属性。您可以这样定义自己的形状类。这样,您就可以在列表中维护形状
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;
}
}
如果我遗漏了任何属性,请随意将它们添加到您的shape类中。
“画笔和颜色是形状的属性”
--也许我误解了您的答案,但这不应该是“不是形状的属性”?请为我澄清。@HovercraftFullOfEels:当你绘制或填充一个形状时,你可以在绘制或填充一个形状之前设置颜色和笔划。这使形状具有颜色和笔划属性。我理论上同意,但我是从字面上阅读它的形状接口及其具体类,它们没有机制来实现这一点。我明白你的意思了。1+“笔触和颜色是形状的属性”
——也许我误解了你的答案,但这不应该是“不是形状的属性”?请为我澄清。@HovercraftFullOfEels:当你绘制或填充一个形状时,你可以在绘制或填充一个形状之前设置颜色和笔划。这使形状具有颜色和笔划属性。我理论上同意,但我是从字面上阅读它的形状接口及其具体类,它们没有机制来实现这一点。我明白你的意思了。1+检查。它比较了两种方法1)从列表中绘制和2)从缓冲区图像绘制,并包含了这两种方法的工作示例。@camickr感谢装满鳗鱼的气垫船,我可以实现这两种检查。它比较了两种方法1)从列表中绘制和2)从缓冲区图像绘制和继续这两种方法都是很好的例子。@camickr多亏了装满鳗鱼的气垫船,我才能够实现我想要的东西!谢谢你,先生!还有,在mouseDragged()中,为什么不仅仅是rect.setSize()呢?为垃圾箱浪费更少的内存和更少的工作collector@Fresco:那可能更好。试试看。这正是我想要的!谢谢你,先生!还有,在mouseDragged()中,为什么不只是rect.setSize()?为垃圾浪费更少的内存和更少的工作collector@Fresco:那很可能更好。去做吧。