我正在对现有应用程序进行维护。我正在开发的功能在 Java 6 下编译时可以使用,但在 Java 7 下无法使用。我会尽量简短。
该应用程序有一个巨大的 JTabbedPane,几乎构成了整个 UI。JTabbedPane 包含许多 JPanel。反过来,每个 JPanel 都包含大量的 JComponent。用户可以在控件中输入值,但是如果出于某种原因他们想要清除所有更改,他们可以选择一个选项来“重置”面板。负责方法的工作方式是删除 JPanel,重新创建一个完全相同的类(它们都继承自 JPanel)并将其重新插入到 JTabbedPane 中的相同索引处。很简单,对吧?
但实际发生的情况是它切换到 JTabbedPane 中的下一个 JPanel 选项卡,然后新面板中的许多控件显示与下一个面板中的控件重叠。因此,例如,如果我选择了 panel0 并想要重置它,它将显示 panel1 已被选中,并且一大堆 panel0 的组件与其重叠。
它变得更加奇怪。发生这种情况后,无法选择其他选项卡。就像用户界面冻结一样。用户必须通过单击其顶部的选项卡来选择当前选项卡(即 panel1)(这很奇怪,因为它已经被选中)。然后他们可以转到其他选项卡,一切都按应有的方式运行。但是,如果他们不知道解决方法,那就太可怕了。这是完全错误的。重置面板应该只显示所有控件为空白的相同面板。
这是用伪代码完成的操作:
- 获取当前面板
- 创建它的新实例
- 移除当前面板
- 插入新实例
- 重新验证和重新绘制
- 设置面板的选中索引
这是实际的代码:
public void resetCurrentTab( int currentTabIndex ) {
// tried using m_tabbedPane.getTabComponentAt( currentTabIndex), but that returns null
JPanel curTab = (JPanel)m_tabbedPane.getSelectedComponent();
if( curTab == null )
return;
String curTabName = curTab.getName().trim();
// create new instance of panel
JPanel newPanel = null;
try {
newPanel = curTab.getClass().newInstance();
} catch (InstantiationException e) {
log.equals("Could not reset tab... tab " + curTabName + " creation failed.");
return;
} catch (IllegalAccessException e) {
log.equals("Could not reset tab... tab " + curTabName + " creation failed.");
return;
}
if( newPanel != null ) {
m_tabbedPane.remove( currentTabIndex );
m_tabbedPane.insertTab( newPanel.getName(), null, newPanel, null, currentTabIndex );
newPanel.setVisible( true );
}
m_tabbedPane.revalidate();
m_tabbedPane.repaint();
m_tabbedPane.setSelectedIndex( currentTabIndex );
}
就像我说的,这是在 Java 6 下编译的。在 Java 7 下,会发生奇怪的事情。我尝试了所有显而易见的事情,比如更改调用 revalidate()、repaint() 和 setSelectedIndex() 的顺序,但这并没有改变行为。我还尝试取出并重新添加相同的 JPanel 只是为了看看会发生什么。我没有得到重叠控件的奇怪之处,但它确实会在选项卡式控件中选择下一个 JPanel(选项卡)。
tl;博士
在 Java 6 下编译运行良好的功能在 Java 7 下编译不工作。
有任何想法吗?
编辑:我将问题完全追溯到其他东西。在用户重置选项卡之前,一个方法会弹出一个 JOptionPane 询问他们是否确定要这样做。它只是使用简单的 YES/NO 版本的 .showConfirmDialog()。如果我删除对话框,该功能将完美运行。如果我使用对话框,我会得到古怪的行为。
int response = JOptionPane
.showConfirmDialog(
currentTab,
confirmMsg,
"Reload the '" + curTabName + "' Tab",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE );
if( response == JOptionPane.YES_OPTION )
// return a value indicating to reset the panel
我为第一个参数尝试了几个不同的值,但没有一个改变行为。如您所见,对话框在重置发生之前很久就超出了范围。仍然不知道为什么这在 Java 6 而不是 7 下有效。