2

我有一个应用程序,它根据用户输入更改 JFrame 的全部内容。我通过删除包含当前组件的 JPanel 并将其替换为具有新组件的新 JPanel 来做到这一点。之后,其中一个组件需要获得焦点,并且 JScrollpane 应该滚动到该组件。在大多数情况下,这可以正常工作。现在有一个场景导致添加了一个 JPanel,它本身包含 500 多个组件。渲染它需要一些时间,并且似乎在 UI 未完全渲染的地方调用了 scrollRectToVisible()。如果我调试,我实际上可以看到它首先滚动到正确的位置,但随后完成了进一步的渲染,并且组件再次移出视口。

所以我试图找到一个监听器,它在渲染完成后被调用。我尝试使用 ComponentListener 和 AnchestorListener。两者都没有收到我所期待的大部分事件。但即使他们这样做了,回调方法也会在屏幕上显示任何 UI 更改之前被调用。

我在 EDT 中交换 JPanel,然后在 JFrame 上调用 validate()。之后我不再处理任何代码。但是,如果我在最后执行的行中设置断点并更进一步,屏幕上的 UI 并没有改变。EDT 正在积极地做某事(我假设渲染 UI)。当 EDT 完成渲染时,我想收到通知。

我尝试过的另一件事:如果我创建另一个只休眠几秒钟的线程(直到 UI 确定呈现)并调用 scrollRectToVisible() ,那么一切正常。

很抱歉没有提供 SSCCE。我试过了,但它似乎相当复杂。我真的很感激任何关于如何在 UIbeeing 完全呈现并且对用户可见的通知上的想法。

谢谢

4

3 回答 3

1

如果我创建另一个只休眠几秒钟的线程(直到 UI 确定呈现)并调用 scrollRectToVisible() ,那么一切正常。

无需休眠,只需将 scrollRectToVisibl() 代码包装在 SwingUtilities.invokeLater() 中。这会将代码添加到 EDT 的末尾,因此应该在所有其他渲染之后对其进行处理。

于 2013-04-02T16:49:15.947 回答
0

添加属性更改侦听器:

    jPanel.addPropertyChangeListener(new PropertyChangeListener() {
        @Override
        public void propertyChange(final PropertyChangeEvent evt) {
            System.out.println(evt);
        }
    });

产生类似的东西:

java.beans.PropertyChangeEvent[propertyName=ancestor; oldValue=null; newValue=javax.swing.JPanel[null.contentPane,0,0,0x0,invalid,layout=javax.swing.JRootPane$1,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]; propagationId=null; source=javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]]
于 2013-04-02T18:29:40.873 回答
-1

也许 JComponent.addNotify() 是你需要的。如果您覆盖该方法,请确保您也调用了 super.addNotifty()!

于 2013-04-02T17:31:51.070 回答