Как я могу заставить качающийся JButton повторять свое действие, когда он удерживается?

Я создаю приложение с сенсорным экраном с помощью Swing, и у меня есть запрос на изменение одной из кнопок, чтобы она вел себя как клавиатура, когда кнопка удерживается нажатой.
(Прежде всего, я не уверен, что сенсорный экран будет разрешить пользователю «удерживать» кнопку, но пока делать вид, что могут)

Я собирался пойти по пути запуска цикла при вызове mousePressed и завершения цикла при вызове mouseReleased. Это потребует запуска потока и работы с синхронизацией, а также с invokeLater() для возврата событий на EventQueue.

Есть ли очень простой способ сделать то, что я хочу? Надеюсь, я просто не вижу API для этого.


person Tony Eichelberger    schedule 21.11.2008    source источник
comment
Нет простого способа. Я думаю, что то, что вы описали в потоке, выполняющем синхронизированный сон и опрос кнопки, является единственным способом.   -  person Paul Tomblin    schedule 21.11.2008


Ответы (4)


javax.swing.Timer — ваш друг . И вот статья с дополнительной информацией.

person ykaganovich    schedule 21.11.2008
comment
Ссылка на статью устарела. - person Christopher Bruns; 19.02.2013

Я бы сделал это так:

  • Слушайте mousePressed и запланируйте запуск java.util.Timer на более позднее время.
  • Таймер выполняет действие и снова устанавливает расписание.
  • Слушайте mouseReleased, чтобы отменить таймер.
person Cyrille Ka    schedule 21.11.2008

Я пошел с java.swing.Timer, так как он автоматически отправит обратно в Swing EventQueue, и это то, что я ищу. Спасибо за помощь.

person Tony Eichelberger    schedule 21.11.2008

Вот как вы можете сделать это, создав подкласс JButton:

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.SwingUtilities;

public class TypomaticButton extends JButton implements MouseListener {
    private boolean autotype = false;
    private static Thread theThread = null;
    private String myName = "unknown";
    private int 
        speed = 150, 
        wait = 300,
        decrement = (wait - speed) / 10; 

    TypomaticButton(Action action){
        super(action);
        myName = action.getValue(Action.NAME).toString();
        addMouseListener(this);
    }

    TypomaticButton(String text){
        super(text);
        setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));

        myName = text;
        addMouseListener(this);
    }

    @Override
    public void mouseClicked(MouseEvent arg0) {}

    @Override
    public void mouseEntered(MouseEvent arg0) { }

    @Override
    public void mouseExited(MouseEvent arg0) {  }

    @Override
    public void mousePressed(MouseEvent arg0) {
        autotype = true;
        theThread = new Thread(new Runnable() { // do it on a new thread so we don't block the UI thread
            @Override
            public void run() {
                for (int i = 10000; i > 0 && autotype; i--) { // don't go on for ever
                    try {
                        Thread.sleep(wait);     // wait awhile
                    } catch (InterruptedException e) {
                        break;
                    }
                    if(wait != speed){
                        wait = wait - decrement;        // gradually accelerate to top speed
                        if(wait < speed)
                            wait = speed;
                    }
                    SwingUtilities.invokeLater(new Runnable() { // run this bit on the UI thread
                        public void run() {
                            if(!autotype)   // it may have been stopped meanwhile
                                return;
                            ActionListener[] als = getActionListeners();
                            for(ActionListener al : als){   // distribute to all listeners
                                ActionEvent aevent = new ActionEvent(getClass(), 0, myName);
                                al.actionPerformed(aevent);
                            }
                        }
                    });
                }
                autotype = false;
            }
        });
        theThread.start();
    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
        autotype = false;
        wait = 300;
    }

    void speed(int millisecs){
        speed = millisecs;
        decrement = (wait - speed) / 10; 
    }

    void stop(){
        autotype = false;
        if(theThread != null){
            theThread.interrupt();
        }
    }

}

Тоже разгоняется.

Надеюсь, это поможет.

person Mike Lima    schedule 11.05.2016