Java 是否有一个与JFrame.pack()等效的方法,仅当子组件小于其数据模型时才调整其大小? 背景

Java 是否有一个与JFrame.pack()等效的方法,仅当子组件小于其数据模型时才调整其大小? 背景,java,swing,user-interface,jframe,Java,Swing,User Interface,Jframe,我正在用Java构建一个系统,该系统在运行时使用一个预定义的值树来生成GUI,该值树描述组件类、布局和数据绑定,其中每个非边缘节点都是某个组件的名称,例如 gui +-- txtDist | +-- class: "text" | +-- binding: "dx" | +-- xy: [0,0] | +-- wh: [1,1] +-- txtTime | +-- class: "text" | +-- bind

我正在用Java构建一个系统,该系统在运行时使用一个预定义的值树来生成GUI,该值树描述组件类、布局和数据绑定,其中每个非边缘节点都是某个组件的名称,例如

gui
+-- txtDist
|   +-- class: "text"
|   +-- binding: "dx"
|   +-- xy: [0,0]
|   +-- wh: [1,1]
+-- txtTime
|   +-- class: "text"
|   +-- binding: "dt
|   +-- xy: [0,1]
|   +-- wh: [1,1]
+-- txtV
|   +-- class: "text"
|   +-- binding: "v"
|   +-- xy: [1,0]
|   +-- wh: [1,2]
+-- btnCalc
|   +-- class: "button"
|   +-- binding: "fnCalcV" //a function that assigns the quotient of dx and dt to v
|   +-- label: "Calc. Velocity"
|   +-- xy: [0,2]
|   +-- wh: [1,1]
+-- btnClear
|   +-- class: "button"
|   +-- binding: "fnClear" //a function which sets variables to 0
|   +-- label: "Clear"
|   +-- xy: [1,2]
|   +-- wh: [1,1]
其中,
绑定
值是kdb+服务器上变量的名称。生成的GUI如下所示:

当系统收到树时,它使用描述创建GUI,但不会立即用数据填充组件。这是因为系统的设计允许它在服务器上更改组件的绑定变量时实时更新组件;当查询或更新服务器时,更新的变量通过ServerSocket发送,并放置在
更新队列
上,然后该队列调用表示kdb+变量的数据模型对象上的
notifyObservers
。组件根据
绑定
树值观察各自的模型,然后提供新数据以显示

问题 从树中呈现GUI时,将调用
JFrame.setVisible(true)
,并且所有组件都向服务器发送查询,请求获取它们的数据。数据对象在更新队列上一个接一个地发回,并随后通知观察者

此时,帧很小,因为组件可见,但为空。目前,我正在调用
JFrame.pack()
,每次更新消息被数据模型对象使用后都会调用,这本身就是一种资源浪费,但它可以确保组件填充后都能正确显示

但是
如果用户调整框架大小使其更大,然后更新服务器上的数据,则在将新数据添加到更新队列时,将再次调用
JFrame.pack()
方法,因此框架的大小调整将撤消。我想知道是否有一个与
pack()
等效的软件,只有在当前大小不适合所有数据的情况下才适合框架。

通常,当您在可见GUI上动态更新组件时,您使用:

panel.add(...);
panel.revalidate();
panel.repaint();
但是,这不会调整框架的大小以显示所有组件


调用上述代码后,可以在面板上调用
getPreferredSize()
getSize()
。然后,如果首选宽度/高度小于实际宽度/高度,您可以在框架上手动调用
pack()

void packExpand(JFrame frame)
{
    Dimension oldDim = frame.getSize();
    frame.pack();
    Dimension newDim = frame.getSize();
    frame.setSize(oldDim.width > newDim.width?oldDim.width:newDim.width, oldDim.height > newDim.height?oldDim.height:newDim.height);
}
然而,这样做的好处是能够“打包”(扩展)一个维度,同时保留另一个维度


一个更好的解决方案是在调整任何大小之前检查
frame.getPreferredSize()
值,但是我发现有些情况下这不能正常工作,所以请自己检查它是否适合您。这可能会有所帮助。

@camickr的建议是合理的;这将动态调用封闭的
窗口上的
pack()