【问题标题】:Java Swing: Do something when a component has *finished* resizingJava Swing:当组件*完成*调整大小时做一些事情
【发布时间】:2010-02-26 10:48:20
【问题描述】:

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

我使用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 非常有帮助。所以谢谢!

【问题讨论】:

    标签: java swing jxtaskpane


    【解决方案1】:

    我知道你已经选择了一个答案,但是重写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 中侦听事件的正确方法是通过属性侦听器。不幸的是,找出正确属性和值的唯一方法是挖掘源代码。

    【讨论】:

    • Fiar enuffski,我说我不是专家,很高兴有一种不那么老套的方法来做 OP 需要的事情
    【解决方案2】:

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

    【讨论】:

    • 詹姆斯 - 谢谢。我会试试这个。大概,我会覆盖 JFrame 上的paint方法?
    • 是的,这就是我的想法,或者在 JPanel 中(扩展 JPanel 可以让您更好地控制事物的设置方式,这往往是我构建 GUI 的方式,虽然我不能自称是专家)。希望你一切顺利!
    • 同意Gonzo,不推荐以这种方式覆盖paint()
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-17
      • 2012-05-19
      • 2016-09-06
      • 2013-04-16
      • 1970-01-01
      • 2011-04-29
      相关资源
      最近更新 更多