Window 绘制字符串时冻结一次
Window freezes for one time when String is drawn
当我在 Java 中制作 2D 游戏时,出现了一个(至少对我而言)非常奇怪的问题。我提供了一个 运行nable, shortened example 它重现了我的问题。当红色方块的x坐标在100和120之间时应该在正方形上方绘制字符串 "Sample Text"。但是,如果您 运行 代码,您会看到 window 完全冻结 几秒钟。滞后之后,您可以毫无问题地越过该区域,并且将显示文本。仅当程序在正方形上方绘制字符串时才会出现此问题。如果我更改代码,使红色方块上方只出现另一个方块,则不会出现延迟。 (我在我的代码中评论了)
如有任何帮助,我们将不胜感激。
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JApplet;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
public class MyExample extends JApplet {
int x = 10;
int y = 150;
public void init() {
setFocusable(true);
requestFocus();
Action right = new moveRight();
Action left = new moveLeft();
JRootPane rootPane = getRootPane();
rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
rootPane.getActionMap().put("right", right);
rootPane.getActionMap().put("left", left);
getContentPane().add(new Paint());
}
protected class moveRight extends AbstractAction {
public void actionPerformed(ActionEvent e) {
x+=3;
repaint();
}
}
protected class moveLeft extends AbstractAction {
public void actionPerformed(ActionEvent e) {
x-=3;
repaint();
}
}
class Paint extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.RED);
g.fillRect(x,y,10,10);
g.setColor(Color.BLACK);
g.drawLine(100,100,100,200);
g.drawLine(129,100,129,200);
if(x>100&&x<120) {
g.setFont(new Font("TimesRoman", Font.PLAIN, 15));
g.setColor(Color.BLACK);
g.drawString("Sample Text",x-30,y-25);
//g.fillRect(x,y-15,10,10); - This work fine if you remove the g.setFont and the drawString
}
}
}
}
这与以下事实有关:您尝试在 paintComponent
方法中加载字体,而底层 API 尝试在绘制字体之前加载字体及其详细信息。
我确实认为您可以使用诸如...
之类的方法来预缓存字体
class Paint extends JPanel {
private Font paintFont;
public Paint() {
paintFont = new Font("TimesRoman", Font.PLAIN, 15);
setFont(paintFont);
}
但在我的测试中,这仍然不起作用,我实际上最终做的是添加对 getFontMetrics
的调用,这似乎迫使 API 加载字体并且它是属性存入内存,使其立即呈现,例如
class Paint extends JPanel {
private Font paintFont;
public Paint() {
paintFont = new Font("TimesRoman", Font.PLAIN, 15);
setFont(paintFont);
getFontMetrics(paintFont);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(x, y, 10, 10);
g.setColor(Color.BLACK);
g.drawLine(100, 100, 100, 200);
g.drawLine(129, 100, 129, 200);
if (x > 100 && x < 120) {
System.out.println("...");
//g.setFont(paintFont);
g.setColor(Color.BLACK);
g.drawString("Sample Text", x - 30, y - 25);
//g.fillRect(x,y-15,10,10); - This work fine if you remove the g.setFont and the drawString
}
}
}
现在,这会使您的应用程序加载速度稍微慢一些,但是当您将字体加载移出绘制周期后,它会运行更快
在我的系统上 TimesRoman
不存在。
我使用 Times New Roman
没问题。我还尝试了其他几种字体,它们都没有问题。所以我想指定一个无效的字体名称会导致打嗝?
我也创建了一次字体并缓存了它:
Font font = new Font("Times New Roman", Font.PLAIN, 15);
然后在绘画中使用的方法:
g.setFont( font );
另外,别忘了 super.paintComponent(g);
这个问题包含我用来在我的机器上列出字体的代码:Java JTextArea font
当我在 Java 中制作 2D 游戏时,出现了一个(至少对我而言)非常奇怪的问题。我提供了一个 运行nable, shortened example 它重现了我的问题。当红色方块的x坐标在100和120之间时应该在正方形上方绘制字符串 "Sample Text"。但是,如果您 运行 代码,您会看到 window 完全冻结 几秒钟。滞后之后,您可以毫无问题地越过该区域,并且将显示文本。仅当程序在正方形上方绘制字符串时才会出现此问题。如果我更改代码,使红色方块上方只出现另一个方块,则不会出现延迟。 (我在我的代码中评论了)
如有任何帮助,我们将不胜感激。
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JApplet;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
public class MyExample extends JApplet {
int x = 10;
int y = 150;
public void init() {
setFocusable(true);
requestFocus();
Action right = new moveRight();
Action left = new moveLeft();
JRootPane rootPane = getRootPane();
rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
rootPane.getActionMap().put("right", right);
rootPane.getActionMap().put("left", left);
getContentPane().add(new Paint());
}
protected class moveRight extends AbstractAction {
public void actionPerformed(ActionEvent e) {
x+=3;
repaint();
}
}
protected class moveLeft extends AbstractAction {
public void actionPerformed(ActionEvent e) {
x-=3;
repaint();
}
}
class Paint extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.RED);
g.fillRect(x,y,10,10);
g.setColor(Color.BLACK);
g.drawLine(100,100,100,200);
g.drawLine(129,100,129,200);
if(x>100&&x<120) {
g.setFont(new Font("TimesRoman", Font.PLAIN, 15));
g.setColor(Color.BLACK);
g.drawString("Sample Text",x-30,y-25);
//g.fillRect(x,y-15,10,10); - This work fine if you remove the g.setFont and the drawString
}
}
}
}
这与以下事实有关:您尝试在 paintComponent
方法中加载字体,而底层 API 尝试在绘制字体之前加载字体及其详细信息。
我确实认为您可以使用诸如...
之类的方法来预缓存字体class Paint extends JPanel {
private Font paintFont;
public Paint() {
paintFont = new Font("TimesRoman", Font.PLAIN, 15);
setFont(paintFont);
}
但在我的测试中,这仍然不起作用,我实际上最终做的是添加对 getFontMetrics
的调用,这似乎迫使 API 加载字体并且它是属性存入内存,使其立即呈现,例如
class Paint extends JPanel {
private Font paintFont;
public Paint() {
paintFont = new Font("TimesRoman", Font.PLAIN, 15);
setFont(paintFont);
getFontMetrics(paintFont);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(x, y, 10, 10);
g.setColor(Color.BLACK);
g.drawLine(100, 100, 100, 200);
g.drawLine(129, 100, 129, 200);
if (x > 100 && x < 120) {
System.out.println("...");
//g.setFont(paintFont);
g.setColor(Color.BLACK);
g.drawString("Sample Text", x - 30, y - 25);
//g.fillRect(x,y-15,10,10); - This work fine if you remove the g.setFont and the drawString
}
}
}
现在,这会使您的应用程序加载速度稍微慢一些,但是当您将字体加载移出绘制周期后,它会运行更快
在我的系统上 TimesRoman
不存在。
我使用 Times New Roman
没问题。我还尝试了其他几种字体,它们都没有问题。所以我想指定一个无效的字体名称会导致打嗝?
我也创建了一次字体并缓存了它:
Font font = new Font("Times New Roman", Font.PLAIN, 15);
然后在绘画中使用的方法:
g.setFont( font );
另外,别忘了 super.paintComponent(g);
这个问题包含我用来在我的机器上列出字体的代码:Java JTextArea font