Change tab bookmark in JTabbedPane

I am trying to prevent a user from changing a tab when the current tab is invalid. So when he clicks on the tab, I want to check if the current one is β€œvalid”, and if not, stay on the current tab. I tried using VetoableChangeListener, which did not work, the code never goes into 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 it right?

Thanks!

+6
source share
3 answers

A VetoableChangeListener is only useful if the class that it registered triggers theChange vet. Most (all? Never encountered one) properties on JComponents and subclasses are not vetoed. In addition, the selection is handled using the SingleSelectionModel, not the component itself.

This model is a hook to support veterinary changes.

  • implement a custom model that runs vetoablePropertyChange when the selection changes
  • If none of his listeners is objective, continue the change, otherwise do nothing
  • set custom model in tabbedPane
  • implement a VetoablePropertyChangeListener that contains validation logic
  • register vetoableListener for the model

in code, something like

 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")); 
+15
source

It looks like you want to disable the tab first. Then, when the current page is valid, enable the tab. It also sounds like you might consider CardLayout instead of tabs. Then use the "Next" or "Continue" button when the current page is valid.

+1
source

It looks like vetoableChange is part of the java.beans package. Try adding 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); } } 
0
source

Source: https://habr.com/ru/post/925222/


All Articles