4

私は日付と時刻を処理するSwingアプリケーションを持っているので、システムの日付と時刻の設定を変更して多くのテストが行​​われます。テスト中に、クロックを減らした後、最初のクリックがアプリケーションによって無視されることに気付きました。

Swing / Java / Windowsのバグですか?これに対する回避策はありますか?

興味深いことに、この問題は、日付/時刻の設定を減らした場合にのみ発生します。増やすと、アプリケーションは正常に動作します。

状況:

  • 実行中のSwingアプリケーション。
  • Windowsの日付と時刻の設定を減らします(たとえば、時刻を15:00から14:00に変更します)。
  • Swingアプリケーションを最初にクリックしても、アクションは発生しないことに注意してください。

コード例(状況を証明するために使用できます):

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    import javax.swing.JButton;
    import javax.swing.JFrame;

    public class Main {

        public static void main(String[] args) {
            final JFrame frame = new JFrame("frame");
            final JButton button = new JButton("button");
            button.addActionListener(new ActionListener() {

                public void actionPerformed(final ActionEvent e) {
                    System.out.println("Button Pressed!");
                }
            });

            frame.add(button);
            frame.setSize(200, 200);
            frame.setVisible(true);
            frame.addWindowListener(new WindowAdapter() {

                @Override
                public void windowClosing(final WindowEvent e) {
                    System.exit(0);
                }
            });
        }

    }
4

2 に答える 2

1

ここに見られるように、Swingは日付を使用してイベントがいつ発生したかを確認します。したがって、何らかの方法で、最後のアクションの「前」に発生したため、おそらくハンドラーがアクションを破棄することによってここでアクションを実行しています。これを確認することはできませんが、おそらく、遅延イベントが現在のフローを台無しにするのを防ぐために、一部のレイアウトマネージャーまたは別のハンドラーがここで何かを台無しにしています。

于 2011-09-28T14:46:03.673 に答える
0

Eclipseを介してデバッグし、何が起こっているのかを調べました。

  • 15時の時計。
  • ボタンをクリックします。前回のイベントタイムを15:00までスイング記録。
  • 時計を14:00に変更します。
  • ボタンをクリックします。マルチクリックのように見えるため、Swingはイベントを無視します。

ここでの問題は、マルチクリックのSwingチェックによって行われた比較が次のとおりであるということです。

if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {
    shouldDiscardRelease = true;

ここで、currentTime - lastTimeは負の値になります。0(my )よりも小さいmultiClickThreshholdため、アクションイベントは発生しません。

public void mouseReleased(MouseEvent e) {
    if (SwingUtilities.isLeftMouseButton(e)) {
        // Support for multiClickThreshhold
        if (shouldDiscardRelease) {
            shouldDiscardRelease = false;
            return;
        }
        AbstractButton b = (AbstractButton) e.getSource();
        ButtonModel model = b.getModel();
        model.setPressed(false);
        model.setArmed(false);
    }
}

上記のすべてのソースはにありjavax.swing.plaf.basic.BasicButtonListenerます。

Buttonクラスにはがありますが、しきい値が。未満の場合setMultiClickThreshholdにスローされます。IllegalArgumentException0

したがって、回避策として、私はこれを行いました:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.Field;

import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Main {

    public static void main(String[] args) throws Exception {
        final JFrame frame = new JFrame("frame");
        final JButton button = new JButton("button");
        removeMulticlickThreshold(button);

        button.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e) {
                System.out.println("Button Pressed!");
            }
        });

        frame.add(button);
        frame.setSize(200, 200);
        frame.setVisible(true);
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(final WindowEvent e) {
                System.exit(0);
            }
        });
    }

    private static void removeMulticlickThreshold(final JButton button) throws Exception {
        final Field multiClickThreshhold = AbstractButton.class.getDeclaredField("multiClickThreshhold");
        multiClickThreshhold.setAccessible(true);
        multiClickThreshhold.set(button, Long.MIN_VALUE);
    }

}
于 2011-09-29T11:34:40.650 に答える