我的重写绘制方法没有被调用
我有一个 JPanel 旨在充当我的游戏的 HUD,自然地,我已经重写了绘制方法来执行我自己的自定义显示,这确实被调用,但仅在调整大小或最大化、最小化框架时调用,而不是在我的游戏循环告诉它重新绘制()。这对我来说似乎特别奇怪,因为我的另外两个面板被重新粉刷得很好。
这是我的 HUD 类:
package base;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class HUD extends JPanel {
private Shiphud[] shiphuds;
public HUD(Ship[] ships) {
shiphuds = new Shiphud[ships.length];
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
for (int i = 0; i < shiphuds.length; i++) {
shiphuds[i] = new Shiphud(ships[i]);
this.add(shiphuds[i]);
}
}
@Override
public void paint(Graphics g) {
for (int i = 0; i < shiphuds.length; i++) {
shiphuds[i].repaint();
}
}
public void run() {
repaint();
}
private class Shiphud extends JPanel {
private Ship ship;
public Shiphud(Ship ship) {
this.ship = ship;
}
@Override
public void paint(Graphics g) {
if (ship != null) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
int fullbar = (int) (this.getWidth() * 0.8);
g.setColor(Color.GREEN);
g.fillRoundRect(getWidth() / 10, getHeight() / 10,
(int) ((ship.energy / 1000) * fullbar), getHeight() / 6, 10, 10);
g.setColor(Color.blue);
g.fillRoundRect(getWidth() / 10, (int) (getHeight() * 0.4),
(int) ((ship.fuel / 1000) * fullbar), getHeight() / 6, 10, 10);
g.setColor(Color.YELLOW);
g.fillRoundRect(getWidth() / 10, (int) (getHeight() * 0.6),
(int) ((ship.ammo / 1000) * fullbar), getHeight() / 6, 10, 10);
g.setColor(Color.MAGENTA);
g.fillRoundRect(getWidth() / 10, (int) (getHeight() * 0.8),
(int) ((ship.special / 1000) * fullbar), getHeight() / 6, 10, 10);
System.out.println("here" + System.currentTimeMillis());
}
}
}
}
它在我的游戏类更新中与我的其他两个面板一起被调用,
public void update() {
...
display.run();
display2.run();
hud.run();
}
它们被我的 JFrame 调用
public void runFrame() {
Thread thread = new Thread() {
@Override
public void run() {
gameLoop();
}
};
thread.start();
}
public void gameLoop() {
while (true) {
long beginTime = System.nanoTime();
game.update();
long timeTaken = System.nanoTime() - beginTime;
long timeLeft = (UPDATE_PERIOD - timeTaken) / 1000000; // in milliseconds
if (timeLeft < 10) {
timeLeft = 10; // set a minimum
}
try {
// Provides the necessary delay and also yields control so that other thread can do work.
Thread.sleep(timeLeft);
} catch (InterruptedException ex) {
}
}
}
长期以来一直在尝试解决这个问题,但我只是不明白,任何帮助都是高度赞赏
I have a JPanel that is meant to act as a HUD for my game, naturally, I have overridden the paint method to do my own custom display, this does get called, but only upon resizing or maximizing, minimizing the frame, and not when my game loop tells it to repaint(). It seems particularly strange to me on account of my two other panels being repainted completely fine.
Here is my HUD class:
package base;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class HUD extends JPanel {
private Shiphud[] shiphuds;
public HUD(Ship[] ships) {
shiphuds = new Shiphud[ships.length];
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
for (int i = 0; i < shiphuds.length; i++) {
shiphuds[i] = new Shiphud(ships[i]);
this.add(shiphuds[i]);
}
}
@Override
public void paint(Graphics g) {
for (int i = 0; i < shiphuds.length; i++) {
shiphuds[i].repaint();
}
}
public void run() {
repaint();
}
private class Shiphud extends JPanel {
private Ship ship;
public Shiphud(Ship ship) {
this.ship = ship;
}
@Override
public void paint(Graphics g) {
if (ship != null) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
int fullbar = (int) (this.getWidth() * 0.8);
g.setColor(Color.GREEN);
g.fillRoundRect(getWidth() / 10, getHeight() / 10,
(int) ((ship.energy / 1000) * fullbar), getHeight() / 6, 10, 10);
g.setColor(Color.blue);
g.fillRoundRect(getWidth() / 10, (int) (getHeight() * 0.4),
(int) ((ship.fuel / 1000) * fullbar), getHeight() / 6, 10, 10);
g.setColor(Color.YELLOW);
g.fillRoundRect(getWidth() / 10, (int) (getHeight() * 0.6),
(int) ((ship.ammo / 1000) * fullbar), getHeight() / 6, 10, 10);
g.setColor(Color.MAGENTA);
g.fillRoundRect(getWidth() / 10, (int) (getHeight() * 0.8),
(int) ((ship.special / 1000) * fullbar), getHeight() / 6, 10, 10);
System.out.println("here" + System.currentTimeMillis());
}
}
}
}
It gets called in my Game classes update along with my other two panels
public void update() {
...
display.run();
display2.run();
hud.run();
}
Which gets called by my JFrame
public void runFrame() {
Thread thread = new Thread() {
@Override
public void run() {
gameLoop();
}
};
thread.start();
}
public void gameLoop() {
while (true) {
long beginTime = System.nanoTime();
game.update();
long timeTaken = System.nanoTime() - beginTime;
long timeLeft = (UPDATE_PERIOD - timeTaken) / 1000000; // in milliseconds
if (timeLeft < 10) {
timeLeft = 10; // set a minimum
}
try {
// Provides the necessary delay and also yields control so that other thread can do work.
Thread.sleep(timeLeft);
} catch (InterruptedException ex) {
}
}
}
Been trying to figure this for a long time now, and I just don't get it, any help would be highly appreaciated
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不要重写 Swing 中的
paint
方法。而是重写
paintComponent
。然后,您不必为子组件调用
paint
或repaint
- 这将自动完成。Do not override the
paint
method in Swing.Override
paintComponent
instead.Then you don't have to call
paint
orrepaint
for your subcomponents - this will be done automatically.JPanel 是一个轻量级容器。 为了让其子级被绘制,您需要调用 super.paint (g) 在重写的paint()方法中。
JPanel is a lightweight container. In order for it's children to get painted, you need to call super.paint(g) in the overridden paint() method.
好吧,伙计们,谢谢你们的帮助,最后它需要结合你们所有的解决方案才能让它工作,最让我惊讶的是它需要是一个 JComponent 才能正确地重新绘制。这是有效的代码,
干杯伙计们!
Alright guys, thanks for your help, in the end it required a combination of all your solutions to get it to work, what surprised me most was that it needed to be a JComponent for it to repaint properly. Here's the code that works
Cheers dudes!