2012-09-13 44 views
2

考慮下面的Java(SWT)碼選擇和輸入之間的區別:SWT:在組合

private static ComboViewer createViewer(final Shell shell) { 
    final ComboViewer v = new ComboViewer(shell, SWT.DROP_DOWN); 
    v.setLabelProvider(new LabelProvider()); 
    v.setContentProvider(new ArrayContentProvider()); 
    v.setInput(new String[]{"value 1", "value 2"}); 
    return v; 
} 

public static void main(final String[] args) { 
    Display display = new Display(); 
    Shell shell = new Shell(display); 
    shell.setSize(200, 60); 
    shell.setLayout(new GridLayout()); 

    final ComboViewer v = createViewer(shell); 

    // This wires up the userSelectedSomething method correctly 
    v.addSelectionChangedListener(new ISelectionChangedListener() { 
    @Override 
    public void selectionChanged(final SelectionChangedEvent event) { 
     userSelectedSomething(); 
    } 
    }); 

    shell.open(); 
    while (!shell.isDisposed()) { 
    if (!display.readAndDispatch()) { 
     display.sleep(); 
    } 
    } 
    display.dispose(); 
} 

public static void userSelectedSomething() { 
    // This should be called *only if* the user selected from the drop-down 
} 

public static void userTypedSomething() { 
    // This should be called *only if* the user typed in the combo 
} 

我想打電話給userTypedSomething方法,只有當用戶鍵入到組合(而不是當他們選擇從下拉菜單中)。我應該添加什麼樣的聽衆來實現這個目標?在組合查看器中使用v.getCombo().addModifyListener(...)添加修改偵聽器是不行的,因爲這是從組合中鍵入和選擇觸發的。

回答

2

既然你想聽鍵盤輸入,我建議你聽聽SWT.KeyUp

這應該是一個很好的起點:

public static void main(String[] args) { 
    final Display display = new Display(); 
    final Shell shell = new Shell(display); 
    shell.setLayout(new FillLayout()); 

    final Combo combo = new Combo(shell, SWT.NONE); 

    combo.add("First"); 
    combo.add("Second"); 

    combo.addListener(SWT.Selection, new Listener() { 

     @Override 
     public void handleEvent(Event arg0) { 
      System.out.println("Selected: " + combo.getItem(combo.getSelectionIndex())); 
     } 
    }); 

    combo.addListener(SWT.KeyUp, new Listener() { 

     @Override 
     public void handleEvent(Event arg0) { 
      System.out.println("Typed"); 
     } 
    }); 

    shell.pack(); 
    shell.open(); 
    while (!shell.isDisposed()) { 
     if (!display.readAndDispatch()) { 
      display.sleep(); 
     } 
    } 
    display.dispose(); 
} 
+0

可悲的是沒有。使用v.getCombo()。addVerifyListener添加驗證偵聽器會導致偵聽器被觸發(兩次!),以便從下拉列表中選擇以及一次用於鍵入。可以說這是JFace修復的錯誤... –

+0

@DavidNorth再次檢查我的答案。我添加了一個代碼片段。你將不得不檢查事件的「文本」的長度。用戶輸入的長度應該等於1.正如我所說的,這不是最佳的,而是一個起點。 – Baz

+0

@DavidNorth再次編輯答案。您可以使用'SWT.KeyUp'事件來觀看鍵盤輸入。 – Baz

4
private static ComboViewer createViewer(final Shell shell) { 
    final ComboViewer v = new ComboViewer(shell, SWT.DROP_DOWN); 
    v.setLabelProvider(new LabelProvider()); 
    v.setContentProvider(new ArrayContentProvider()); 
    v.setInput(new String[]{"value 1", "value 2"}); 
    return v; 
    } 

    private static boolean userTyped; 
    private static int index = -1; 

    public static void main(final String[] args) { 
    Display display = new Display(); 
    Shell shell = new Shell(display); 
    shell.setSize(200, 60); 
    shell.setLayout(new GridLayout()); 

    final ComboViewer v = createViewer(shell); 
    /* 
    * invoked multiple times when combo selection happens 
    * invoked once when user types 
    */ 
    v.getCombo().addVerifyListener(new VerifyListener() { 



     @Override 
     public void verifyText(VerifyEvent e) { 
     userTyped = (e.keyCode != 0); 
     } 
    }); 



v.getCombo().addModifyListener(new ModifyListener() { 

    @Override 
    public void modifyText(ModifyEvent e) { 

    Combo c = (Combo)e.widget; 

    if(userTyped || index == c.getSelectionIndex() || c.getSelectionIndex() == -1) 
    { 
     userTypedOrEditedSomething(); 
    } 
    index = c.getSelectionIndex(); 
    } 
}); 

    // This wires up the userSelectedSomething method correctly 
    v.addSelectionChangedListener(new ISelectionChangedListener() { 
     @Override 
     public void selectionChanged(final SelectionChangedEvent event) { 
     userSelectedSomething(); 
     } 
    }); 

    shell.open(); 
    while (!shell.isDisposed()) { 
     if (!display.readAndDispatch()) { 
     display.sleep(); 
     } 
    } 
    display.dispose(); 
    } 

    public static void userSelectedSomething() { 
    // This should be called *only if* the user selected from the drop-down 
    System.out.println("User selected"); 
    } 

    public static void userTypedOrEditedSomething() { 
    // This should be called *only if* the user typed in the combo 
    System.out.println("User typed or edited"); 
    } 

我會建議你使用驗證事件,而不是關鍵,作爲你可能endup處理很多事情(箭頭鍵,魔鍵...等等)。驗證也是關鍵事件,但它會過濾掉ALT,CNTRL,組合的。當用戶類型只檢查鍵碼!= 0。

正如您所指出的,當您使用CNTRL + V時,右鍵單擊菜單粘貼....組合不會將其視爲關鍵事件,但會觸發驗證事件以確保剪貼板文本對於組合是否有效。我認爲這是應該如何工作的,因爲組合菜單項選擇和按鍵事件是不同的事情。 您可以隨時監控所有關鍵事件,以執行復制/粘貼/刪除等特殊操作。

上面的示例代碼應該能夠執行你正在尋找的東西。

+0

謝謝,看起來可能可行。如果Eclipse沒有迴應我的錯誤,我會嘗試你的方法。 –