0

通常の JCheckbox は、ユーザー入力に直接反応し、目盛りを設定または設定解除します。この後、MouseListener が呼び出されます。私が達成したいのは、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();
}
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 に答える