2016-07-04 26 views
-1

我有一個Composite包含一些Text控件。我已將MouseListeners附加到每個控件。爲什麼我會從控件邊界之外的位置獲取MouseDown事件?

有什麼令我驚訝的是,有時候,當我點擊一個控件時,我從它的鄰居那裏得到一個MouseDown事件。事件的位置在控件的邊界之外,並且我沒有從我認爲我點擊過的另一個控件中獲得事件。

什麼會導致這種情況發生?

代碼片段

運行。按Esc關閉消息框。點擊字段BBBB。按Esc關閉MessageBox。點擊字段AAAA。該事件從字段BBBB生成。

public class Test 
{ 
    public class MyListener implements MouseListener, FocusListener 
    { 
     private boolean active; 

     @Override 
     public void focusGained(FocusEvent e) 
     { 
      System.out.println(e); 
      message((Text) e.widget, "FocusGained"); 
     } 

     @Override 
     public void focusLost(FocusEvent e) 
     { 
      System.out.println(e); 
     } 

     @Override 
     public void mouseDoubleClick(MouseEvent e) 
     { 
     } 

     @Override 
     public void mouseDown(MouseEvent e) 
     { 
      System.out.println(e); 
     } 

     private void message(final Text t, final String m) 
     { 
      if (active == false) 
      { 
       active = true; 
       MessageBox mb = new MessageBox(t.getShell()); 
       mb.setText(m); 
       mb.setMessage(t.getMessage() + "\n\n" + m); 
       mb.open(); 
       active = false; 
      } 
     } 

     @Override 
     public void mouseUp(MouseEvent e) 
     { 
      System.out.println(e); 
      message((Text) e.widget, e.toString()); 
     } 
    } 

    private MyListener listener = null; 

    public static void main(String[] args) 
    { 
     Display display = new Display(); 
     Shell shell = new Shell(display); 
     new Test(shell); 
     shell.open(); 
     while (!shell.isDisposed()) 
     { 
      if (!display.readAndDispatch()) 
       display.sleep(); 
     } 
     display.dispose(); 
    } 

    public Test(Composite parent) 
    { 
     listener = new MyListener(); 
     create(parent); 
    } 

    private void create(Composite parent) 
    { 
     parent.setLayout(new GridLayout(2, true)); 
     createText(parent, "AAAA"); 
     createText(parent, "BBBB"); 
     parent.layout(true); 
    } 

    private Text createText(Composite parent, String message) 
    { 
     Text t = new Text(parent, SWT.NONE); 
     t.setMessage(message); 
     GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); 
     t.setLayoutData(gd); 
     t.addFocusListener(listener); 
     t.addMouseListener(listener); 
     return t; 
    } 
} 
+0

嗨保羅,我假設你在Eclipse中使用WindownBuilder插件?有時它會產生錯誤的位置,而不是您在設計視圖中看到的位置。如果控制重疊,它們也可能導致這種失誤。 – bigneo

+1

你能提供一個獨立的片段來展示你的desribe嗎? –

+0

「x」和「y」位置是相對於小部件的,即基於小部件的左上角。你確定你看到的是在widget外面發生的事情嗎? 'MouseEvent#widget'指的是什麼? – Baz

回答

1

這確實很奇怪。當從B遍歷到A時,MouseUp事件被標記爲從字段B發送。

如果將MessageBox替換爲不中斷事件,即System.out,則鼠標事件發送者是正確的。

對我而言,這似乎更像是一個理論性的案例。體面的應用程序不會使用模式窗口中斷用戶字段遍歷。但是,如果這與你有關,我會report a bug to SWT

+0

查看我的解決方案。應用程序想要一個彈出式鍵盤。我已經從Text控件事件中解耦彈出。這似乎是問題所在。你認爲錯誤報告是合適的嗎? – paul

+0

從焦點處理POV開始,您的解決方案與完全不調用MessageBox相同 - 即它不會妨礙您的工作。是的,我認爲一個錯誤報告是適當的。 –

0

我設法通過從事件中分離彈出窗口來實現此功能。該message方法現在看起來是這樣的:

private void message(final Text t, final String m) 
{ 
    //NB active is declared as 'volatile' 
    if (active == false) 
    { 
     active = true; 
     t.getDisplay().asyncExec(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       MessageBox mb = new MessageBox(t.getShell()); 
       mb.setText(m); 
       mb.setMessage(t.getMessage() + "\n\n" + m); 
       mb.open(); 
       active = false; 
      } 
     }); 
    } 
    else 
    { 
     System.out.println("Already active: " + t.getMessage()); 
    } 
} 

這似乎給事件的機會,在彈出的窗口中繼續不間斷。彈出窗口將在稍後激活。到目前爲止,它工作正常。

+0

請注意,沒有必要將'active'聲明爲volatile。仍然只涉及單個線程。當像這裏一樣從UI線程調用asyncExec()時,可運行程序只是添加到消息隊列的末尾。 –

相關問題