问题描述
我正在非EDT的线程中的JFrame的Swing组件上调用repaint()
(与Swing侦听器/适配器/动作映射中的典型repaint
调用相反)。从技术上讲,它是在javax.sound.midi Reciever
的回调中调用的,但我认为这与一般情况没有什么不同。
该组件更新缓慢。此玩具代码显示了一个JLabel
,其文本应立即更新为当前时间,然后我们repaint
,然后打印以输出当前时间。在我的系统上,标签和标准输出时间 look 正确-标签repaint
的发生时间比标准输出早几毫秒。但是,标签视觉上不会更新一段时间,似乎是随机的,甚至是半秒。当它确实更新时,它会显示一个合理的时间,但是它是一个旧的时间。
在鼠标侦听器(或按键侦听器等)的回调中执行[更新显示时间,重绘,打印时间]测试,效果很好,延迟很短。当然,调用repaint
仅安排它的发生,但是行为不应该相同,尤其是如果包装在SwingUtilities.invokelater
中吗?我是否缺少事件优先级或简单的线程事实?如果没有JLabel
,哪些组件需要很长时间才能重新粉刷?总之,如何从非Swing,非EDT线程调用repaint
?
非工作解决方案:
- 像在https://stackoverflow.com/a/9004806/14495758中一样直接呼叫
paintComponent
;我不必实施自定义JFrame
,对吧? - 像repaint() in Java doesn't "re-paint" immediately?一样呼叫
paintImmediately
;这会导致相同的行为,对repaint
的调用不会被收集并稍后调用 - 在
repaint
上呼叫JFrame
;导致相同的行为
import javax.sound.midi.*;import javax.swing.*;import java.lang.reflect.InvocationTargetException;
public class Main {
public static String time() {return (System.currentTimeMillis()/1000)+"."+(System.currentTimeMillis()%1000);}
public static void main(String[] args) {
JFrame w = new JFrame();
JLabel label = new JLabel("hey");
Transmitter tr = MidiUtil.firstTransmitterExcept("gervill","real time sequencer");//makes a MidiDevice and returns its transmitter
tr.setReceiver(new Receiver(){public void send(final MidiMessage message,final long t) {
try {
label.setText(time());
SwingUtilities.invokeAndWait(()->{label.paintImmediately(0,label.getWidth(),label.getHeight());});
}catch(final InterruptedException ie) {}catch(final InvocationTargetException ite) {}
System.out.println(time());
}public void close() {}});
w.add(label);
w.pack();
w.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
w.setVisible(true);
}
}
多谢您阅读。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)