禁止在JTabbedPane中更改选项卡

我试图阻止用户在当前选项卡无效时更改选项卡。 因此,当他点击标签时,我想检查当前标签是否“有效”,如果没有,请保持当前标签。 我试图使用一个不起作用的VetoableChangeListener,代码永远不会进入vetoableChange方法:

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

我怎么能这样做呢?

谢谢!

VetoableChangeListener仅在注册的类触发可否决的propertyChange时才有用。 JComponents和子类中的大多数(所有?从未遇到过)属性都不可撤销。 此外,选择由SingleSelectionModel处理,而不是组件本身。

该模型是支持可撤销变更的钩子

  • 实现一个自定义模型,在选择更改时触发vetoablePropertyChange
  • 如果没有听众反对,请继续进行更改,否则不执行任何操作
  • 将自定义模型设置为tabbedPane
  • 实现一个包含validation逻辑的VetoablePropertyChangeListener
  • 将vetoableListener注册到模型

在代码中,类似于

 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")); 

听起来你想先禁用标签。 然后当当前页面有效时启用该选项卡。 听起来你可能想要考虑CardLayout而不是标签。 然后在当前页面有效时使用“下一步”或“继续”按钮。

看起来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); } }