8

为这个有点不清楚的问题道歉 - 想不出更好的表达方式。

我使用JXTaskPane(来自 Swing 实验室扩展 API)来显示一些信息。

用户可以“单击”标题以展开面板。JXTaskPane 位于容器 JPanel 中,然后将其添加到 JFrame,即我的主应用程序窗口。

我希望我的应用程序窗口调整为展开的任务窗格的大小。为了实现这一点,我在容器 JPanel 中添加了一个组件侦听器,它将大小设置为现在展开的面板。

panel.addComponentListener(new ComponentListener()
{   
    public void componentResized(ComponentEvent e)
    {
        Dimension newSize = ((JXTaskPane)e.getSource()).getSize();
        reSizeFrame(newSize);
    }
}

private void reSizeFrame(Dimension newSize)
{   
    if ((newSize.height < maxSize.height) && (newSize.width < maxSize.width))
    {
        containerPanel.setSize(newSize);
        appFrame.setSize(containerPanel.getSize());
        appFrame.pack();
    }
}

问题是componentResized方法在任务窗格展开时被调用,结果 resizeFrame 方法被调用了很多次,在屏幕上看起来真的很糟糕。

如何检测 JXTaskpane 何时完成调整大小?我想到了两种方法:

  • 将 resizeFrame() 方法放入 SwingUtilities.invokeLate(..) 调用中。

  • 放入计时器 resizeFrame 调用,因此任何后续调用在计时器触发之前都不会执行任何操作。这应该为面板调整大小提供足够的时间。

最好的前进方式是什么?

另外 - 这是我在多年的服务器端程序之后的第一个严肃的 Java GUI 应用程序。StackOverflow 非常有帮助。那谢谢啦!

4

3 回答 3

9

我知道你已经选择了一个答案,但是重写paint方法肯定是不正确的,虽然你可以破解一些东西,但这并不理想。

查看JXTaskPane的源代码并特别查看 setExpanded()(第 387 行),您可以看到它调用了 JXCollapsiblePane.setCollapsed(...),然后触发扩展的属性更改事件。该属性上的侦听器将不正确,因为它会在动画完成之前触发。所以,如果你进入JXCollapsiblePane并查看 setCollapsed(...) (第 470 行),您会看到如果它是动画的,它会设置参数并启动一个计时器。我们想知道动画什么时候结束,所以在那个文件中,查看动画器(第 620 行,特别是 652-667 行),它表明当动画结束时,它会触发 ANIMATION_STATE_KEY 的属性更改,其值为“collapsed ”或“扩展”。这是您真正想要的事件。但是,您无权访问 JXCollapsiblePane,因此返回 JXTaskPane 并搜索 ANIMATION_STATE_KEY,您会找到第 208 行,这表明 JXTaskPane 在 JXCollapsiblePane.ANIMATION_STATE_KEY 上创建了一个侦听器,并将其作为自己的事件重新触发。

由于您确实有权访问 JXTaskPane,因此您可以侦听该事件,因此...

taskPane.addPropertyChangeListener(JXCollapsiblePane.ANIMATION_STATE_KEY, new PropertyChangeListener() {
  public void propertyChange(PropertyChangeEvent e) {
    if(e.getNewValue().equals("expanded") {
      ...
    }
    else if(e.getNewValue().equals("collapsed") {
      ...
    }
  }
}

应该在你想要的时候准确地得到你的事件。

在 Swing 中侦听事件的正确方法是通过属性侦听器。不幸的是,找出正确属性和值的唯一方法是挖掘源代码。

于 2010-03-01T00:43:55.597 回答
1

作为建议,您是否尝试过覆盖paint方法,首先调用super,然后如果(且仅当)大小发生显着变化时,将调整大小代码放在最后。

于 2010-02-26T10:52:16.677 回答
1

我对 JXTaskPane 不熟悉,但我的第一反应是您可能正在处理错误的事件。您希望在用户单击标题时调整框架的大小 - 那么为什么不处理该事件(也许在调整任务窗格大小后使用 EventQueue.invokeLater() 来调整框架的大小)?

但是,如果这不起作用并且您需要使用上面概述的方法,那么使用 javax.swing.Timer 可能是最好的。将其设置为 200 毫秒左右,并在每次 componentResized() 触发时重新启动它。

于 2010-03-01T00:21:20.113 回答