【问题标题】:JFrame graphics ignores the first few rendersJFrame 图形忽略前几个渲染
【发布时间】:2020-10-04 00:26:16
【问题描述】:

这是查看错误的最小代码:

import javax.swing.*;
import java.awt.*;

public class Main1 extends JFrame {
    static Main1 main;
    public Main1() {
        super("app");
    }

    public static void main(String[] args) {
        main = new Main1();
        main.setBounds(300, 300, 800, 500);
        main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        main.setVisible(true);
        Graphics g = main.getGraphics();
        for(int i = 0; i < 100; i++){
            g.setColor(new Color(255, 0, 0));
            g.fillRect(0, 0, 800, 500);
        }
    }
}

如果我在“for”循环中使用 100,则框架似乎没有着色,但 200 个循环足以着色。

我想制作一个帧很少更改的应用程序,但是这个功能会破坏代码的质量,因为我必须制作许多虚拟帧。

【问题讨论】:

  • 这不是你做 Swing 图形的方式。通过在组件上调用 .getGraphics() 来获取 Graphics 对象会给您一个短暂的不稳定且有时为空的对象。而是使用 JVM 根据教程提供的 Graphics 对象在 JPanel 的 paintComponent 方法中进行绘制。
  • 另外,如果您只想设置 JFrame 的背景颜色,那么只需在构造函数的 contentPane 上调用 setBackground(...) 即可。
  • 欢迎来到 SO! +1 用于最小的、可重现的示例,这对我们很有帮助。我相信custom painting 上的 Swing 教程可能对您有用。另外,我看到您将 for 循环迭代称为“帧”。请注意,for 循环不会导致不同的“帧”。它运行得太快了。您需要使用Swing timer 才能制作任何动画。

标签: java swing graphics jframe


【解决方案1】:
public static void main(String[] args) {
    main = new Main1();
    main.setBounds(300, 300, 800, 500);
    main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    main.setVisible(true);
    Graphics g = main.getGraphics();
    for(int i = 0; i < 100; i++){
        g.setColor(new Color(255, 0, 0));
        g.fillRect(0, 0, 800, 500);
    }
}

这不是你制作 Swing 图形的方式。通过在组件上调用 .getGraphics() 来获取 Graphics 对象会为您提供一个短暂的不稳定且有时为 null 的对象。比如创建的JFrame渲染需要一些时间,如果你调用getGraphics()在渲染之前尝试使用它,对象可能为null,肯定不会wokr。

而是使用 JVM 根据教程提供的 Graphics 对象在 JPanel 的 paintComponent 方法中进行绘制:

public class MainPanel extends JPanel {

    public MainPanel {
        setPreferredSize(new Dimension(800, 500)));
        setBackground(new Color(255, 0, 0)); // if you just want to set background
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        // use g here do do your drawing
    }

}

然后像这样使用它:

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        JFrame frame = new JFrame("GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new MainPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    });
}  

教程:Lesson: Performing Custom Painting

是的,如果您想驱动一个简单的动画,请使用Swing Timer 来帮助驱动它:

public class MainPanel extends JPanel {
    private int x = 0;
    private int y = 0;

    public MainPanel {
        setPreferredSize(new Dimension(800, 500)));
        setBackground(new Color(255, 0, 0)); // if you just want to set background
        
        // timer code:
        int timerDelay = 15;
        new Timer(timerDelay, ()-> {
            x += 4;
            y += 4;
            repaint();
        }).start();
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        // use g here do do your drawing
        g.setColor(Color.BLUE);
        g.drawRect(x, y, 20, 20);
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 2020-08-20
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多