2012-09-12 41 views
6

Tôi đang cố gắng ngăn người dùng thay đổi tab khi tab hiện tại không hợp lệ. Vì vậy, khi anh ấy nhấp vào một tab, tôi muốn kiểm tra xem tab hiện tại có "hợp lệ" hay không và nếu không, hãy ở lại tab hiện tại. tôi cố gắng sử dụng một VetoableChangeListener mà không hiệu quả, các mã không bao giờ đi bên trong phương pháp vetoableChange:Thay đổi tab cấm trong JTabbedPane

jTabbedPane.addVetoableChangeListener(new VetoableChangeListener() { 

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

Làm thế nào tôi có thể làm điều này đúng cách?

Cảm ơn!

Trả lời

14

Một VetoableChangeListener chỉ hữu ích nếu lớp được đăng ký với kích hoạt thuộc tính có thể phủ nhận. Hầu hết (tất cả? Không bao giờ đi qua một) các thuộc tính trên JComponents và các lớp con không bị phủ quyết. Thêm vào đó việc lựa chọn được xử lý bởi một SingleSelectionModel, không phải chính thành phần đó.

Đó mô hình là móc để hỗ trợ vetoable thay đổi

  • thực hiện một mô hình tùy chỉnh mà bắn một vetoablePropertyChange về biến đổi lựa chọn
  • nếu không ai trong số thính giả của nó đối tượng, đi trước với sự thay đổi, nếu không làm gì cả
  • đặt mô hình tùy chỉnh thành tabbedPane
  • triển khai VetoablePropertyChangeListener chứa logic xác thực
  • đăng ký vetoableList Ener với mô hình

trong mã, một cái gì đó giống như

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

Công cụ này rất hữu ích cho việc thay đổi tab, nhưng bạn làm cách nào để tab phủ quyết đóng? 'vetoableChange' được gọi sau khi tab được đóng và khi tab trước đó được chọn. Tôi đã tìm kiếm trên internet cho vetoableClose, nhưng không có lần truy cập nào. –

+0

âm thanh không liên quan/mở rộng - vui lòng đăng câu hỏi với SSCCE – kleopatra

+0

Không sao, tôi đã giải quyết được. Tôi đã thêm một thành phần nút trên mỗi tab để đóng chúng lại. Nó gọi 'JTabbedPane.remove (tabIndex)'. Tôi xoay xở để giải quyết nó. Tôi đang chọn tab trước đó trước khi đóng tab hiện tại để phương thức 'valueChanged' được gọi. –

0

Dường như vetoableChange là một phần của gói java.beans. Thử thêm 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

đoán bạn không bạn cố gắng mà ;-) Tại thời điểm thông báo thay đổi lựa chọn các lựa chọn đã _is_ thay đổi, do đó chỉ thingy bạn sẽ có thể làm là để hoàn nguyên sự thay đổi - nhưng em bé đã chết sau khi rơi vào giếng .. – kleopatra

1

Có vẻ như bạn muốn tắt tab trước. Sau đó, khi trang hiện tại hợp lệ, hãy bật tab. Cũng có vẻ như bạn có thể muốn xem xét một CardLayout thay vì các tab. Sau đó, sử dụng nút "Tiếp theo" hoặc "Tiếp tục" khi trang hiện tại hợp lệ.

+1

Vô hiệu hóa tab thứ hai có thể không trực quan cho người dùng. Nhưng bố trí thẻ có thể thực hiện công việc. Đừng quên để thêm một số lời khuyên cho người dùng để xem lý do tại sao anh ta không thể tiến tới màn hình tiếp theo. – svz

+0

Tôi không muốn tắt bất kỳ tab nào. Điều đó có nghĩa là tôi cần phải kiểm tra xem tab có hợp lệ sau mỗi hành động được thực hiện bởi người dùng không, điều này là không thể. – Nanocom

Các vấn đề liên quan