0

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

2 回答 2

1

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

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

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

for (int i = 0; i < ml.length; i++)
    checkBox.removeMouseListener( ml[i] );
于 2013-12-12T20:16:42.437 回答
0

如果您在绘制之前覆盖绘制方法并根据您的需要更改模型,那么还有另一种方法可以实现我想要的行为。

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();
}
于 2013-12-14T11:29:53.457 回答