Java 等待AWT重新喷漆完成
我有一个Java 等待AWT重新喷漆完成,java,awt,frame,Java,Awt,Frame,我有一个框架,全是一种颜色,但角落里有一些文本。我设置颜色,从显示器上读取颜色,然后根据这些测量值进行一些计算 问题是,调用repaint()会导致帧在我进行测量之后被绘制。我假设这是由于repaint()委托EDT造成的,但由于实际喷漆工作之前/期间发生的测量,我得到了不正确的结果 我最初的想法是让一个监听器完成绘制,但我重新绘制以更新文本的频率要比我更新颜色的频率高很多,我不想听那些事件。我怎么能等到实际的绘画任务完成后再进行测量呢?你能找到的东西真是太棒了 EventQueue.invok
框架
,全是一种颜色,但角落里有一些文本。我设置颜色,从显示器上读取颜色,然后根据这些测量值进行一些计算
问题是,调用repaint()
会导致帧在我进行测量之后被绘制。我假设这是由于repaint()
委托EDT造成的,但由于实际喷漆工作之前/期间发生的测量,我得到了不正确的结果
我最初的想法是让一个监听器完成绘制,但我重新绘制以更新文本的频率要比我更新颜色的频率高很多,我不想听那些事件。我怎么能等到实际的绘画任务完成后再进行测量呢?你能找到的东西真是太棒了
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
PaintEvent pe = (PaintEvent) event;
String type = "";
if (pe.getID() == PaintEvent.PAINT) {
type = "PAINT";
} else if (pe.getID() == PaintEvent.PAINT_FIRST) {
type = "PAINT_FIRST";
} else if (pe.getID() == PaintEvent.PAINT_LAST) {
type = "PAINT_LAST";
} else if (pe.getID() == PaintEvent.UPDATE) {
type = "UPDATE";
}
System.out.println(type + "; pe.UpdateRec = " + pe.getUpdateRect() + "; pe.component = " + pe.getComponent());
}
}, AWTEvent.PAINT_EVENT_MASK);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
现在,因为重新绘制请求可以快速、灵活地进行,我很想在最后一个请求完成后不久就会触发一个小的“延迟”
private Timer updateTimer;
// ...
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
updateTimer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Update compulations here...
}
});
updateTimer.setRepeats(false);
updateTimer.setCoalesce(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
updateTimer.restart();
}
}, AWTEvent.PAINT_EVENT_MASK);
}
}
这样做的目的是在最后一次重新绘制请求和编译开始之间留出至少250毫秒的时间。你可能想玩弄一下这些价值观,看看什么适合你
更新
你也可以试试
绘制此组件中的指定区域及其所有
与区域重叠的子体,立即
很少需要调用此方法。在大多数情况下,这更重要
调用重新绘制非常有效,这会延迟实际绘制,并且可以
将冗余请求折叠为单个绘制调用。这种方法是可行的
如果需要在当前事件发生时更新显示,则此选项非常有用
被派遣
我知道这是一个旧线程,但如果有人正在搜索这个问题的答案,有一个名为的方法,可以在AWT调度线程上与当前线程同步运行任务。请注意,如果您需要在事件调度线程内执行此操作,则无法执行此操作。您可以围绕匿名锁对象同步线程,以使一个线程等待另一个线程。恕我直言,我认为您不能(可靠地)执行此操作。您可以尝试使用SwingUtilities.invokeLater(Runnable)
在调用repaint后将计算放在EDT的末尾,但不能保证已经在EDT上放置了重新绘制请求…@Vulcan,但我对EDT没有任何控制权,是吗?我想从实际的角度来看,EDT可能是FIFO,但从正确性的角度来看,我能保证吗?@MadProgrammer如果对repaint()
的调用已经完成,那么我就不能保证它已经提交给EDT了吗?尽管我们仍然存在EDT执行顺序错误的问题。@AndyShulman No。重新绘制请求可能会合并以减少重新绘制事件的数量。注意:如果在处理初始重绘请求之前组件上发生了多次重绘()调用,则多个请求可能会折叠为一次更新()调用。确定何时应折叠多个请求的算法取决于实现。如果多个请求被折叠,则生成的更新矩形将等于折叠请求中包含的矩形的并集。我知道您在这里尝试执行的操作,但是您确定它们将以正确的顺序放置在EDT中吗?一些测试表明,调用repaint()
一次会产生对我的paint()
方法的5个调用,我不知道这些调用是同步的还是附加到事件队列的末尾。因为可以合并重绘请求,无法保证它们会按照您要求的顺序出现。那么,我不确定您的解决方案实际如何工作。它似乎是围绕着“在代码中延迟一段时间,并期待最好的结果”展开的。我错了吗?有点。延迟的关键是您不会对每个绘制事件做出响应(因为您可能会收到几十个与同一个更新请求相关的事件)。我们的想法是引入一个小的延迟,以允许EDT空闲(或者至少是在这种情况下重新绘制的请求)。这是我认为你将接近“油漆结束”的周期。除非您希望处理每个绘制事件,但您需要在收到事件通知以及实际绘制调用发生时进行测试……您遇到的另一个问题是,“重新绘制”并不是生成绘制请求的唯一方式。Java可能正在响应来自操作系统的请求,例如鼠标悬停、窗口移动和更改。。。