我已经阅读了很多关于绘制 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);
}
}
关于java - 将多个 graphic2d 组件绘制到 JPanel 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31033359/