既存のアプリケーションのメンテナンスを行っています。私が取り組んでいる機能は、Java 6 でコンパイルすると動作していましたが、Java 7 では動作しませんでした。簡単に説明しようと思います。
このアプリには、UI のほぼ全体を構成する巨大な JTabbedPane があります。JTabbedPane には、多数の JPanel が含まれています。次に、各 JPanel には、非常に多くの JComponents が含まれています。ユーザーはコントロールに値を入力できますが、何らかの理由ですべての変更をクリアしたい場合は、パネルを「リセット」するオプションを選択できます。責任あるメソッドが動作する方法は、JPanel を削除し、まったく同じクラスの新しいものを再作成し (それらはすべて JPanel から継承します)、同じインデックスで JTabbedPane に再挿入します。シンプルですね。
しかし実際には、JTabbedPane の次の JPanel タブに切り替わり、新しいパネルの多数のコントロールが次のパネルのコントロールに重なって表示されます。したがって、たとえば、panel0 を選択してリセットしたい場合は、panel1 が選択されているように表示され、panel0 のコンポーネント全体がそれに重なって表示されます。
それはさらに奇妙になります。これが発生すると、他のタブを選択できなくなります。UIがフリーズするようなものです。ユーザーは、現在のタブ (つまり、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;dr
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
最初のパラメーターにいくつかの異なる値を試しましたが、動作を変更するものはありませんでした。ご覧のとおり、リセットが発生するずっと前にダイアログが範囲外になります。これが7ではなくJava 6で機能する理由はまだわかりません。