2017-07-04 25 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