当桥的内容改变时刷新包含 AWT-SWT 桥的 Eclipse RCP 部分
Refreshing Eclipse RCP part containing an AWT-SWT bridge when contents of the bridge change
我正在开发一个从 Swing 版本过渡的 RCP 应用程序。因此,在此过渡期间,我们有很多 UI 组件仍然需要存在于 Swing 世界中。我能够将现有的 Swing 组件正确地放置在 AWT-SWT 桥接框架中。
在将这些 Swing 组件添加到桥之前,我将它们包装在一个 JScrollable 窗格中,这样当 Swing UI 元素的大小发生变化时,我不必调整包含部分的大小。我将一个旧的 Swing 组件放在一个部分中的代码如下所示:
@PostConstruct
public void postConstruct(final Composite parent) {
/* Create embedding composite */
final Frame bridgeFrame;
final Composite embed;
embed = new Composite(parent, SWT.EMBEDDED);
embed.setLayout(new FillLayout());
bridgeFrame = SWT_AWT.new_Frame(embed);
bridgeFrame.setLayout(new BorderLayout());
bridgeFrame.add(
new JScrollPane(getTestPanel()),
BorderLayout.CENTER);
}
我的 Swing 组件有一种行为,即当用户单击按钮时,隐藏在组件中的内容会变得可见,或者新的 UI 元素会添加到 Swing 组件中。例如:
private JPanel getTestPanel() {
final JPanel output;
final JButton eastBttn, westBttn;
output = new JPanel();
eastBttn = new JButton("East Button");
westBttn = new JButton("West Button");
output.setLayout(new BorderLayout());
output.add(eastBttn, BorderLayout.EAST);
output.add(westBttn, BorderLayout.WEST);
eastBttn.addActionListener(evt -> {
System.out.println("East Button Clicked");
output.add(new JLabel("East Button Clicked"), BorderLayout.CENTER);
});
return output;
}
我的问题是,当 Swing 组件中的元素发生变化时,父桥框架无法正确呈现。
首次创建部件时,我的应用程序如下所示:
在我点击 EastButton
之后,它应该会在该桥框架的中心添加一个文本标签。但是,应用程序视图中没有任何变化。
但是,当我开始稍微调整包含部分窗框的大小时,包含桥框的部分会正确更新:
如何让桥接框架更新包含部分自动更新?
为了测试这是否是桥架上的重绘问题,我有一个菜单项会触发桥架的 repaint
/ revalidate
/ pack
,但这并没有解决问题。我怀疑它与包含部分的渲染器有关,但不知道如何解决它。
纯Swing解决方案中存在同样的问题:
public static void main(String[] args) {
JFrame bridgeFrame = new JFrame("Test");
bridgeFrame.setSize(400, 400);
bridgeFrame.setLayout(new BorderLayout());
bridgeFrame.add(new JScrollPane(getTestPanel()), BorderLayout.CENTER);
bridgeFrame.setVisible(true);
}
您需要在事件处理程序中添加 output.doLayout()
。
我最终通过将自定义 ControlListener
/ ComponentListener
附加到包含桥的部分来解决这个问题。如果桥接框架工作中的任何变化导致它的大小调整到超出父级,我会让监听器调整它的大小以适应父级,从而强制滚动窗格接管。
这是我的听众:
public class BridgeComponetAdapter
extends ComponentAdapter
implements ControlListener {
private final Composite parent;
private final Frame bridgeFrame;
private Point parentSize;
public BridgeComponetAdapter(
final Composite parent,
final Frame bridgeFrame) {
this.parent = parent;
this.bridgeFrame = bridgeFrame;
bridgeFrame.addComponentListener(this);
parent.addControlListener(this);
}
@Override
public void componentResized(final ComponentEvent e) {
System.out.println(e);
if (e.getSource() != bridgeFrame)
return;
final Dimension currentBridgeSize;
currentBridgeSize = bridgeFrame.getSize();
if (currentBridgeSize.getWidth() > parentSize.x
|| currentBridgeSize.getHeight() > parentSize.y) {
bridgeFrame.setSize(parentSize.x, parentSize.y);
}
}
@Override
public void controlMoved(final ControlEvent e) {}
@Override
public void controlResized(final ControlEvent e) {
System.out.println(e);
if (e.getSource() == parent)
parentSize = parent.getSize();
}
}
这不是一个优雅的解决方案;我仍然对解决问题的其他想法持开放态度。
我正在开发一个从 Swing 版本过渡的 RCP 应用程序。因此,在此过渡期间,我们有很多 UI 组件仍然需要存在于 Swing 世界中。我能够将现有的 Swing 组件正确地放置在 AWT-SWT 桥接框架中。
在将这些 Swing 组件添加到桥之前,我将它们包装在一个 JScrollable 窗格中,这样当 Swing UI 元素的大小发生变化时,我不必调整包含部分的大小。我将一个旧的 Swing 组件放在一个部分中的代码如下所示:
@PostConstruct
public void postConstruct(final Composite parent) {
/* Create embedding composite */
final Frame bridgeFrame;
final Composite embed;
embed = new Composite(parent, SWT.EMBEDDED);
embed.setLayout(new FillLayout());
bridgeFrame = SWT_AWT.new_Frame(embed);
bridgeFrame.setLayout(new BorderLayout());
bridgeFrame.add(
new JScrollPane(getTestPanel()),
BorderLayout.CENTER);
}
我的 Swing 组件有一种行为,即当用户单击按钮时,隐藏在组件中的内容会变得可见,或者新的 UI 元素会添加到 Swing 组件中。例如:
private JPanel getTestPanel() {
final JPanel output;
final JButton eastBttn, westBttn;
output = new JPanel();
eastBttn = new JButton("East Button");
westBttn = new JButton("West Button");
output.setLayout(new BorderLayout());
output.add(eastBttn, BorderLayout.EAST);
output.add(westBttn, BorderLayout.WEST);
eastBttn.addActionListener(evt -> {
System.out.println("East Button Clicked");
output.add(new JLabel("East Button Clicked"), BorderLayout.CENTER);
});
return output;
}
我的问题是,当 Swing 组件中的元素发生变化时,父桥框架无法正确呈现。
首次创建部件时,我的应用程序如下所示:
在我点击 EastButton
之后,它应该会在该桥框架的中心添加一个文本标签。但是,应用程序视图中没有任何变化。
但是,当我开始稍微调整包含部分窗框的大小时,包含桥框的部分会正确更新:
如何让桥接框架更新包含部分自动更新?
为了测试这是否是桥架上的重绘问题,我有一个菜单项会触发桥架的 repaint
/ revalidate
/ pack
,但这并没有解决问题。我怀疑它与包含部分的渲染器有关,但不知道如何解决它。
纯Swing解决方案中存在同样的问题:
public static void main(String[] args) {
JFrame bridgeFrame = new JFrame("Test");
bridgeFrame.setSize(400, 400);
bridgeFrame.setLayout(new BorderLayout());
bridgeFrame.add(new JScrollPane(getTestPanel()), BorderLayout.CENTER);
bridgeFrame.setVisible(true);
}
您需要在事件处理程序中添加 output.doLayout()
。
我最终通过将自定义 ControlListener
/ ComponentListener
附加到包含桥的部分来解决这个问题。如果桥接框架工作中的任何变化导致它的大小调整到超出父级,我会让监听器调整它的大小以适应父级,从而强制滚动窗格接管。
这是我的听众:
public class BridgeComponetAdapter
extends ComponentAdapter
implements ControlListener {
private final Composite parent;
private final Frame bridgeFrame;
private Point parentSize;
public BridgeComponetAdapter(
final Composite parent,
final Frame bridgeFrame) {
this.parent = parent;
this.bridgeFrame = bridgeFrame;
bridgeFrame.addComponentListener(this);
parent.addControlListener(this);
}
@Override
public void componentResized(final ComponentEvent e) {
System.out.println(e);
if (e.getSource() != bridgeFrame)
return;
final Dimension currentBridgeSize;
currentBridgeSize = bridgeFrame.getSize();
if (currentBridgeSize.getWidth() > parentSize.x
|| currentBridgeSize.getHeight() > parentSize.y) {
bridgeFrame.setSize(parentSize.x, parentSize.y);
}
}
@Override
public void controlMoved(final ControlEvent e) {}
@Override
public void controlResized(final ControlEvent e) {
System.out.println(e);
if (e.getSource() == parent)
parentSize = parent.getSize();
}
}
这不是一个优雅的解决方案;我仍然对解决问题的其他想法持开放态度。