英文:
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("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);
}
}
}
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 < 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(() -> {
JFrame frame = new JFrame("GUI");
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, ()-> {
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);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论