マインスイーパを実装していますが、マウス イベントの処理に少し問題があります。(mousePressed ではなく) mouseRelease でアクションを実行したいので、ユーザーはマウス ボタンを押した後に気が変わることができます。次の 3 つのアクションがあります。
- LMB リリース - 現在のフィールドを表示
- RMB がリリースされました - 現在のフィールドにフラグを立てます
- LMB と RMB の両方がリリースされました - 隣接するフィールドをハイライトまたは表示します
アクションはそれほど重要ではありません。私が問題を抱えているのは、それらをトリガーする方法です。
ケース 1 と 2 では、他のボタンが押されていません。これは簡単に確認できます。
問題は、両方のボタンを離すと、mouseRelease メソッドが 2 回呼び出されることです。両方のボタンを離すまでの遅延が大きすぎる場合は、アクションをトリガーしないことをお勧めします。つまり、両方のボタンがほぼ同時に離された場合にのみトリガーする必要があります。
たとえば、ボタン 1 を放したときにボタン 3 が押されていることは簡単に確認できますが、あまり役に立ちません。
現時点では、最初のボタンが離された時間を保存し、それを別のボタンが離された時間と比較する以外に考えがありません。差が十分に小さい場合は、アクションをトリガーします。
System.currentTimeMillis() または System.nanoTime() で遊ぶという考えはあまり好きではありません。それを行うより良い方法があるかどうか疑問に思いますか?
解決:
問題を非常に単純化したのは、ユーザーがマウス ポインタを別のフィールドにドラッグできないようにすることでした (そのため、「選択された」フィールドが変更されました)。両方のボタンを放す間の遅延は問題ではありません。マウス ポインタが別のフィールドに移動すると、すべてがクリアされます。コード スニペットは次のとおりです。
private static final int B1DM = MouseEvent.BUTTON1_DOWN_MASK;
private static final int B3DM = MouseEvent.BUTTON3_DOWN_MASK;
private boolean bothWereDown = false;
@Override
public void mousePressed(MouseEvent e) {
// action if single button pressed
// in my case this is a sub-action of pressing both buttons
int both = B1DM | B3DM;
bothWereDown = (e.getModifiersEx() & both) == both;
if (bothWereDown) {
// action if both buttons pressed
}
}
@Override
public void mouseDragged(MouseEvent e) {
// some other code
if ( /* if pointer leaves field where mouse was pressed */) {
// some other code
bothWereDown = false;
// some other code
}
}
@Override
public void mouseReleased(MouseEvent e) {
// some other code
if (e.getButton() == MouseEvent.BUTTON1) {
if (bothWereDown) {
if ((e.getModifiersEx() & B3DM) != B3DM) {
// action if both released
}
} else {
// action if left button released
}
} else if (e.getButton() == MouseEvent.BUTTON3) {
if (bothWereDown) {
if ((e.getModifiersEx() & B1DM) != B1DM) {
// action if both released
}
} else {
// action if right button released
}
}
}