Java JTextField中的Highlight文本,但仅当使用制表符时
我想创建一个JDialog,在这里选择文本字段中的文本,但仅当焦点从键盘获得时(TAB,CTRL+TAB)。我在这个问题上找到了几个话题,但在实施上遇到了问题 这是我一直在尝试的 我的代码是:Java JTextField中的Highlight文本,但仅当使用制表符时,java,swing,tabs,jtextfield,selectall,Java,Swing,Tabs,Jtextfield,Selectall,我想创建一个JDialog,在这里选择文本字段中的文本,但仅当焦点从键盘获得时(TAB,CTRL+TAB)。我在这个问题上找到了几个话题,但在实施上遇到了问题 这是我一直在尝试的 我的代码是: public class Dialogg extends JDialog implements FocusListener, MouseListener { private boolean focusFromMouse = false; public Dialogg() { JTextFiel
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;
}
}
它不能按预期工作,无论文本始终突出显示的焦点来源是什么。当我运行代码并一步一步地跟踪它时,结果表明FocusGaund代码发生在MouseClick代码之前,因此标志不会在应该重置时重置。有什么提示吗
编辑:
根据普罗霍罗夫先生的建议,我已经从代码中删除了不太相关的(关于问题)行。谢谢
编辑2:
我正试图按照camickr的建议来包装focus listener。现在看起来是这样的:
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;
我在每次事件后都打印行以查看操作顺序,但最后还是鼠标点击了。我做错了什么
编辑3:
好的,我找到了一个满足我的简单对话框要求的解决方案。
我找不到使用invokeLater
或EventQueue
来实现这一点的方法。工作,但据我所知,它限制用户只使用键盘。
我使用了最初的方法,但我添加了一个辅助变量和一些条件,允许通过在给定时刻不应更改标志的事件传递标志“未受伤害”。它可能并不微妙或通用,但适用于我的应用程序。代码如下:
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;
}
当我运行代码并一步一步地跟踪它时,结果表明FocusGain代码发生在鼠标单击之前
将FocusListener
中的代码包装到SwingUtilities.invokeLater()
中。将把代码放在事件分派线程(EDT)的末尾,因此代码将在设置MouseListener中的变量后运行
有关EDT的更多信息,请参阅
编辑:
我注意到了另一个答案。你也许可以做一些简单的事情。Istead的侦听器已单击鼠标
,侦听已按下的鼠标
。mouseClicked事件仅在MouseRelease事件之后生成,因此此时FocusListener逻辑已经执行,即使添加到EDT的末尾也是如此
编辑2:
如果上述方法不起作用,则可以使用EventQueue.peek()
方法查看队列中是否有MouseEvent。这可能比担心调用器的使用更容易
当我运行代码并一步一步地跟踪它时,结果表明FocusGain代码发生在鼠标单击之前
将FocusListener
中的代码包装到SwingUtilities.invokeLater()
中。将把代码放在事件分派线程(EDT)的末尾,因此代码将在设置MouseListener中的变量后运行
有关EDT的更多信息,请参阅
编辑:
我注意到了另一个答案。你也许可以做一些简单的事情。Istead的侦听器已单击鼠标
,侦听已按下的鼠标
。mouseClicked事件仅在MouseRelease事件之后生成,因此此时FocusListener逻辑已经执行,即使添加到EDT的末尾也是如此
编辑2:
如果上述方法不起作用,则可以使用
EventQueue.peek()
方法查看队列中是否有MouseEvent。这可能比担心使用invokeLater更容易。首先,默认情况下,焦点在JTextField上是由鼠标按下事件而不是鼠标单击请求的
因此,这种方法:
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
无效,因为鼠标单击事件是在鼠标按下事件之后触发的
解决问题的一种方法是从JTextField中删除所有本机MouseListener:
...
for( MouseListener ml : tf1.getMouseListeners() ){
tf1.removeMouseListener(ml);
}
for( MouseMotionListener mml : tf1.getMouseMotionListeners() ){
tf1.removeMouseMotionListener(mml);
}
...
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if( event.getSource() == tf1 ){
((MouseEvent)event).consume();
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
另一种方法是处理所有鼠标事件并使用这些事件,这些事件由JTextField触发:
...
for( MouseListener ml : tf1.getMouseListeners() ){
tf1.removeMouseListener(ml);
}
for( MouseMotionListener mml : tf1.getMouseMotionListeners() ){
tf1.removeMouseMotionListener(mml);
}
...
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if( event.getSource() == tf1 ){
((MouseEvent)event).consume();
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
首先,默认情况下,鼠标按下事件而不是鼠标单击请求关注JTextField 因此,这种方法:
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
无效,因为鼠标单击事件是在鼠标按下事件之后触发的
解决问题的一种方法是从JTextField中删除所有本机MouseListener:
...
for( MouseListener ml : tf1.getMouseListeners() ){
tf1.removeMouseListener(ml);
}
for( MouseMotionListener mml : tf1.getMouseMotionListeners() ){
tf1.removeMouseMotionListener(mml);
}
...
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if( event.getSource() == tf1 ){
((MouseEvent)event).consume();
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
另一种方法是处理所有鼠标事件并使用这些事件,这些事件由JTextField触发:
...
for( MouseListener ml : tf1.getMouseListeners() ){
tf1.removeMouseListener(ml);
}
for( MouseMotionListener mml : tf1.getMouseMotionListeners() ){
tf1.removeMouseMotionListener(mml);
}
...
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if( event.getSource() == tf1 ){
((MouseEvent)event).consume();
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
我认为您可以安全地减少这个问题中的代码量,而不会失去它的意义。例如,仅使用单个面板作为示例,并跳过所有空侦听器方法。这样我们就更容易看到发生了什么,这意味着我们更容易帮助你。另请注意,如果您正在寻找提示,那么唯一实际存在的就是事件的
paramString
。试着检查一下,也许会有帮助。@M.Prokhorov:你测试过paramString了吗?为什么会有这个建议?@hoverfullofeels,不,我没有。这只是在黑暗中拍摄,老实说,我不认为Swing的设计者特别有兴趣在活动背景下提供此类信息,因此可能根本不可用,或者作为框架本身内部某些本地上下文对象的一部分提供。@M.Prokhorov:我可以告诉您,paramString
不会保存帮助OP的信息,但我同意您的观点,库不是为了轻松提取这些信息而构建的。我不知道是否存在相当大的混乱,主要是因为我的程序都不需要这个功能。我认为你可以安全地减少这个问题中的代码量,而不会失去它的意义。例如,仅使用单个面板作为示例,并跳过所有空侦听器方法。这样我们就更容易看到发生了什么,这意味着我们更容易帮助你。另请注意,如果您正在寻找提示,那么唯一实际存在的就是事件的paramString