2012-09-12 16 views
6

Próbuję uniemożliwić użytkownikowi zmianę karty, gdy bieżąca karta jest niepoprawna. Po kliknięciu na kartę chcę sprawdzić, czy aktualny jest "prawidłowy", a jeśli nie, pozostać na bieżącej karcie. Próbowałem użyć VetoableChangeListener który nie działa, kod nigdy nie wychodzi wewnątrz metody vetoableChange:Nie można zmienić zakładki w JTabbedPane

jTabbedPane.addVetoableChangeListener(new VetoableChangeListener() { 

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

Jak mogę to zrobić poprawnie?

Dzięki!

Odpowiedz

14

VetoableChangeListener jest przydatny tylko wtedy, gdy klasa, w której jest zarejestrowany, wywołuje vetoable propertyChange. Większość (nigdy nie natknęła się na jedno) właściwości na JComponents i podklasach nie podlegają żadnym przepisom. Plus wybór jest obsługiwany przez SingleSelectionModel, a nie sam komponent.

Ten model jest hak do wspierania vetoable zmienia

  • wdrożyć niestandardowy model, który wystrzeliwuje vetoablePropertyChange na zmianę wyboru
  • jeśli żaden z jego słuchaczy obiekt, iść do przodu ze zmianą, w przeciwnym razie zrobić nic
  • ustawić niestandardowy model do tabbedPane
  • wdrożyć VetoablePropertyChangeListener która zawiera logikę walidacji
  • zarejestrować vetoableList ENER do modelu

w kodzie, coś

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

Działa to doskonale w przypadku zmiany tabulatora, ale w jaki sposób można zawetować zamknięcie karty? 'vetoableChange' zostaje wywołane po zamknięciu karty i wybraniu poprzedniej karty. Przeszukałem internet pod kątem vetoableClose, ale bez trafień. –

+0

Dźwięki niezwiązane/rozszerzone - proszę napisać pytanie z SSCCE – kleopatra

+0

Jest ok, rozwiązałem to. Mam dodany komponent przycisku na każdej karcie, aby je zamknąć. Wywołuje 'JTabbedPane.remove (tabIndex)'. Udało mi się to obejść. Wybieram poprzednią zakładkę przed zamknięciem bieżącej, więc wywoływana jest metoda 'valueChanged'. –

0

Wygląda jak vetoableChange jest częścią pakietu java.beans. Spróbuj dodać javax.swing.event.ChangeListener.

+4

Chyba nie spróbujesz to ;-) W momencie zgłoszenia zmian selekcja już wybór _jest_ zmieniony tak, że tylko Coś, co byłbyś w stanie zrobić, to cofnąć zmianę - ale dziecko już nie żyje po wpadnięciu do studni. – kleopatra

1

Wygląda na to, że chcesz najpierw wyłączyć zakładkę. Następnie, gdy aktualna strona jest prawidłowa, włącz zakładkę. Również brzmi, jakbyś chciał rozważyć CardLayout zamiast kart. Następnie użyj przycisku "Dalej" lub "Kontynuuj", gdy aktualna strona jest ważna.

+1

Wyłączenie drugiej zakładki może nie być intuicyjne dla użytkownika. Ale układ kart może wykonać to zadanie. Nie zapomnij dodać kilku wskazówek dla użytkownika, aby zobaczyć, dlaczego nie może przejść do następnego ekranu. – svz

+0

Nie chcę wyłączać żadnej karty. Oznaczałoby to, że muszę sprawdzić, czy zakładka jest ważna po każdej czynności wykonanej przez użytkownika, co nie jest możliwe. – Nanocom

Powiązane problemy