Java: принудительно отсоединить / освободить JSlider от мыши при перетаскивании

#java #swing #mouse #drag #jslider

#java #swing #мышь #перетаскивание #jslider

Вопрос:

Я использую a JSlider для поиска аудиофайла в пользовательском приложении музыкального проигрывателя Java. Когда ползунок отпущен, проигрыватель переходит к соответствующему времени воспроизведения. Чего я хочу добиться, так это следующего: при ESCAPE нажатии во время перетаскивания ползунка я хочу, чтобы он был отпущен / отсоединен от курсора мыши и вернулся в исходное положение. Другими словами: я хочу прервать / остановить перетаскивание пользователя вручную.

Для достижения этой цели я попробовал следующее:

  1. вызов slider.setValue(initialValue)
  2. запуск пользовательского mouseReleased() события (даже если мышь все еще была нажата)
  3. запуск пользовательского windowDeactivated() события в основном фрейме, чтобы вывести ползунок из фокуса

Ничего не сработало. Ручка ползунка продолжает прилипать к мыши, пока я физически не отпущу ее. Есть ли какой-либо другой способ добиться этого?

 import java.awt.Dimension;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.BevelBorder;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;

public class DetachSlider {

    // true when slider is being dragged
    private boolean dragged;
    
    public static void main (String[] args) {
        new DetachSlider().initFrame();
    }
    
    public void initFrame() {

        JFrame frame = new JFrame();
        frame.setTitle("Detach Slider Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                
        JSlider slider = new JSlider();
        slider.setPreferredSize(new Dimension(500,50));
        slider.addMouseListener(new MouseHandler());
        slider.addKeyListener(new KeyHandler());
        
        JPanel panel = new JPanel();
        panel.setBorder(new CompoundBorder(new EmptyBorder(5,5,5,5), new BevelBorder(BevelBorder.LOWERED)));
        panel.add(slider);

        frame.setContentPane(panel);
        frame.setLocation(500,400);
        frame.pack();
        frame.setVisible(true);
    }

    // MouseListener for Slider
    private class MouseHandler extends MouseAdapter {
        public void mousePressed(MouseEvent me) {
            dragged = true;
        }
        public void mouseReleased(MouseEvent me) {
            dragged = false;
        }
    }
    
    // KeyListener for Slider
    private class KeyHandler extends KeyAdapter {
        public void keyPressed (KeyEvent ke) {
            if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) {
                JSlider slider = (JSlider)ke.getSource();
                if (dragged) {
                    System.out.println("ESCAPE pressed when slider is dragged");
                    slider.setValue(0);
                }
                else {
                    System.out.println("ESCAPE pressed when slider is idle");
                    slider.setValue(0);
                }
            }
        }
    }

}
 

Комментарии:

1. Я предлагаю вам отключить мышь в этот момент и подключить ее обратно — или схватить этого парня за руку. Или, еще лучше, удалите прослушиватель мыши и снова включите!!

2. Я попробовал это сделать. Я перебрал MouseListeners слайдера, их было 2: javax.swing. ToolTipManager и javax.swing.plaf.basic.BasicSliderUI $TrackListener. Я удалил их, но ползунок продолжал прилипать к мыши. Кроме того, мне было интересно, что даже после того, как я удалил все MouseListeners, я все еще мог перетаскивать ползунок с помощью мыши…

3. если бы вы могли создать упрощенную версию, мы могли бы попробовать — если у вас большое программное обеспечение, и вы полагаетесь на автоматизированные решения, тогда ок — иначе взгляните на свою программу и посмотрите, где добавлены слушатели мыши — это может быть вопрос синхронизации и т. Д. Я не слишком разбираюсь в тонкостях, Ноесли вы создадите модель, мы могли бы попробовать

4. Кажется, что очередь событий удерживает событие мыши при нажатии, и все, что происходит, будет выполнено впоследствии — это может стать немного сложнее, но вы можете прочитать в EventQueue — я не знаю, можно ли его как-то отменить, чтобы события были выпущены — читайте дальше!!!

5. Упомянутые MouseListeners являются слушателями OOTB, ничего пользовательского. Мое программное обеспечение огромно и сложно, но я добавил простой фрагмент кода, который показывает проблему. Если при перетаскивании ползунка нажать ESCAPE, ничего не произойдет. Если вы не перетаскиваете его, его значение устанавливается равным 0.

Ответ №1:

Хорошо, я думаю, у нас есть решение. Это делается для отправки события mouseRelease всем MouseListeners, прикрепленным к слайдеру. Следующим образом:

 MouseListener[] cs=slider.getMouseListeners();
MouseEvent me = new MouseEvent((JSlider)ke.getSource(), MouseEvent.MOUSE_RELEASED, 0, 0, 100, 100, 1, false);
for(MouseListener m:cs) m.mouseReleased(me);
 

Это происходит внутри метода нажатия клавиш.

Комментарии:

1. Вы справились с этим! Это делает свое дело. На самом деле я был действительно близок к одному из моих первоначальных подходов. Итак, ключ в том, чтобы отправить событие MOUSE_RELEASE всем подключенным MouseListeners, а не только пользовательскому. Большое вам спасибо за вашу помощь и веселого Рождества!