[英]Why is the repaint() method not calling my paintComponent() method?
我试图从教程中复制 repaint() 和 paintComponent() 方法。 在我复制这两个方法后,我的 paintComponent 没有被调用,所以矩形没有被显示。 这是我的代码:
public class Main {
GameWindow gw;
Main() {
gw = new GameWindow();
}
void start() {
gw.setWindow();
}
public static void main(String[] args) {
new Main().start();
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameWindow extends JPanel implements Runnable {
final int ORIGINAL_TILE_SIZE = 16;
final int SCALE = 3;
final int TILE_SIZE = ORIGINAL_TILE_SIZE * SCALE;
final int MAX_SCREEN_COLUMNS = 16;
final int MAX_SCREEN_ROWS = 12;
final int SCREEN_WIDTH = TILE_SIZE * MAX_SCREEN_COLUMNS;
final int SCREEN_HEIGHT = TILE_SIZE * MAX_SCREEN_ROWS;
Thread animation;
void setWindow() {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.setTitle("Avontuur");
window.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
window.getContentPane().setBackground(Color.black);
ImageIcon icon = new ImageIcon("C:\\Users\\Rick\\Desktop\\Star.png");
window.setIconImage(icon.getImage());
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
startAnimation();
}
void startAnimation() {
animation = new Thread(this);
animation.start();
}
@Override
public void run() {
while (animation != null) {
update();
repaint();
}
}
public void update() {
}
public void paintComponent(final Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.white);
g2.fillRect(100, 100, TILE_SIZE, TILE_SIZE);
g2.dispose();
}
}
我已经尝试过 stackOverflow 的一些解决方案,但它们没有用,或者与我的问题无关。 现在上面的代码是我自己使用视频尝试的,但是在方法中使用 println 后我发现它没有被调用。 看完教程后,我希望它能工作,但没有。 有谁知道我该如何解决这个问题? 提前致谢!
Swing 是单线程的 - 永远不会阻塞事件调度线程长时间运行或阻塞操作
Swing 不是线程安全的 - 永远不要更新 UI 或 state UI 依赖于事件调度线程上下文之外的任何内容。
有关详细信息,请参阅Swing中的并发。
Swing 使用被动渲染引擎 - 您无法控制绘画过程,您需要在其预期的设计/工作流程中工作,请参阅AWT 中的绘画和 Swing以及执行自定义绘画以获取更多详细信息。
那么,解决方案是什么? 在最简单的形式中,使用Swing Timer
,例如......
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePane extends JPanel {
final int ORIGINAL_TILE_SIZE = 16;
final int SCALE = 3;
final int TILE_SIZE = ORIGINAL_TILE_SIZE * SCALE;
final int MAX_SCREEN_COLUMNS = 16;
final int MAX_SCREEN_ROWS = 12;
final int SCREEN_WIDTH = TILE_SIZE * MAX_SCREEN_COLUMNS;
final int SCREEN_HEIGHT = TILE_SIZE * MAX_SCREEN_ROWS;
private Timer timer;
@Override
public Dimension getPreferredSize() {
return new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT);
}
@Override
public void addNotify() {
super.addNotify();
if (timer != null) {
timer.stop();
}
timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
update();
}
});
timer.start();
}
@Override
public void removeNotify() {
super.removeNotify();
if (timer != null) {
timer.stop();
}
}
public void update() {
System.out.println("Updatey update");
repaint();
}
public void paintComponent(final Graphics g) {
super.paintComponent(g);
System.out.println("Painty paint paint");
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(Color.white);
g2.fillRect(100, 100, TILE_SIZE, TILE_SIZE);
g2.dispose();
}
}
}
您现在应该看到一堆文本被打印到控制台。
另外 - 你可能不会,我已经对你的代码进行了一些结构更改,没有理由让基于 class 的JPanel
创建它自己的 window(或者如果你真的想这样做,我会创建一个static
方法来做它,但后来我会质疑为什么)。
哦,还有 DontKnowMuchBut Getting Better 在评论中所说的!
这是您的代码的特定矩形问题,我不会提及其他事情,因为不在问题中,您没有将 GameWindow 本身添加为 JFrame 的组件,并且您没有在任何地方调用您的 paintComponent 方法,我把它放在更新中它工作正常,但我担心你的代码会阻塞,你将无法移动 window 并与之交互,因为你总是在你的 while 语句中一遍又一遍地调用更新/重绘。
编辑:正如评论中的那个人所说,我们不能直接调用 paintcomponent,所以我修复了。
void setWindow() {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.setTitle("Avontuur");
window.add(GameWindow.this);
window.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
window.getContentPane().setBackground(Color.black);
ImageIcon icon = new ImageIcon("C:\\Users\\Rick\\Desktop\\Star.png");
window.setIconImage(icon.getImage());
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
startAnimation();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.