[英]I've overridden paintComponent(), so why aren't my shapes appearing?
I'm toying around with awt graphics an at first I managed to get everything just as I wanted but after cleaning up my code suddenly nothing other than an empty frame appears with the JPanel inside it.我在玩awt图形,起初我设法得到了我想要的一切,但是在清理我的代码之后突然出现一个空框架,里面有JPanel。
It's probably painfully obvious but I cannot find why my shapes aren't appearing any more.这可能很明显,但我找不到我的形状不再出现的原因。 What am I doing wrong?我究竟做错了什么?
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Game().setVisible(true);
}
});
}
}
public class Game extends JFrame {
static int width = 500;
static int height = 500;
public Game() {
this.setPreferredSize(new Dimension(width, height));
JPanel menuPanel = new JPanel(); // Menypanel
JPanel filmPanel = new JPanel(); // Filmpanel
JPanel gamePanel = new JPanel(); // Spelpanel
gamePanel.setBackground(Color.WHITE);
// Intro texts
Queue<String> intro = new ArrayDeque<>();
intro.add("Welcome to the jungle!");
intro.add("We've got fun and games.");
FadingTextBox introBox = new FadingTextBox(intro);
gamePanel.add(introBox);
getContentPane().add(gamePanel);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
pack();
}
}
This one doesn't appear at all:这个根本没有出现:
class FadingTextBox extends JComponent implements ActionListener {
private RoundRectangle2D rr;
private String text = "";
private float alpha;
private float alphaDelta = 0.05f; // Alpha fade speed
private final int fps = 60; // FPS
private javax.swing.Timer timer = new Timer(1000 / fps, this);
private java.util.Queue<String> textQueue; // Contains lines of texts
public FadingTextBox(java.util.Queue<String> textQueue) {
this.textQueue = textQueue;
this.setFont(new Font("OCR A EXTENDED", Font.BOLD, 24));
int arc = 10;
int height = (int) (Game.height * 0.2);
int width = (int) (Game.width - Game.width * 0.1);
int x = Game.width / 2 - width / 2;
int y = (int) (Game.height - height * 1.5);
rr = new RoundRectangle2D.Double(x, y, width, height, arc, arc);
setText(textQueue.remove());
timer.start();
}
private void setText(String text) {
this.text = text;
}
boolean isRunning() {
return timer.isRunning();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// Set component alpha
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
// Draw RoundRectangle
g2.setBackground(Color.DARK_GRAY);
g2.fill(rr);
// Draw text
// g2.setColor(Color.BLUE);
final FontMetrics fm = g.getFontMetrics();
Rectangle2D textBounds = fm.getStringBounds(text, g2);
g2.drawString(text, (float) (rr.getCenterX() - (textBounds.getWidth() / 2)), (float) (rr.getCenterY() + textBounds.getHeight() / 2));
}
@Override
public void actionPerformed(ActionEvent e) {
if (alpha >= 0) {
alpha += alphaDelta;
}
if (alpha < 0) {
alpha = 0;
try {
setText(textQueue.remove());
} catch (NoSuchElementException ex) {
timer.stop();
}
alphaDelta *= -1;
} else if (alpha >= 1) {
alpha = 1;
alphaDelta *= -1;
// Sleep 1 sec on full alpha
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
repaint();
}
}
New Take:新拍摄:
public class Game extends JFrame {
...
GameCanvas gameCanvas;
public Game() {
...
gameCanvas = new GameCanvas(); // Spelpanel
getContentPane().add(gameCanvas);
...
pack();
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayDeque;
import java.util.NoSuchElementException;
public class GameCanvas extends Canvas implements Runnable {
private final int fps = 24; // FPS
private RoundRectangle2D rr;
private String text;
private float alpha;
private float alphaDelta = 0.05f; // Alpha fade speed
private javax.swing.Timer timer = new Timer(1000 / fps, a -> repaint());
private java.util.Queue<String> textQueue; // Contains lines of texts
public GameCanvas() {
this.setFont(new Font("OCR A EXTENDED", Font.BOLD, 20));
// Intro texts
textQueue = new ArrayDeque<>();
textQueue.add("Welcome to the jungle!");
textQueue.add("We've got fun and games.");
// RoundRectangle
int arc = 10;
int height = (int) (Game.height * 0.2);
int width = (int) (Game.width - Game.width * 0.1);// (int) (Game.width - Game.width * 0.5);
int x = Game.width / 2 - width / 2 - 10;
int y = (int) (Game.height - height * 1.5);
rr = new RoundRectangle2D.Double(x, y, width, height, arc, arc);
this.text = textQueue.remove();
Thread thread = new Thread(this); // Fade thread
thread.start();
timer.start();
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
// Set component alpha
// g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
// Draw RoundRectangle
g2.setBackground(Color.DARK_GRAY);
g2.fill(rr);
// Draw text
final FontMetrics fm = g2.getFontMetrics();
Rectangle2D textBounds = fm.getStringBounds(text, g2);
g2.setColor(Color.WHITE);
g2.drawString(text, (float) (rr.getCenterX() - (textBounds.getWidth() / 2)), (float) (rr.getCenterY() + textBounds.getHeight() / 2));
g2.setColor(Color.DARK_GRAY);
}
@Override
public void run() {
while (true) {
if (alpha >= 0) {
alpha += alphaDelta;
}
if (alpha < 0) {
alpha = 0;
try {
this.text = textQueue.remove();
} catch (NoSuchElementException ex) {
timer.stop();
}
alphaDelta *= -1;
} else if (alpha >= 1) {
alpha = 1;
alphaDelta *= -1;
// Sleep 1 sec on full alpha
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
It is because you gamePanel
does not have a LayoutManager
(it uses FlowLayout
by default) that fills the panel with the component.这是因为您的gamePanel
没有使用组件填充面板的LayoutManager
(默认情况下使用FlowLayout
)。 In order to see something change it to JPanel gamePanel = new JPanel(new BorderLayout());
为了看到一些东西,把它改成JPanel gamePanel = new JPanel(new BorderLayout());
However, in Timer
's action, you Thread.sleep()
.但是,在Timer
的操作中,您是Thread.sleep()
。 This will freeze the whole GUI since Timer
's action listener runs in the Event Dispatch Thread , which is a Thread
that should not sleep
.这将冻结整个 GUI,因为Timer
的动作侦听器在Event Dispatch Thread中运行,这是一个不应sleep
的Thread
。 Instead, you could use a second Timer
or some kind o flag variables or maybe a SwingWorker
.相反,您可以使用第二个Timer
或某种 o 标志变量或SwingWorker
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.