2013-12-12 20 views
0

正常JCheckbox直接對用戶輸入做出反應並設置或取消設置滴答。在此之後,MouseListener被調用。我想實現的是JCheckbox的狀態只能由控制器更改。什麼是體面的方式來實現這一目標?JCheckbox只能通過控制器更改其狀態

我試圖添加一個鼠標偵聽器,立即再次添加/刪除勾號,但這會導致閃爍。

我發現的唯一辦法是覆蓋processMouseEvent方法,但是這是非常糟糕......

EDIT(我目前的版本): 這不現在現在的工作。錯過之前調整模型。

import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.EventListener; 
import javax.swing.JCheckBox; 

public class MyJCheckBox extends JCheckBox { 
    public MyJCheckBox() { 
     MouseListener[] ml = (MouseListener[]) this.getListeners(MouseListener.class); 

     for (int i = 0; i < ml.length; i++) { 
      this.removeMouseListener(ml[i]); 
      this.addMouseListener(new MouseListenerWrapper(ml[i])); 
     } 

    } 

    public void addClickListener(ClickListener listener) { 
     listenerList.add(ClickListener.class, listener); 
    } 

    private class MouseListenerWrapper implements MouseListener { 
     MouseListener listener; 

     public MouseListenerWrapper(MouseListener listener) { 
      this.listener = listener; 
     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
      listener.mouseClicked(e); 
     } 

     @Override 
     public void mousePressed(MouseEvent e) { 
      listener.mousePressed(e); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      for(ClickListener listener : listenerList.getListeners(ClickListener.class)) { 
       listener.onClick(); 

          //Adjust model 
       MyJCheckBox.this.getModel().setArmed(false); 
       MyJCheckBox.this.getModel().setPressed(false); 
      } 

     } 

     @Override 
     public void mouseEntered(MouseEvent e) { 
      listener.mouseEntered(e); 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
      listener.mouseExited(e); 
     } 
    } 
} 

interface ClickListener extends EventListener { 
    public void onClick(); 
} 
+0

之後,調用MouseListener。 ==請原因,在哪裏,什麼,以便更快地發佈SSCCE,簡短,可運行,可編譯,只需一個帶有MouseListener的JCheckBox – mKorbel

+0

setSelected。 ..... – mKorbel

+0

我想要這個的原因是有一個被動的觀點,只能通過控制器改變他的狀態。 –

回答

1

我不喜歡人們玩UI的時候。這會讓用戶感到困惑,如果他們無法點擊複選框,他們會認爲應用程序已經損壞。

無論如何,從複選框中刪除MouseListener。

MouseListener[] ml = (MouseListener[])checkBox.getListeners(MouseListener.class); 

for (int i = 0; i < ml.length; i++) 
    checkBox.removeMouseListener(ml[i]); 
+0

AFAIK這些監聽器是共享的,沒有影響模型可能是一種方式 – mKorbel

+0

@mKorbel,不知道他們是否共享,但如果你只從一個複選框中刪除他們,那麼複選框將不會響應鼠標點擊。 – camickr

+0

也許你是對的,但我記得問題,我必須檢查 – mKorbel

0

還有另一種方法來實現我想要的行爲,如果在繪製之前覆蓋paint方法並根據需要更改模型。

import java.awt.Graphics; 
import javax.swing.AbstractButton; 
import javax.swing.ButtonModel; 

public class MyJCheckBox extends JCheckBox { 
    private boolean change = false; 
    private boolean previousState = false; 

    @Override 
    public void setSelected(boolean selected) { 
     if(this.isSelected() != selected) { 
      change = true; 
    } 
     super.setSelected(selected); 
    } 

    @Override 
    public void paint(Graphics g) { 
     AbstractButton b = this; 
     ButtonModel model = b.getModel(); 

     boolean changeRequest = false; 

     //adjust model state to our needs. A state change 
     //is only possible if it was requested by 
     //setSelected() 

     if(previousState != model.isSelected()) { 
      //Revert change if it was not requested by 
      //by setSelected() 
      if(! change) { 
       changeRequest = true; 
       model.setSelected(previousState); 
      } 
      //Reset change to false so it can only be changed once 
      //To change it again you have to call setSelected() again. 
      change = false; 
     } 

     //Set current state as previous state 
     previousState = model.isSelected(); 

     //paint with adjusted model 
     super.paint(g); 

     //Inform listener that a change was requested 
     if(changeRequest) { 
      for(ClickListener listener : listenerList.getListeners(ClickListener.class)) { 
      listener.onClick(); 
      } 
     } 
    } 
} 

interface ClickListener extends EventListener { 
    public void onClick(); 
} 
相關問題