Swing игнорирует первый щелчок после уменьшения времени Windows - PullRequest
4 голосов
/ 28 сентября 2011

У меня есть приложение 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);
                }
            });
        }

    }

Ответы [ 2 ]

1 голос
/ 28 сентября 2011

Как видно здесь Свинг использует дату, чтобы проверить, когда произошло событие.Таким образом, в некотором смысле, вероятно, здесь действует обработчик, отменив свое действие, поскольку оно произошло «до» последнего действия.Я не могу вам это подтвердить, но, возможно, какой-то Менеджер по расположению или другой обработчик что-то здесь связывает, чтобы предотвратить возникновение отложенных событий с текущим потоком.

0 голосов
/ 29 сентября 2011

Я отладил его через Eclipse и выяснил, что происходит.

  • Часы в 15:00.
  • Нажмите на кнопку.Свинг записать время последнего события на 15:00.
  • Измените время на 14:00.
  • Нажмите на кнопку.Swing игнорирует событие, потому что оно выглядит как мульти-клик.

Проблема здесь в том, что сравнение, выполненное Swing при проверке мульти-клика, таково:

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

ЗдесьcurrentTime - lastTime дает отрицательное значение.Это меньше, чем 0 (мой 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.

The *У класса 1025 * есть setMultiClickThreshhold, но он выдает IllegalArgumentException в случае, если пороговое значение меньше 0.

Итак, в качестве обходного пути я сделал это:

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);
    }

}
...