Java摇摆按钮

时间:2010-04-06 18:59:25

标签: java swing jbutton

我正在尝试创建一个JButton或AbstractButton的子类,只要按住鼠标按钮就可以调用指定的.actionPerformed。

到目前为止,我正在考虑扩展JButton,在创建时添加鼠标侦听器(在构造函数内部)并在鼠标停止时调用actionPerformed。到目前为止,我提出了这个问题,但如果我走在正确的轨道上,我就会感到畏缩,如果是这样,那么如何正确地实现“压制”逻辑。

package components;

import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;

public class HoldButton extends JButton {

    private class HeldDownMouseListener implements MouseListener {

        private boolean mouseIsHeldDown;

        private HoldButton button;

        private long millis;

        public HeldDownMouseListener(HoldButton button, long millis) {
            this.button = button;
            this.millis = millis;
        }

        @Override
        public void mouseClicked(MouseEvent arg0) { }

        @Override
        public void mouseEntered(MouseEvent arg0) { }

        @Override
        public void mouseExited(MouseEvent arg0) { }

        @Override
        public void mousePressed(MouseEvent arg0) {
            mouseIsHeldDown = true;
//          This should be run in a sub thread?
//          while (mouseIsHeldDown) {
//              button.fireActionPerformed(new ActionEvent(button, ActionEvent.ACTION_PERFORMED, "heldDown"));
//              try {
//                  Thread.sleep(millis);
//              } catch (InterruptedException e) {
//                  e.printStackTrace();
//                  continue;
//              }
//          }
        }

        @Override
        public void mouseReleased(MouseEvent arg0) {
            mouseIsHeldDown = false;
        }

    }

    public HoldButton() {
        addHeldDownMouseListener();
    }

    public HoldButton(Icon icon) {
        super(icon);
        addHeldDownMouseListener();
    }

    public HoldButton(String text) {
        super(text);
        addHeldDownMouseListener();
    }

    public HoldButton(Action a) {
        super(a);
        addHeldDownMouseListener();
    }

    private void addHeldDownMouseListener() {
        addMouseListener(new HeldDownMouseListener(this, 300));
    }

}

非常感谢你的时间。

编辑:选择Timer方法我想出了一个有效的实现:

package components;

import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;

public class HoldButton extends JButton {

    private static final long serialVersionUID = 1L;

    public static final long CLICK_LAG = 300;

    public static final long INITIAL_FIRE_DELAY = 500;

    public static final double FIRE_DELAY_STEP_MULTIPLIER = 25;

    public static final long MIN_FIRE_DELAY = 100;

    private class HeldDownMouseListener implements MouseListener {

        private class HeldDownCheckerTask extends TimerTask {

            private HeldDownMouseListener listener;

            public HeldDownCheckerTask(HeldDownMouseListener listener) {
                this.listener = listener;
            }

            @Override
            public void run() {
                long delay = INITIAL_FIRE_DELAY;

                while (listener.isMouseHeldDownOnButton()) {
                    listener.fireMouseHeldDown();

                    try {
                        Thread.sleep(delay);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    if (delay > MIN_FIRE_DELAY) {
                        final long decrease = Math.round(FIRE_DELAY_STEP_MULTIPLIER * Math.pow(INITIAL_FIRE_DELAY / delay, 2));
                        delay = Math.max(delay - decrease, MIN_FIRE_DELAY);
                    }
                }
            }

        }

        private boolean mouseIsHeldDown;

        private boolean mouseIsOnButton;

        private HoldButton button;

        private Timer timer;

        public HeldDownMouseListener(HoldButton button) {
            this.button = button;
        }

        public boolean isMouseHeldDownOnButton() {
            return mouseIsHeldDown && mouseIsOnButton;
        }

        private void cancelTimer() {
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
        }

        private void fireMouseHeldDown() {
            button.fireActionPerformed(new ActionEvent(button, ActionEvent.ACTION_PERFORMED, "heldDown"));
        }

        @Override
        public void mouseClicked(MouseEvent arg0) {
            cancelTimer();
        }

        @Override
        public void mouseEntered(MouseEvent arg0) {
            mouseIsOnButton = true;
        }

        @Override
        public void mouseExited(MouseEvent arg0) {
            mouseIsOnButton = false;
        }

        @Override
        public void mousePressed(MouseEvent arg0) {
            cancelTimer();
            mouseIsHeldDown = true;
            timer = new Timer();
            timer.schedule(new HeldDownCheckerTask(this), CLICK_LAG);
        }

        @Override
        public void mouseReleased(MouseEvent arg0) {
            mouseIsHeldDown = false;
        }

    }

    public HoldButton() {
        addHeldDownMouseListener();
    }

    public HoldButton(Icon icon) {
        super(icon);
        addHeldDownMouseListener();
    }

    public HoldButton(String text) {
        super(text);
        addHeldDownMouseListener();
    }

    public HoldButton(Action a) {
        super(a);
        addHeldDownMouseListener();
    }

    private void addHeldDownMouseListener() {
        addMouseListener(new HeldDownMouseListener(this));
    }

}

2 个答案:

答案 0 :(得分:1)

当按下鼠标时,你可以启动一个计时器,在你需要的时间间隔内重复调用你的动作,直到松开按钮。然后你可以停止计时器。通过将其提交给计时器,您可以将其提交给新线程,而不是自己进行线程管理。

答案 1 :(得分:1)

至少有一个好的做法是做'工作',在这种情况下你通过SwingUtilies.invokeLater()在runnable中运行actionPerformed-loop。这样它就会被卸载到事件线程池/队列中,并且你没有阻止awt主线程,因此你不会阻止你的GUI。