JFrame图形忽略了最开始的几次渲染。

huangapple go评论86阅读模式
英文:

JFrame graphics ignores the first few renders

问题

这里是一个查看错误的最小代码示例:

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 次循环足以进行着色。

我想创建一个应用程序,其中窗口很少更改,但这个特性会破坏代码的质量,因为我不得不创建许多虚拟窗口。

英文:

Here is a minimal code to see the bug:

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

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

    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 &lt; 100; i++){
            g.setColor(new Color(255, 0, 0));
            g.fillRect(0, 0, 800, 500);
        }
    }
}

If i use 100 in the "for" cycle, the frame appears not to be colored, but 200 loops is enough to color it.

I want to make an application where frames change rarely, but this feature ruins the quality of code because I have to make a number of dummy frames.

答案1

得分: 5

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

    public Main1() {
        setPreferredSize(new Dimension(800, 500));
        setBackground(new Color(255, 0, 0)); // 如果只想设置背景色
        
        // 定时器代码:
        int timerDelay = 15;
        new Timer(timerDelay, () -> {
            x += 4;
            y += 4;
            repaint();
        }).start();
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        // 在这里使用 g 进行绘制
        g.setColor(Color.BLUE);
        g.drawRect(x, y, 20, 20);
    }
}

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

教程:教程:执行自定义绘图

如果你想要制作简单的动画,可以使用 Swing 定时器 来帮助驱动,如下所示:

public class Main1 extends JPanel {
    // ...(略去前面的内容)

    public Main1() {
        // ...(略去中间的内容)
        
        // 定时器代码:
        int timerDelay = 15;
        new Timer(timerDelay, () -> {
            x += 4;
            y += 4;
            repaint();
        }).start();
    }

    // ...(略去后面的内容)
}
英文:
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 &lt; 100; i++){
        g.setColor(new Color(255, 0, 0));
        g.fillRect(0, 0, 800, 500);
    }
}

This is not how you do Swing graphics. Getting a Graphics object by calling .getGraphics() on a component gives you a short-lived unstable and sometimes null object. For instance, it takes some time for the created JFrame to render, and if you call getGraphics() and try to use it prior to rendering, the object may be null, and certainly won't wokr.

Instead paint within a JPanel's paintComponent method using the Graphics object given by the JVM as per the tutorials:

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
    }

}

and then use it like so:

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

Tutorial: Lesson: Performing Custom Painting

And yes, if you want to drive a simple animation, use a Swing Timer to help drive it like so:

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, ()-&gt; {
            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);
    }

}

huangapple
  • 本文由 发表于 2020年10月4日 08:26:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/64190150.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定