jframejava中的闪烁
大家好,我正在做一个线程来更新JFrame上的一个球,所以我重新绘制了屏幕。。。然后绘制球并更新其位置。。然后再画一次屏幕。。。画出球和相同的循环。。。这是密码jframejava中的闪烁,java,swing,concurrency,java-2d,Java,Swing,Concurrency,Java 2d,大家好,我正在做一个线程来更新JFrame上的一个球,所以我重新绘制了屏幕。。。然后绘制球并更新其位置。。然后再画一次屏幕。。。画出球和相同的循环。。。这是密码 private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) { Thread t = new Thread() { public void run() { while(true) {
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
Thread t = new Thread()
{
public void run()
{
while(true)
{
repaint();
b2.update(ob,2);
b2.paint(ob.getGraphics());
b2.setT(b2.getT() + 1);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
System.out.println("Error in Sleeping");
}
}
}
};
t.start();
}
但问题是我看不到球。。。屏幕上的油漆总是覆盖着球,球就像在Jframe下一样 如果在EDT(事件调度线程)之外访问GUI组件,则可能会遇到奇怪的问题,相反,如果在EDT中执行长时间运行的任务,则也会遇到问题
有关Java中的GUI线程的更多信息,请参阅帖子如果您想在Swing中使用动画,建议使用的类是
javax.Swing.Timer
。此类允许您定期在事件分派线程上执行操作
- 在SO上发布的消息(在SO上的Swing wiki中链接)
- Swing不是线程安全的,您应该只从事件调度线程的上下文中更新UI组件
- “重新绘制管理器”不控制绘制过程。您可以通过调用
请求进行更新,但在尝试更新显示时,不应直接调用repaint
和update
paint
- 绘制子系统使用的
上下文是一个共享资源,不能保证在绘制周期之间相同,您不应维护对它的引用。您也不应该依赖图形
的结果。此方法能够返回nullJComponent#getGraphics
一些一般规则
SwingWorker
,但考虑到您要做的就是进入一个无限循环,使用SwingUtilities#invokeLater
然后实际使用publish
方法会更容易,这种方法实际上需要更多的工作
您也可以使用线程
,但最终会遇到与使用SwingWorker
simpliset解决方案实际上是一个javax.swing.Timer
public class Blinky {
public static void main(String[] args) {
new Blinky();
}
public Blinky() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BlinkyPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class BlinkyPane extends JPanel {
private JLabel blinkyLabel;
private boolean blink = false;
public BlinkyPane() {
setLayout(new GridBagLayout());
blinkyLabel = new JLabel("I'm blinking here");
blinkyLabel.setBackground(Color.RED);
add(blinkyLabel);
Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
blink = !blink;
if (blink) {
blinkyLabel.setForeground(Color.YELLOW);
} else {
blinkyLabel.setForeground(Color.BLACK);
}
blinkyLabel.setOpaque(blink);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
}
}
您可以查看和了解更多信息b2和ob变量的类型是什么?我认为问题可能是因为您在EDT(事件调度线程)之外调用SWING代码。在EDT之外调用repaint是可以的(repaint是少数例外之一),但如果b2是swing(或awt)组件,则在EDT之外调用其方法是不可以的。b2变量是公共类Ball extends JApplet的一个实例,它就是Ball本身。。ob变量是jframe对象的引用。。我将其发送到球,以确定帧的高度和宽度,以避免超出边界。。你知道吗。。。当我注释这行时,请重新绘制();球出现了,但是越过了jframe,jframe没有得到预期的更新。。但一旦我加上它。。球消失了!!您不应该在EDT之外处理GUI更新任务。要更快地获得更好的帮助,请发布一个。不,它不起作用。。就好像我在画球,但屏幕上没有重新油漆一样。。。。所以我仍然可以在屏幕上看到球的轨迹。。。。就像我看到了球的位置。。。而且它们不会被删除。。。这不是我想要的..在EDT上调用
Thread.sleep
,因为它会阻塞整个UI。如果你想在SwingYou中制作动画,可以使用javax.swing.Timer
类。你也可以使用SwingWorker。@2012 EndoftheWorld SwingWorker对于这个问题来说是致命的+1对于javax.swing.Timer
,它方便地封装了睡眠。