Как я могу сделать свинг JButton повторить свое действие, когда он удерживается? - PullRequest
5 голосов
/ 21 ноября 2008

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

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

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

Ответы [ 4 ]

9 голосов
/ 21 ноября 2008

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

5 голосов
/ 21 ноября 2008

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

  • Прослушайте mousePressed и запланируйте запуск java.util.Timer позднее.
  • Таймер выполняет действие и снова устанавливает расписание.
  • Прослушивание мыши. Выпущено для отмены таймера.
0 голосов
/ 11 мая 2016

Вот как вы можете сделать это, создав подкласс 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();
        }
    }

}

Он тоже ускоряется.

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

0 голосов
/ 21 ноября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...