As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center作为指导。
6年前关闭。
考虑下面的MouseListener。我的问题是:具有此侦听器提供的额外功能,其中一些您将不需要,是否值得拥有这些功能所带来的内存和处理开销?还是应该避免像这样的“冗长”的实现?
6年前关闭。
考虑下面的MouseListener。我的问题是:具有此侦听器提供的额外功能,其中一些您将不需要,是否值得拥有这些功能所带来的内存和处理开销?还是应该避免像这样的“冗长”的实现?
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Timer;
/**
* This is an overkill class that is useful for distinguishing between buttons and includes functions for hold and double-click events.
*
* @author Paranoid Android
*/
public class ParanoidMouseListener extends MouseAdapter {
public static final int LEFT = MouseEvent.BUTTON1;
public static final int MIDDLE = MouseEvent.BUTTON2;
public static final int RIGHT = MouseEvent.BUTTON3;
private DoubleClickTimer leftDouble = new DoubleClickTimer();
private DoubleClickTimer middleDouble = new DoubleClickTimer();
private DoubleClickTimer rightDouble = new DoubleClickTimer();
private MouseEvent event;
private int pressedButton;
private Component pressed;
private boolean dragging;
/**
* This method allows methods to ignore the MouseEvent when not needed.
*
* @return the latest mouse event.
*/
public MouseEvent getEvent() {
return event;
}
private HoldTimer leftHold = new HoldTimer() {
@Override
public void perform() {
onLeftHold();
}
};
private HoldTimer middleHold = new HoldTimer() {
@Override
public void perform() {
onMiddleHold();
}
};
private HoldTimer rightHold = new HoldTimer() {
@Override
public void perform() {
onRightHold();
}
};
@Override
public final void mouseClicked(MouseEvent event) {
this.event = event;
switch (event.getButton()) {
case LEFT:
if (leftDouble.isRunning()) {
leftDouble.stop();
onLeftDoubleClick();
} else {
leftDouble.start();
onPureLeftClick();
}
break;
case MIDDLE:
if (middleDouble.isRunning()) {
middleDouble.stop();
onMiddleDoubleClick();
} else {
middleDouble.start();
onPureMiddleClick();
}
break;
case RIGHT:
if (rightDouble.isRunning()) {
rightDouble.stop();
onRightDoubleClick();
} else {
rightDouble.start();
onPureRightClick();
}
break;
}
}
@Override
public final void mousePressed(MouseEvent event) {
this.event = event;
pressedButton = event.getButton();
pressed = event.getComponent();
switch (event.getButton()) {
case LEFT:
leftHold.start();
onLeftPress();
break;
case MIDDLE:
middleHold.start();
onMiddlePress();
break;
case RIGHT:
rightHold.start();
onRightPress();
break;
}
}
@Override
public final void mouseReleased(MouseEvent event) {
this.event = event;
pressedButton = -1;
Component src = event.getComponent();
boolean contains = src.contains(event.getPoint());
switch (event.getButton()) {
case LEFT:
leftHold.stop();
onLeftRelease();
if (!dragging && src == pressed && contains) onLeftClick();
break;
case MIDDLE:
middleHold.stop();
onMiddleRelease();
if (!dragging && src == pressed && contains) onMiddleClick();
break;
case RIGHT:
rightHold.stop();
onRightRelease();
if (!dragging && src == pressed && contains) onRightClick();
break;
}
dragging = false;
}
@Override
public final void mouseMoved(MouseEvent event) {
this.event = event;
moved();
}
@Override
public final void mouseDragged(MouseEvent event) {
this.event = event;
dragging = true;
switch (pressedButton) {
case LEFT:
onLeftDrag();
break;
case MIDDLE:
onMiddleDrag();
break;
case RIGHT:
onRightDrag();
break;
}
}
@Override
public final void mouseEntered(MouseEvent event) {
this.event = event;
entered();
}
@Override
public final void mouseExited(MouseEvent event) {
this.event = event;
exited();
}
private int getDoubleClickInterval() {
String property = "awt.multiClickInterval";
return (int) Toolkit.getDefaultToolkit().getDesktopProperty(property);
}
private class DoubleClickTimer extends Timer {
public DoubleClickTimer() {
super(getDoubleClickInterval(), null);
this.setRepeats(false);
}
}
public int getHoldInitialDelay() {
return 300;
}
public int getHoldQueueDelay() {
return 60;
}
private class HoldTimer extends Timer {
public HoldTimer() {
super(getHoldQueueDelay(), null);
this.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
perform();
}
});
this.setInitialDelay(getHoldInitialDelay());
}
public void perform() {
}
}
public void moved() {
}
public void entered() {
}
public void exited() {
}
public void onLeftHold() {
}
public void onMiddleHold() {
}
public void onRightHold() {
}
public void onLeftClick() {
}
public void onMiddleClick() {
}
public void onRightClick() {
}
public void onPureLeftClick() {
}
public void onPureMiddleClick() {
}
public void onPureRightClick() {
}
public void onLeftDoubleClick() {
}
public void onMiddleDoubleClick() {
}
public void onRightDoubleClick() {
}
public void onLeftPress() {
}
public void onMiddlePress() {
}
public void onRightPress() {
}
public void onLeftRelease() {
}
public void onMiddleRelease() {
}
public void onRightRelease() {
}
public void onLeftDrag() {
}
public void onMiddleDrag() {
}
public void onRightDrag() {
}
}
最佳答案
正如《气垫船充满鳗鱼》在评论中指出的那样,这是You Aren't Gonna Need It的经典案例。在清楚地知道谁将使用功能以及何时禁止使用功能之前,先实施功能。在这种情况下,考虑到您在注释中概述的用例,您有几种选择:
在任何地方使用此类,并接受略高的开销。奇怪的是,您不太关心性能影响,这可能很小。但是,这的确在整个其余代码中引入了对该类的更大依赖,这意味着如果您以后引入回归,则有可能破坏大量相关系统。
允许该类的使用者指示他们将使用哪些功能(例如,双击)并禁用该使用者不想要的功能。这将复杂性引入了您的课堂,并使其更容易出错,并使测试更加困难(尽管几乎不可能)。如果在类之间非常需要一致性,则可以选择。
需要添加功能时,请使用此类,并在其他地方使用普通的MouseAdapter
。这可能是您的最佳选择,尤其是在自定义类中某些行为情况未明确定义的情况下。这样可以减少对类的依赖,并在内部简化类。权衡在消费者类之间如何处理鼠标交互方面的一致性较差,而为了为消费者实现MouseAdapter
的代码略多-通常是值得进行的权衡。
10-08 01:19