【问题标题】:How to keep focus on JTextField. SwingWorker如何专注于 JTextField。摇摆工人
【发布时间】:2014-07-19 17:52:10
【问题描述】:

我需要继续关注 JTextField。应用程序使用 Swing 库。我需要不时关注该领域,以避免将焦点转移到其他组件的用户错误。我想我需要使用 SwingWorker。设置焦点是 Swing 上的一个操作 组件,因此应该在 EDT 中调用它。我的问题是如何编写 SwingWorker 来做到这一点? 我知道方法 done() 传递要在 EDT 中调用的任务,但我需要每隔 2 秒调用一次此任务。方法 done() 被调用一次。 那么这样的事情可能会好吗?

public class myWorker extends SwingWorker<Void, Void> {

@Override
protected Void doInBackground() throws Exception {
SwingUtilities.invokeLater(new Runnable() {
  @Override
  public void run() {
    //here set focus on JTextField
    return null;
  }
});
}}

编辑:

我注意到作为 SwingWorker 一部分的方法 process() 可能是合适的,因为它是在 EDT 中调用的。我不确定,但是当我调用 publish() 方法时,可能总是会调用此方法。那么你能告诉我这段代码是否可以有效地完成这项任务吗?

private class KeepFocusWorker extends SwingWorker<Void, Void>
{
    @Override
    protected Void doInBackground() throws Exception
    {
        while(true)
        {
            publish();
        }
    }

    @Override
    protected void process(List<Void> chunks)
    {
        codeBar.requestFocusInWindow();
    }
}

【问题讨论】:

  • “所以也许……” ..西斯?南?懒惰?键入单词的所有字母,而不是让人们猜测。
  • Focus 是用户的指南。与其推测一个糟糕的解决方案,不如解释你想要完成什么以及你尝试过什么。另请参阅How to Use Swing Timers
  • 好的。我编辑了我的帖子以使其更清晰。

标签: java multithreading swing swingworker swingutilities


【解决方案1】:

使用javax.swing.Timer 代替SwingWorker。在这种情况下,actionPerformed 将在 EDT 中执行。同样要在组件中设置焦点,您需要调用requestFocus。顾名思义,这只是一个请求,不能保证。所以你可以改变你的方法。

Timer timer = new Timer(2000, new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        codeBar.requestFocus();
    }
});

timer.setRepeats(true);
timer.start();

【讨论】:

  • 感谢您的建议。很高兴了解这个解决方案,但最后我决定应该尽可能频繁地完成这个任务(所以应该是 Thread 或 SwingWorker)。
  • SwingWorker 不适用于重复性任务。它是在工作线程中执行耗时的任务。要在 EDT 中重复执行代码,请使用 javax.swing.Timer。我已经为此更新了上面的代码。
【解决方案2】:

当然最好首先限制用户将注意力从文本字段中移开的能力?就我个人而言,我不明白为什么这是一个问题,但我认为最好将注意力集中在一个组件上,而不是让用户转移焦点,让它每隔几秒钟就转移回来。

因此,您可以向组件添加一个 FocusListener,覆盖 focusLost 方法,然后基本上再次 requestFocus()。

codeBar.addFocusListener(new FocusAdapter() {
    public void focusGained(FocusEvent e) {
    }
    public void focusLost(FocusEvent e) {
        codeBar.requestFocus();
    }
});

注意,我自己并没有真正尝试过,但不明白为什么它不起作用。

或者,您可以使用始终返回 falseInputVerifier 来防止焦点被转移。

【讨论】:

  • 谢谢您的建议。原因是我想在只有 2 个其他字段需要焦点时停止该线程。我的面板中有很多文本字段,但焦点仅在其中 2 个中可接受。但正如我们所知,还有很多其他方法可以放松焦点,因此线程可以避免这种情况。最后我决定使用 FocusListeners 并在任何其他组件上设置 setFocusable(false)
猜你喜欢
  • 2013-10-04
  • 2014-07-04
  • 2018-04-07
  • 2013-12-24
  • 2013-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
相关资源
最近更新 更多