2017-07-04 23 views
0

我想创建一个JDialog,其中文本字段中的文本被选中,但仅当从键盘(TAB,CTRL + TAB)获得焦点时才被选中。我已经在这个问题上找到了几个主题,但是在实现它时遇到了问题。JTextField中的Higlight文本,但仅当Tab键时

Here是我正在尝试的一种。

而且我的代码:

public class Dialogg extends JDialog implements FocusListener, MouseListener { 

private boolean focusFromMouse = false; 

public Dialogg() { 
    JTextField tf1 = new JTextField("text1"); 
    JTextField tf2 = new JTextField("text2"); 

    tf1.addMouseListener(this); 
    tf2.addMouseListener(this); 
    tf1.addFocusListener(this); 
    tf2.addFocusListener(this); 
} 

@Override 
public void focusGained(FocusEvent e) { 
    if (!focusFromMouse) { 
     JTextField tf = (JTextField) e.getComponent(); 
     tf.selectAll(); 
     focusFromMouse = true; 
    } 
} 

@Override 
public void focusLost(FocusEvent e) { 
    focusFromMouse = false; 
} 

@Override 
public void mouseClicked(MouseEvent e) { 
    focusFromMouse = true; 
} 

}

按预期它不工作,也无所谓什么是重点源文本处处彰显。当我运行代码并按照步骤进行操作时,事实证明focusGained代码发生在mouseClicked代码之前,因此该标志在应该时不会被重置。任何提示?

编辑:从code.Thank你

至于建议由M.普罗霍罗夫我已经删除了相关性较低(对于这个问题)线。

编辑2:

我试图总结的焦点侦听器由camickr的建议。它现在看起来像这样:

tf1.addFocusListener(new FocusAdapter() { 
     public void focusGained(FocusEvent evt){ 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
         if (!focusFromMouse){ 
         tf1.selectAll(); 
         focusFromMouse=true; 
        }       
       }     
      }); 
     } 
     public void focusLost(FocusEvent evt){ 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        focusFromMouse=false; 
       } 
      }); 
     } 
    }); 
public void mouseClicked(MouseEvent e) { 
     focusFromMouse=true;   

我在每个事件之后打印行以查看操作顺序,仍然是mouseClicked最后发生。我究竟做错了什么?

编辑3:

OK,我发现它满足我简单的对话框的需求的解决方案。 我找不到使用invokeLaterEventQueue的方法。 Vladislav's method的作品,但据我了解,限制用户只使用键盘。 我已经使用了最初的方法,但我添加了一个辅助变量和几个条件,允许通过标志“不受伤害”低谷在给定时刻不应更改标志的事件。它可能不是微妙的或普遍的,但适用于我的应用程序。下面是代码:

public void focusGained(FocusEvent e) { 
    if(!focusFromMouse){ 
     if (higlight){ 
      JTextField tf = (JTextField) e.getComponent(); 
      tf.selectAll(); 
      focusFromMouse=false;  
     } 
    }   
} 

public void focusLost(FocusEvent e) { 
    if (focusFromMouse){ 
     higlight=false; 
     focusFromMouse=false; 
    }else{ 
     higlight=true;  
    } 
} 

public void mousePressed(MouseEvent e) { 
    focusFromMouse=true;  
} 
+1

我认为你可以安全地减少这个问题的代码量而不会失去它的含义。例如,仅使用单个面板作为示例,并跳过所有空的侦听器方法。通过这种方式,可以更容易地看到会发生什么,这意味着我们可以更容易地为您提供帮助。另请参见[最小,完整和可验证的示例](https://stackoverflow.com/help/mcve) –

+0

除此之外,如果您正在寻找提示,那么唯一真实的是事件的'paramString'。尝试检查一下,也许它会有所帮助。 –

+0

@ M.Prokhorov:你测试过paramString,看它是否有帮助吗?为什么这个建议? –

回答

1

当我运行的代码,并按照它一步一步事实证明,focusGained代码的mouseClicked

裹在SwingUtilities.invokeLater()代码在FocusListener之前发生。该代码将放置在事件分派线程(EDT)的末尾,因此代码将在MouseListener中的变量设置完成后运行。

有关EDT的更多信息,请参阅Concurrency in Swing

编辑:

刚注意到另一个答案。你可能可以做更简单的事情。倾听mouseClicked,倾听mousePressed。 mouseClicked事件仅在mouseReleased事件之后生成,因此到那时FocusListener逻辑已经执行,即使添加到EDT的末尾。

编辑2:

如果以上不工作,那么您可能能够使用EventQueue.peek()方法,看看是否的MouseEvent在队列中。这可能比担心使用invokeLater更容易。

+0

谢谢你的回答,请在我的原帖中看看EDIT2。 – stalko

+0

@stalko,请参阅编辑: – camickr

1

首先,默认情况下,通过鼠标按下事件请求关注JTextField,而不是通过鼠标单击。

所以,这个方法:因为鼠标点击事件,鼠标按下事件后触发

public void mouseClicked(MouseEvent e) { 
    focusFromMouse = true; 
} 

是没用的。

一个为您解决问题的方法是从JTextField中删除所有本地MouseListeners:

... 
for(MouseListener ml : tf1.getMouseListeners()){ 
    tf1.removeMouseListener(ml); 
} 

for(MouseMotionListener mml : tf1.getMouseMotionListeners()){ 
    tf1.removeMouseMotionListener(mml); 
} 
... 

另一种方式是处理所有的鼠标事件,并消耗这些人,这是由JTextField中触发:

Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { 
    @Override 
    public void eventDispatched(AWTEvent event) { 
    if(event.getSource() == tf1){ 
     ((MouseEvent)event).consume(); 
    } 
    } 
}, AWTEvent.MOUSE_EVENT_MASK); 
+0

(1+)注意OP正在侦听mouseClicked。 – camickr