2012-09-12 11 views
6

現在のタブが無効なときにユーザーがタブを変更しないようにしようとしています。 それで、彼がタブをクリックするとき、私は現在のものが "有効"であるかどうかチェックし、そうでなければ、現在のタブにとどまります。 私は動作しませんでしたVetoableChangeListenerを使用しようとした、コードがvetoableChangeメソッド内部に入ることはありません:JTabbedPaneでタブの変更を禁止する

jTabbedPane.addVetoableChangeListener(new VetoableChangeListener() { 

    @Override 
    public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { 
    if (!isCurrentTabValid()) { 
     throw new PropertyVetoException("test", evt); 
    } 
    } 
}); 

私はこれを適切に行うことができますどのように?

ありがとうございます!

答えて

14

VetoableChangeListenerは、登録されたクラスが拒否可能なpropertyChangeを発生させる場合にのみ有効です。 JComponentsとサブクラスのほとんどのプロパティー(すべてが一度も見つからない)は拒否できません。さらに、選択はコンポーネント自体ではなく、SingleSelectionModelによって処理されます。モデルは拒否可能をサポートするためのフックが

  • を変更している

    は、そのリスナーのいずれもオブジェクトいない場合は選択変更

  • にvetoablePropertyChangeを発射カスタムモデルを実装チェンジを進める、そうでない場合は何もしない
  • は、検証ロジック
  • vetoableList登録が含まれているVetoablePropertyChangeListenerを実装タブ区画
  • へのカスタムモデルを設定しましたコードでモデル

にENER、

public static class VetoableSingleSelectionModel extends 
     DefaultSingleSelectionModel { 

    private VetoableChangeSupport vetoableChangeSupport; 

    @Override 
    public void setSelectedIndex(int index) { 
     if (getSelectedIndex() == index) 
      return; 
     try { 
      fireVetoableChange(getSelectedIndex(), index); 
     } catch (PropertyVetoException e) { 
      return; 
     } 
     super.setSelectedIndex(index); 
    } 

    private void fireVetoableChange(int oldSelectionIndex, 
      int newSelectionIndex) throws PropertyVetoException { 
     if (!isVetoable()) 
      return; 
     vetoableChangeSupport.fireVetoableChange("selectedIndex", 
       oldSelectionIndex, newSelectionIndex); 

    } 

    private boolean isVetoable() { 
     if (vetoableChangeSupport == null) 
      return false; 
     return vetoableChangeSupport.hasListeners(null); 
    } 

    public void addVetoableChangeListener(VetoableChangeListener l) { 
     if (vetoableChangeSupport == null) { 
      vetoableChangeSupport = new VetoableChangeSupport(this); 
     } 
     vetoableChangeSupport.addVetoableChangeListener(l); 
    } 

    public void removeVetoableChangeListener(VetoableChangeListener l) { 
     if (vetoableChangeSupport == null) 
      return; 
     vetoableChangeSupport.removeVetoableChangeListener(l); 
    } 

} 

// usage 
JTabbedPane pane = new JTabbedPane(); 
VetoableSingleSelectionModel model = new VetoableSingleSelectionModel(); 
VetoableChangeListener validator = new VetoableChangeListener() { 

    @Override 
    public void vetoableChange(PropertyChangeEvent evt) 
      throws PropertyVetoException { 
     int oldSelection = (int) evt.getOldValue(); 
     if ((oldSelection == -1) || isValidTab(oldSelection)) return; 

     throw new PropertyVetoException("change not valid", evt); 

    } 

    private boolean isValidTab(int oldSelection) { 
     // implement your validation logic here 
     return false; 
    } 
}; 
model.addVetoableChangeListener(validator); 
pane.setModel(model); 
pane.addTab("one", new JLabel("here we are and stay")); 
pane.addTab("other", new JLabel("poor me, never shown")); 
+0

これはタブの変更には効果的ですが、どのようにタブの閉じを拒否しますか? 'vetoableChange'は、タブが閉じられた後、前のタブが選択されたときに呼び出されます。私はvetoableCloseについてインターネットを検索しましたが、ヒットはありません。 –

+0

は無関係/拡張されているように聞こえます - SSCCEに質問を投稿してください – kleopatra

+0

これは問題ありません。私はそれらを閉じるために各タブに追加されたボタンコンポーネントを持っています。 'JTabbedPane.remove(tabIndex)'を呼び出します。私はそれを回避することができました。 'valueChanged'メソッドが呼び出されるように、現在のタブを閉じる前に前のタブを選択しています。 –

0

vetoableChangeがjava.beansパッケージの一部であるようです。 javax.swing.event.ChangeListenerを追加してみてください。

+4

のようなものは、あなたが唯一のように;-)選択変更通知の瞬間に選択がすでに、変更_is_ことをしようとしなかったと思いますあなたがすることができることは、変更を元に戻すことです - しかし、赤ちゃんは既に井戸に落ちた後に死んでいます。 – kleopatra

1

最初にタブを無効にしたいような音がします。現在のページが有効なとき、タブを有効にします。また、タブの代わりにCardLayoutを考えてみてください。次に、現在のページが有効なときに「次へ」または「続行」ボタンを使用します。

+1

2番目のタブを無効にすることは、ユーザーにとって直感的ではありません。しかし、カードのレイアウトは仕事をすることができます。ユーザーが次の画面に進むことができない理由を確認するためのヒントをいくつか追加することを忘れないでください。 – svz

+0

私はタブを無効にしたくありません。つまり、ユーザーが行った各操作の後にタブが有効であることを確認する必要がありますが、これは不可能です。 – Nanocom

関連する問題