我们的应用程序显示数据的2D视图(主要是地图),然后允许用户更改为3D视图。 2D和3D视图由自定义C ++代码生成,这些代码SWIG进入我们的Swing GUI并包含在JComponent
中。然后,这些JComponent
将显示在另一个父JComponent中。
我们的问题是,当我们从2D视图更改为3D视图然后再返回2D视图时,当我们调整窗口大小时,2D视图不会调整大小。调整大小事件不会发送到2D视图。
我们的应用程序在Linux(Fedora 11)下运行。我们正在运行Java版本1.6.0_12。
下面是一些示例代码,其中我用两个2 JButton
替换了2D视图和3D视图,这会产生相同的行为。进入3D后再返回2D,调整窗口大小不会导致2D视图的大小调整。
/* TestFrame.java
* Compile with: $ javac TestFrame.java
* Run with: $ java TestFrame
*/
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JButton;
public class TestFrame extends javax.swing.JFrame {
private boolean mode2D = true;
private JButton view2D = null;
private JButton view3D = null;
private Container parent = null;
public TestFrame() {
initComponents();
containerPanel.setLayout(new BorderLayout());
view2D = new JButton("2D View");
view2D.addComponentListener(new MyListener("2D VIEW"));
containerPanel.add(view2D);
}
private void changerButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (parent == null) {
parent = view2D.getParent();
}
if (mode2D) {
System.out.println("Going from 2D to 3D");
view2D.setVisible(false);
if (view3D != null) {
view3D.setVisible(true);
} else {
view3D = new JButton("3D View");
view3D.addComponentListener(new MyListener("3D VIEW"));
parent.add(view3D);
}
((JButton) evt.getSource()).setText("Change to 2D");
mode2D = false;
} else {
System.out.println("Going from 3D to 2D");
view3D.setVisible(false);
view2D.setVisible(true);
((JButton) evt.getSource()).setText("Change to 3D");
mode2D = true;
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestFrame().setVisible(true);
}
});
}
private javax.swing.JPanel containerPanel;
private javax.swing.JButton changerButton;
private class MyListener implements ComponentListener {
private String name;
public MyListener(String name) {
this.name = name;
}
@Override
public void componentHidden(ComponentEvent event) {
System.out.println("@@@ [" + name + "] component Hidden");
}
@Override
public void componentResized(ComponentEvent event) {
System.out.println("@@@ [" + name + "] component Resized");
}
@Override
public void componentShown(ComponentEvent event) {
System.out.println("@@@ [" + name + "] component Shown");
}
@Override
public void componentMoved(ComponentEvent event) {
System.out.println("@@@ [" + name + "] component Moved");
}
};
@SuppressWarnings("unchecked")
private void initComponents() {
containerPanel = new javax.swing.JPanel();
changerButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
containerPanel.setBorder(new javax.swing.border.MatteBorder(null));
javax.swing.GroupLayout containerPanelLayout = new javax.swing.GroupLayout(containerPanel);
containerPanel.setLayout(containerPanelLayout);
containerPanelLayout.setHorizontalGroup(
containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 374, Short.MAX_VALUE)
);
containerPanelLayout.setVerticalGroup(
containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 239, Short.MAX_VALUE)
);
changerButton.setText("Change to 3D");
changerButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
changerButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(containerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(changerButton))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(containerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(changerButton)
.addContainerGap())
);
pack();
}
}
(我为Netbeans生成的GUI代码道歉)
我应该提一下,当我们调用parent.remove(view2D)
和parent.add(view3D)
来更改视图时,我们3D视图的X Windows ID会发生变化,而我们无法恢复3D视图。因此,parent.remove(view2D)
和parent.add(view3D)
并非真正的解决方案,我们必须在包含我们的2D和3D视图的setVisible(false)
上调用setVisible(true)
和JComponent
隐藏并展示它们。
非常感谢任何帮助。
答案 0 :(得分:2)
为什么不使用CardLayout从2D切换到3D组件? 在我的理解中,CardLayout正是为了这种目的而完成的。 另一个好处是它将简化您的代码。
答案 1 :(得分:2)
在您的remove()
和add()
方法更改组件后,您应该致电:
parent.revalidate(); //To make the layout manager do its work.
parent.repaint(); //This could be necessary, to suggest a repaint of the panel
Javadoc for JComponent#revalidate():
支持延迟自动布局。
调用无效,然后添加此项 组件的validateRoot到列表中 需要验证的组件。 毕竟验证将会发生 目前有待处理的事件 出动。换言之,在此之后 方法被称为第一个 在什么时候发现validateRoot(如果有的话) 走向收容层次结构 该组件的验证将被验证。 默认情况下,JRootPane,JScrollPane, 和JTextField从中返回true 一个isValidateRoot。
此方法将自动生效 在a时调用此组件 属性值变化使得大小, 位置或内部布局 组件受到影响。这个 自动更新不同于 AWT因为节目一般没有 更长时间需要调用验证来获取 要更新的GUI的内容。
答案 2 :(得分:0)
我找到了解决方案。您需要在布局管理器中添加/删除组件:
private void changerButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (parent == null) {
parent = view2D.getParent();
}
LayoutManager layoutMgr = parent.getLayout();
if (mode2D) {
System.out.println("Going from 2D to 3D");
view2D.setVisible(false);
layoutMgr.removeLayoutComponent(view2D);
if (view3D != null) {
view3D.setVisible(true);
if (layoutMgr != null && layoutMgr instanceof LayoutManager2) {
((LayoutManager2) layoutMgr).addLayoutComponent(view3D, null);
}
} else {
view3D = new JButton("3D View");
view3D.addComponentListener(new MyListener("3D VIEW"));
parent.add(view3D);
}
((JButton) evt.getSource()).setText("Change to 2D");
mode2D = false;
} else {
System.out.println("Going from 3D to 2D");
view3D.setVisible(false);
layoutMgr.removeLayoutComponent(view3D);
view2D.setVisible(true);
if (layoutMgr != null && layoutMgr instanceof LayoutManager2) {
((LayoutManager2) layoutMgr).addLayoutComponent(view2D, null);
}
((JButton) evt.getSource()).setText("Change to 3D");
mode2D = true;
}
}