禁止在JTabbedPane中更改选项卡
我正在尝试阻止用户在当前标签无效时更改标签。
所以当他点击一个标签时,我想检查当前标签是否有效,如果不是,请保持当前标签。
我试图使用不起作用的VetoableChangeListener,代码永远不会进入vetoableChange方法:
I'm trying to prevent the user from changing a tab when the current tab is not valid. So when he clicks on a tab, I want to check if the current one is "valid", and if not, stay on the current tab. I tried to use a VetoableChangeListener which didn't work, the code never goes inside the vetoableChange method:
jTabbedPane.addVetoableChangeListener(new VetoableChangeListener() {
@Override
public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
if (!isCurrentTabValid()) {
throw new PropertyVetoException("test", evt);
}
}
});
我该如何正确地做到这一点?
How can I do this properly?
谢谢!
VetoableChangeListener仅在其注册的类触发可否决的propertyChange时才有用。 JComponents和子类中的大多数(所有?从未遇到过)属性都不可撤销。此外,选择由SingleSelectionModel处理,而不是组件本身。
A VetoableChangeListener is useful only if the class it is registered with fires a vetoable propertyChange. Most (all? never came across one) properties on JComponents and subclasses are not vetoable. Plus the selection is handled by a SingleSelectionModel, not the component itself.
该模型是支持可否决更改的钩子
That model is the hook to support vetoable changes
- 实现一个自定义模型,在选择更改时触发vetoablePropertyChange
- 如果没有任何侦听器反对,请继续进行更改,否则什么都不做 li>
- 将自定义模型设置为tabbedPane
- 实现包含验证逻辑的VetoablePropertyChangeListener
- 将vetoableListener注册到代码中的模型
- implement a custom model that fires a vetoablePropertyChange on selection change
- if none of its listeners object, go ahead with the change, otherwise do nothing
- set the custom model to the tabbedPane
- implement a VetoablePropertyChangeListener which contains the validation logic
- register the vetoableListener to the model
,类似于
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"));