![](/img/trans.png)
[英]Is there a way of copying a JPanel's Graphic2D instance to make a Graphic2D for a BufferedImage?
[英]Drawing multiple graphic2d components into JPanel
我已经阅读了很多有关绘制Graphics2D组件并将其添加到JPanel / JFrame的教程,但是我找不到如何简单地将多个这些组件添加到一个JPanel中的教程。 我下面的代码仅添加了1个组件(行),而我找不到为什么无法添加更多组件。
我究竟做错了什么?
期望的行为:应该有3条红线。
我的整个代码:
package Examples;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example1 extends JFrame {
private final JPanel panel;
public Example1() {
// jpanel with graphics
panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panel.setBackground(Color.WHITE);
add(panel);
// adding lines to jpanel
AddMyLine(); // 1st: this works well
AddMyLine(); // 2nd: this doesn't work
AddMyLine(); // 3rd: this doesn't work
setLayout(new FlowLayout(FlowLayout.LEFT));
setSize(250, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLocationRelativeTo(null);
}
// add new line to jpanel
private void AddMyLine() {
MyLine c = new MyLine();
System.out.println(c);
panel.add(c);
}
// line component
private class MyLine extends JComponent {
public MyLine() {
setPreferredSize(new Dimension(200, 200));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.red);
g2d.setStroke(new BasicStroke(1));
int x1 = (int)Math.round(Math.random()*200);
int y1 = (int)Math.round(Math.random()*200);
int x2 = (int)Math.round(Math.random()*200);
int y2 = (int)Math.round(Math.random()*200);
g2d.drawLine(x1,y1,x2,y2);
}
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Example1();
}
});
}
}
您的MyLine类不应是Swing组件,因此不应扩展JComponent。 相反,它应该是一个逻辑实体,并且实际上可以是实现Shape的对象(例如Line2D),也可以是您自己的完整类,但是应该知道如何绘制自身,即,如果它不实现Shape,那么它应该具有其他类可以调用的某种类型的draw(Graphics2D g)
方法。 我认为相反,您应该扩展面板的JPanel类,以覆盖其paintComponent
方法,为它提供一个集合来容纳添加到其中的任何MyLine项目,并在paintComponent中绘制MyLine项目。
其他选项包括直接绘制到BufferedImage上,然后在JPanel的paintComponent方法中显示该BufferedImage。 这对于静态图像非常有用,但对于需要更改或移动的图像则不好。
例如,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class DrawChit extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private List<Shape> shapes = new ArrayList<>();
public DrawChit() {
setBackground(Color.white);
}
public void addShape(Shape shape) {
shapes.add(shape);
repaint();
}
@Override // make it bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Shape shape : shapes) {
g2.draw(shape);
}
}
private static void createAndShowGui() {
DrawChit drawChit = new DrawChit();
drawChit.addShape(new Line2D.Double(10, 10, 100, 100));
drawChit.addShape(new Ellipse2D.Double(120, 120, 200, 200));
JFrame frame = new JFrame("DrawChit");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(drawChit);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
或使用我自己的MyDrawable类的示例,该类生成一个如下所示的GUI:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
@SuppressWarnings("serial")
public class DrawChit extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private List<MyDrawable> drawables = new ArrayList<>();
public DrawChit() {
setBackground(Color.white);
}
public void addMyDrawable(MyDrawable myDrawable) {
drawables.add(myDrawable);
repaint();
}
@Override
// make it bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (MyDrawable myDrawable : drawables) {
myDrawable.draw(g2);
}
}
public void clearAll() {
drawables.clear();
repaint();
}
private static void createAndShowGui() {
final List<MyDrawable> myDrawables = new ArrayList<>();
myDrawables.add(new MyDrawable(new Line2D.Double(100, 40, 400, 400),
Color.red, new BasicStroke(40)));
myDrawables.add(new MyDrawable(new Ellipse2D.Double(50, 10, 400, 400),
Color.blue, new BasicStroke(18)));
myDrawables.add(new MyDrawable(new Rectangle2D.Double(40, 200, 300, 300),
Color.cyan, new BasicStroke(25)));
myDrawables.add(new MyDrawable(new RoundRectangle2D.Double(75, 75, 490, 450, 40, 40),
Color.green, new BasicStroke(12)));
final DrawChit drawChit = new DrawChit();
JFrame frame = new JFrame("DrawChit");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(drawChit);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
int timerDelay = 1000;
new Timer(timerDelay, new ActionListener() {
private int drawCount = 0;
@Override
public void actionPerformed(ActionEvent e) {
if (drawCount >= myDrawables.size()) {
drawCount = 0;
drawChit.clearAll();
} else {
drawChit.addMyDrawable(myDrawables.get(drawCount));
drawCount++;
}
}
}).start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyDrawable {
private Shape shape;
private Color color;
private Stroke stroke;
public MyDrawable(Shape shape, Color color, Stroke stroke) {
this.shape = shape;
this.color = color;
this.stroke = stroke;
}
public Shape getShape() {
return shape;
}
public Color getColor() {
return color;
}
public Stroke getStroke() {
return stroke;
}
public void draw(Graphics2D g2) {
Color oldColor = g2.getColor();
Stroke oldStroke = g2.getStroke();
g2.setColor(color);
g2.setStroke(stroke);
g2.draw(shape);
g2.setColor(oldColor);
g2.setStroke(oldStroke);
}
public void fill(Graphics2D g2) {
Color oldColor = g2.getColor();
Stroke oldStroke = g2.getStroke();
g2.setColor(color);
g2.setStroke(stroke);
g2.fill(shape);
g2.setColor(oldColor);
g2.setStroke(oldStroke);
}
}
您不应该通过添加组件来画线。 组件是面板,按钮等。
请参阅本教程,了解如何使用Graphics2D进行绘制: https : //docs.oracle.com/javase/tutorial/2d/geometry/primitives.html
您的代码添加了三个组件,但是面板不够大,无法显示其他两个组件
panel.setPreferredSize(new Dimension(200, 600));
setSize(250, 800);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.