理解困难 java swing
understanding difficulties java swing
我正在尝试通过单击 JMenu 在 JPanel 上绘制随机(尚未)圆圈。
我使用 JTextField(并且必须保留它)用于某些输出。
这是我的 Class:
class RandomDrawer extends JPanel implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//double x = Math.random();
//double y = Math.random();
Random generator = new Random();
int x = generator.nextInt(100)+1;
int y = generator.nextInt(100)+1;
//System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x: %d y: %d", x, y));
Graphics2D gg = (Graphics2D) canvas.getGraphics();
gg.setColor(Color.BLACK);
gg.drawOval(50, 50, 50, 50);
}
}
只要我让线
status.setText(String.format("rnd draw x: %d y: %d", x, y));
留在那儿,我什么也没画。没有它我得到我的圈子,我不确定问题是什么。想不通为什么什么都画不出来
非常感谢
编辑:
您好,我想了解给定的信息。
遗憾的是我必须使用 Graphics2D class 进行绘制,所以我想我不能使用形状进行绘制。所以我试了这个,遗憾的是它还不会画,你能给我一些提示吗?
我尝试创建一个新的 class DrawShape,我的想法是我可以跟踪那些对象。
根据我的理解,现在应该有一个绘制的椭圆形
gg.drawOval(100,100,100,100);
谢谢。
class DrawShape {
public DrawShape(String string) {
// TODO Auto-generated constructor stub
}
}
class RandomDrawer extends JPanel implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
private List<DrawShape> shapes = new ArrayList<DrawShape>();
public void addShape(DrawShape s) {
shapes.add(s);
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D gg = (Graphics2D) g;
gg.setColor(Color.BLACK);
gg.drawOval(100, 100, 100, 100);
}
@Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
if (e.getActionCommand()==("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x:%d y:%d ", x, y));
DrawShape circle = new DrawShape("Circle");
addShape(circle);
int count = shapes.size();
System.out.printf("objects in array: %d\n", count);
}
else if (e.getActionCommand()==("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//Graphics2D gg = (Graphics2D) canvas.getGraphics();
//gg.setColor(Color.BLACK);
//gg.drawRect(x, y, generator.nextInt(x), generator.nextInt(y));
}
}
}
Graphics2D gg = (Graphics2D) canvas.getGraphics();
不要使用getGraphics() 方法进行绘画。这幅画是暂时的。例如,如果您调整框架的大小,它将丢失。
相反,您需要覆盖面板的 paintComponent()
方法。
如果要绘制多个对象,则需要跟踪每个对象。查看 Custom Painting Approaches 以了解执行此操作的两种常用方法:
- 保留要绘制的对象列表,然后在每次重新绘制组件时循环访问该列表。
- 将对象直接绘制到 BufferedImage,然后只绘制 BufferedImage。
该示例绘制矩形。基本上你需要像 addRectangle(...)
这样的方法来添加一个新的对象来绘制。因此,每次单击按钮时,都会添加新的随机形状。
据推测,您的问题是由 setText()
调用以某种意想不到的方式修改 Graphics
对象引起的。在您自己的代码中使用 getGraphics()
很少是合适的。相反,用给你的 Graphics
作画。
无论如何,你的方法是有缺陷的。如果您设法只在 GUI 组件上绘制一次,就像您尝试做的那样,那么当下次重新绘制该组件时,您绘制的任何内容都会消失。重绘的发生可能有多种原因,其中许多与程序自身的行为无关。
您需要做的是存储某种数据,组件的 paintComponent()
方法每次 都将依赖这些数据来执行您的自定义绘制。因此,您需要覆盖要在其上绘制圆的组件的 paintComponent()
方法。例如,您可以创建一个 class 来记录一个圆的所有需要的绘图细节,并将这些对象的 List
作为成员变量提供给 RandomDrawer
。动作侦听器适当地操作该列表并安排重新绘制,并且 paintComponent()
被覆盖以执行实际绘制。
绘画等事件驱动。如果需要重绘组件的一部分,则会调用其 paintComponent
方法。
这意味着您需要一个组件来了解如何绘制,例如:
public class DrawShape {
public final String text;
public final Color color;
public final Shape shape;
public DrawShape(String text, Color color, Shape shape) {
this.text = text;
this.color = color;
this.shape = shape;
}
}
public class CanvasWithShapes extends JPanel {
private List<DrawShape> shapes = new ArrayList<>();
public void addShape(DrawShape shape) {
shapes.add(shape);
}
@Override
public void paintComponent(Graphics g) {
final Graphics2D gg = (Graphics2D) g;
// Java 8: shapes.stream().forEach((shape) -> gg.draw(shape));
for (DrawShape drawShape : shapes) {
gg.setColor(drawShape.color);
gg.draw(drawShape.shape);
Rectangle bounds = shape.getBounds();
gg.drawString(shape.text, bounds.x+ 10, bounds.y + 20);
}
}
}
然后只需添加稍后重绘的形状即可。
Shape oval = ...;
c.add(oval);
c.repaint(50L); // A bit later
更详细
A Shape 有许多有趣的实现,例如矩形和椭圆形。
Graphics2D 可以绘制和填充 Shape。所以在你的情况下,添加这样一个形状是理想的。也许连同颜色和文字。所以我用你的 DrawShape class 来保存这些属性。
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
if (e.getActionCommand().equals("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x:%d y:%d ", x, y));
int w = generator.nextInt(100) + 10;
int h = w;
Shape circle = new Ellipse2D.Double(x, y, w, h);
addShape(new DrawShape(text, Color.BLACK, circle));
int count = shapes.size();
System.out.printf("objects in array: %d\n", count);
} else if (e.getActionCommand().equals("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
generator.nextInt(y));
int w = generator.nextInt(100) + 10;
int h = generator.nextInt(100) + 10;
形状矩形 = Rectangle2D.Double(x, y, w, h)
addShape(new DrawShape(text, Color.BLACK, rect));
}
我正在尝试通过单击 JMenu 在 JPanel 上绘制随机(尚未)圆圈。 我使用 JTextField(并且必须保留它)用于某些输出。 这是我的 Class:
class RandomDrawer extends JPanel implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//double x = Math.random();
//double y = Math.random();
Random generator = new Random();
int x = generator.nextInt(100)+1;
int y = generator.nextInt(100)+1;
//System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x: %d y: %d", x, y));
Graphics2D gg = (Graphics2D) canvas.getGraphics();
gg.setColor(Color.BLACK);
gg.drawOval(50, 50, 50, 50);
}
}
只要我让线
status.setText(String.format("rnd draw x: %d y: %d", x, y));
留在那儿,我什么也没画。没有它我得到我的圈子,我不确定问题是什么。想不通为什么什么都画不出来
非常感谢
编辑:
您好,我想了解给定的信息。
遗憾的是我必须使用 Graphics2D class 进行绘制,所以我想我不能使用形状进行绘制。所以我试了这个,遗憾的是它还不会画,你能给我一些提示吗?
我尝试创建一个新的 class DrawShape,我的想法是我可以跟踪那些对象。
根据我的理解,现在应该有一个绘制的椭圆形
gg.drawOval(100,100,100,100);
谢谢。
class DrawShape {
public DrawShape(String string) {
// TODO Auto-generated constructor stub
}
}
class RandomDrawer extends JPanel implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
private List<DrawShape> shapes = new ArrayList<DrawShape>();
public void addShape(DrawShape s) {
shapes.add(s);
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D gg = (Graphics2D) g;
gg.setColor(Color.BLACK);
gg.drawOval(100, 100, 100, 100);
}
@Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
if (e.getActionCommand()==("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x:%d y:%d ", x, y));
DrawShape circle = new DrawShape("Circle");
addShape(circle);
int count = shapes.size();
System.out.printf("objects in array: %d\n", count);
}
else if (e.getActionCommand()==("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//Graphics2D gg = (Graphics2D) canvas.getGraphics();
//gg.setColor(Color.BLACK);
//gg.drawRect(x, y, generator.nextInt(x), generator.nextInt(y));
}
}
}
Graphics2D gg = (Graphics2D) canvas.getGraphics();
不要使用getGraphics() 方法进行绘画。这幅画是暂时的。例如,如果您调整框架的大小,它将丢失。
相反,您需要覆盖面板的 paintComponent()
方法。
如果要绘制多个对象,则需要跟踪每个对象。查看 Custom Painting Approaches 以了解执行此操作的两种常用方法:
- 保留要绘制的对象列表,然后在每次重新绘制组件时循环访问该列表。
- 将对象直接绘制到 BufferedImage,然后只绘制 BufferedImage。
该示例绘制矩形。基本上你需要像 addRectangle(...)
这样的方法来添加一个新的对象来绘制。因此,每次单击按钮时,都会添加新的随机形状。
据推测,您的问题是由 setText()
调用以某种意想不到的方式修改 Graphics
对象引起的。在您自己的代码中使用 getGraphics()
很少是合适的。相反,用给你的 Graphics
作画。
无论如何,你的方法是有缺陷的。如果您设法只在 GUI 组件上绘制一次,就像您尝试做的那样,那么当下次重新绘制该组件时,您绘制的任何内容都会消失。重绘的发生可能有多种原因,其中许多与程序自身的行为无关。
您需要做的是存储某种数据,组件的 paintComponent()
方法每次 都将依赖这些数据来执行您的自定义绘制。因此,您需要覆盖要在其上绘制圆的组件的 paintComponent()
方法。例如,您可以创建一个 class 来记录一个圆的所有需要的绘图细节,并将这些对象的 List
作为成员变量提供给 RandomDrawer
。动作侦听器适当地操作该列表并安排重新绘制,并且 paintComponent()
被覆盖以执行实际绘制。
绘画等事件驱动。如果需要重绘组件的一部分,则会调用其 paintComponent
方法。
这意味着您需要一个组件来了解如何绘制,例如:
public class DrawShape {
public final String text;
public final Color color;
public final Shape shape;
public DrawShape(String text, Color color, Shape shape) {
this.text = text;
this.color = color;
this.shape = shape;
}
}
public class CanvasWithShapes extends JPanel {
private List<DrawShape> shapes = new ArrayList<>();
public void addShape(DrawShape shape) {
shapes.add(shape);
}
@Override
public void paintComponent(Graphics g) {
final Graphics2D gg = (Graphics2D) g;
// Java 8: shapes.stream().forEach((shape) -> gg.draw(shape));
for (DrawShape drawShape : shapes) {
gg.setColor(drawShape.color);
gg.draw(drawShape.shape);
Rectangle bounds = shape.getBounds();
gg.drawString(shape.text, bounds.x+ 10, bounds.y + 20);
}
}
}
然后只需添加稍后重绘的形状即可。
Shape oval = ...;
c.add(oval);
c.repaint(50L); // A bit later
更详细
A Shape 有许多有趣的实现,例如矩形和椭圆形。 Graphics2D 可以绘制和填充 Shape。所以在你的情况下,添加这样一个形状是理想的。也许连同颜色和文字。所以我用你的 DrawShape class 来保存这些属性。
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
if (e.getActionCommand().equals("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x:%d y:%d ", x, y));
int w = generator.nextInt(100) + 10;
int h = w;
Shape circle = new Ellipse2D.Double(x, y, w, h);
addShape(new DrawShape(text, Color.BLACK, circle));
int count = shapes.size();
System.out.printf("objects in array: %d\n", count);
} else if (e.getActionCommand().equals("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
generator.nextInt(y)); int w = generator.nextInt(100) + 10; int h = generator.nextInt(100) + 10; 形状矩形 = Rectangle2D.Double(x, y, w, h) addShape(new DrawShape(text, Color.BLACK, rect)); }