JCheckbox只是通过控制器改变他的状态

时间:2013-12-12 20:14:11

标签: java swing mouselistener jcheckbox passive-view

普通JCheckbox直接对用户输入作出反应并设置或取消设置勾号。在此之后调用MouseListener。我想要实现的是JCheckbox的状态只能由控制器更改。有什么方法可以达到这个目的?

我尝试添加一个鼠标监听器,它立即再次添加/删除勾号,但这会导致闪烁。

我找到的唯一方法是覆盖processMouseEvent方法,但这真的很糟糕......

编辑(我目前的版本): 现在这确实有效。之前错过了调整模型。

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();
}

2 个答案:

答案 0 :(得分:1)

当人们玩UI时,我不喜欢它。这会使用户感到困惑,如果他们无法单击复选框,他们会认为应用程序已损坏。

无论如何,从复选框中删除MouseListener。

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

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

答案 1 :(得分: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();
}