理解困难 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 以了解执行此操作的两种常用方法:

  1. 保留要绘制的对象列表,然后在每次重新绘制组件时循环访问该列表。
  2. 将对象直接绘制到 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)); }