2012-09-12 92 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

相关问题