如何让一个摇摆的JButton在按住时重复执行它的动作?

5
我正在使用Swing创建一个触摸屏应用,并且有一个请求要求更改其中一个按钮,以便在按住该按钮时它将像键盘一样工作。
(首先,我不确定触摸屏是否允许用户“按住”按钮,但现在假装他们可以)
我本来想通过在调用mousePressed时启动循环,然后在调用mouseReleased时结束循环来实现。 这将涉及启动线程并处理同步,以及使用invokeLater()将事件返回到EventQueue
是否有非常简单的方法来实现我的需求?我希望我没有看到实现它的API。

没有简单的方法。我认为你所概述的使用线程进行定时休眠和轮询按钮的方式是唯一的方法。 - Paul Tomblin
4个回答

9

该文章链接已失效。 - Christopher Bruns

5
我会这样做:
  • 监听 mousePressed 事件并安排 java.util.Timer 在稍后启动。
  • Timer 执行操作并设置自身再次调度。
  • 监听 mouseReleased 以取消 Timer。

0

以下是通过子类化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

我选择了java.swing.Timer,因为它会自动返回到Swing EventQueue,这正是我想要的。谢谢你的帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接