2012-09-12 128 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僅當它註冊的類觸發vetoable propertyChange時纔有用。 JComponents和子類中的大多數(從未遇到過)屬性都不可否決。另外,選擇由SingleSelectionModel處理,而不是組件本身。

這種模式是支持可否決變化

  • 實現觸發一個vetoablePropertyChange選擇更改自定義模型鉤
  • 如果沒有它的聽衆對象,繼續與變化,否則什麼也不做
  • 設置自定義模型爲tabbedpane
  • 實施VetoablePropertyChangeListener其中包含驗證邏輯
  • 註冊vetoableList 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

bodyTabbedPane.addChangeListener(new javax.swing.event.ChangeListener() { 
     public void stateChanged(javax.swing.event.ChangeEvent evt) { 
      bodyTabbedPaneStateChanged(evt); 
     } 
    }); 


private void bodyTabbedPaneStateChanged(javax.swing.event.ChangeEvent evt) { 
    if (!isCurrentTabValid()) {    
     throw new PropertyVetoException("test", evt);   
    } 
} 
+4

猜你沒你嘗試;-)在選擇變更通知的時刻已經選擇_is_改變,因此,唯一的你可以做的事情就是恢復變化 - 但是在落入井中後寶寶已經死了。 – kleopatra

1

聽起來像要先禁用選項卡。然後噹噹前頁面有效時啓用該選項卡。也聽起來你可能想考慮一個CardLayout而不是製表符。然後在當前頁面有效時使用「下一步」或「繼續」按鈕。

+1

禁用第二個標籤對用戶來說可能並不直觀。但卡布局可以完成這項工作。不要忘記給用戶添加一些提示,看看他爲什麼不能進入下一個屏幕。 – svz

+0

我不想禁用任何選項卡。這意味着我需要在用戶做出每個動作後檢查該選項卡是否有效,這是不可能的。 – Nanocom

相關問題