0

既存のアプリケーションのメンテナンスを行っています。私が取り組んでいる機能は、Java 6 でコンパイルすると動作していましたが、Java 7 では動作しませんでした。簡単に説明しようと思います。

このアプリには、UI のほぼ全体を構成する巨大な JTabbedPane があります。JTabbedPane には、多数の JPanel が含まれています。次に、各 JPanel には、非常に多くの JComponents が含まれています。ユーザーはコントロールに値を入力できますが、何らかの理由ですべての変更をクリアしたい場合は、パネルを「リセット」するオプションを選択できます。責任あるメソッドが動作する方法は、JPanel を削除し、まったく同じクラスの新しいものを再作成し (それらはすべて JPanel から継承します)、同じインデックスで JTabbedPane に再挿入します。シンプルですね。

しかし実際には、JTabbedPane の次の JPanel タブに切り替わり、新しいパネルの多数のコントロールが次のパネルのコントロールに重なって表示されます。したがって、たとえば、panel0 を選択してリセットしたい場合は、panel1 が選択されているように表示され、panel0 のコンポーネント全体がそれに重なって表示されます。

それはさらに奇妙になります。これが発生すると、他のタブを選択できなくなります。UIがフリーズするようなものです。ユーザーは、現在のタブ (つまり、panel1) の上部にあるタブをクリックして選択する必要があります (既に選択されているため、これは奇妙です)。その後、他のタブに移動すると、すべてが正常に機能します。しかし、彼らが回避策を知らない場合、それはむしろ恐ろしいことです。そして、それは明らかに間違っています。パネルをリセットすると、すべてのコントロールが空白の同じパネルが表示されます。

疑似コードで行われることは次のとおりです。

  1. 現在のパネルを取得する
  2. それの新しいインスタンスを作成します
  3. 現在のパネルを削除
  4. 新しいインスタンスを挿入
  5. 再検証と再描画
  6. パネルの選択されたインデックスを設定します

実際のコードは次のとおりです。

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で機能する理由はまだわかりません。

4

1 に答える 1

0

すべての提案をありがとう。

これを異常な方法で修正しましたが、これは異常なバグです。メソッド内の Panel (上記のコードでは curTab と呼ばれる) を削除してから、フラグを設定しました。TabbedPane (JTabbedPane から継承した独自のものを作成する必要がありました) は、カスタム Paint() メソッドでフラグを探します。カスタム ペインティングは行いませんが、このメソッドでは、新しい Panel を割り当てて、古い Panel が削除されたインデックスの TabbedPane に挿入します。次に、すべてのフラグをクリアして、すべてをクリーンアップします。

私が言ったように、これは異常な修正ですが、視覚的および機能的な不具合を回避するために私が試みた唯一の方法です.

于 2013-03-28T21:26:19.963 に答える