Java Swing:在组件*完成*大小调整时执行某些操作

时间:2010-02-26 10:48:20

标签: java swing jxtaskpane

对于有些不明确的问题道歉 - 想不出更好的方法。

我使用JXTaskPane(来自Swing labs扩展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非常有用。谢谢!

3 个答案:

答案 0 :(得分:9)

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

查看JXTaskPane的来源并特别查看setExpanded()(第387行),您可以看到它调用JXCollapsiblePane.setCollapsed(...)然后触发属性更改事件以进行扩展。该属性上的侦听器将不正确,因为它将在动画完成之前触发。所以,如果你进入JXCollapsiblePane并查看setCollapsed(...)(第470行),你会看到如果它是动画的,它会设置参数并启动一个计时器。我们想知道动画何时结束,所以在该文件中,查看动画师(第620行,特别是652-667),它显示动画结束时,它会触发ANIMATION_STATE_KEY的属性更改,其值为“折叠” “或”扩大“。这是你真正想要的事件。但是,您无权访问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中侦听事件的正确方法是通过属性侦听器。不幸的是,找出正确属性和值的唯一方法是挖掘源代码。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

相关问题