java - 从非 EDT 触发 Java 重绘很慢
问题描述
我在repaint()
不是 EDT 的线程中调用 JFrame 中的 Swing 组件(与repaint
Swing 侦听器/适配器/动作映射中的典型调用相反)。从技术上讲,它是在 javax.sound.midi 的回调中调用的Reciever
,但我认为这与一般情况没有什么不同。
组件更新缓慢。这个玩具代码显示了一个JLabel
其文本应该立即更新到当前时间,然后是我们repaint
,然后我们打印到当前时间的标准输出。在我的系统上,标签和标准输出时间看起来是正确的——标签repaint
比标准输出早了几毫秒。但是,标签在视觉上不会更新一段时间,看起来是随机的,甚至长达半秒。当它确实更新时,它会显示一个合理的时间,但它是一个旧时间。
从鼠标侦听器(或按键侦听器等)的回调中执行 [更新显示时间、重绘、打印时间] 测试工作正常,延迟低。当然调用repaint
只是安排它发生,但行为不应该是相同的,特别是如果包裹在SwingUtilities.invokeLater
? 我是否缺少事件优先级或简单的线程事实?如果不是,什么组件需要很长时间才能重新绘制JLabel
?总之,我如何repaint
从非 Swing、非 EDT 线程调用?
非工作解决方案:
paintComponent
直接调用https://stackoverflow.com/a/9004806/14495758;我不应该实现一个 customJFrame
,对吧?paintImmediately
在 Java中调用repaint() 不会立即“重新绘制”?; 这会导致相同的行为,调用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,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);
}
}
提前感谢您的阅读。
解决方案
推荐阅读
- vue.js - 在初始页面加载时获取用户 - Nuxt 中间件
- google-cloud-platform - 如何查看 GCP HealthCheck 日志
- python - 将s3文件下载到临时文件
- python - 使用 BeautifulSoup 访问 aria 标签和 yelp 评论
- wordpress - 使用 Genesis 框架对自定义帖子类型的评论
- javascript - 将图像 URL 转换为 base 64 字符串
- java - 将 Blob 转换为 String 仅在 Java 中生成 Blob 对象名称
- android - ViewPager 孩子在父母旁边滑动
- asp.net - 带有 Azure Key Vault 的本地 ASP.NET Framework Web 应用
- authentication - 如何使用基本身份验证访问页面(Apify SDK)