我正在尝试创建一个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));
}
}
答案 0 :(得分:1)
当按下鼠标时,你可以启动一个计时器,在你需要的时间间隔内重复调用你的动作,直到松开按钮。然后你可以停止计时器。通过将其提交给计时器,您可以将其提交给新线程,而不是自己进行线程管理。
答案 1 :(得分:1)
至少有一个好的做法是做'工作',在这种情况下你通过SwingUtilies.invokeLater()在runnable中运行actionPerformed-loop。这样它就会被卸载到事件线程池/队列中,并且你没有阻止awt主线程,因此你不会阻止你的GUI。