2017-06-13 7 views
0

私は下の図に示すUI /エディタを作成しました。テキストはStyledTextで表示されます。黒い線は実際にはLabelの線で描かれたカスタムボーダーです。SWT MouseDownイベントがカスタム選択コントロールであまりにも支配的です

unselected

selected

今、私の目標は、ユーザーがそれらを削除したり、それらに他の人を追加するControl Sを選択することを可能にする選択を提供することです。 2番目の画像は選択例を示しています。だから、すべての種類のMouseEventで始まりました。これは私が最初に考えたより複雑です。 MouseDownイベントは、私は、ユーザーがMouseMoveイベントは、マウスがリリースされるまでMouseDownイベントを発射した同じコントロールが含まれているので、選択したい他のControl Sを追跡することはできませんよどのControlに解雇され

。選択したControlの視覚的なフィードバックを提供するために、進行中の選択を追跡する必要があります。以下のコードは、動作を示す最小限の例を示しています。

public class Tester { 

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

     Composite comp = new Composite(shell, SWT.NONE); 
     comp.setLayout(new GridLayout(1, true)); 
     SelectionListener listener = new SelectionListener(); 

     StyledText text = new StyledText(comp, SWT.NONE); 
     text.setText("first text"); 
     attachListener(text, listener); 
     text = new StyledText(comp, SWT.NONE); 
     text.setText("second text"); 
     attachListener(text, listener); 


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

    private static void attachListener(Control control, Listener listener) { 
     if(control != null && !control.isDisposed()){ 
      control.addListener(SWT.MouseDown, listener); 
      control.addListener(SWT.MouseMove, listener); 
      control.addListener(SWT.MouseEnter, listener); 
      control.addListener(SWT.MouseUp, listener); 
     } 
    } 

    static class SelectionListener implements Listener { 

     Event lastEvent = null; 

     @Override 
     public void handleEvent(Event event) { 
      switch(event.type){ 

      case SWT.MouseDown: 
       lastEvent = event; 
       break; 

      case SWT.MouseMove: 
       if(lastEvent != null){ 
        if(event.widget == lastEvent.widget) 
         System.out.println("the same!!!"); 
        else 
         System.out.println("not the same!!!"); 
       } 
       break; 

      case SWT.MouseEnter: 
       //this also does not fire when MouseDown is fired 
       System.out.println("entering"); 
       break; 

      case SWT.MouseUp: 
       lastEvent = null; 
       break; 
      } 
     } 

    } 
} 

ですから、基本的に私は手助けをしています。たぶん、これを達成するためのより良い/より簡単な方法があります。私はまた、複数の選択をサポートするテーブルや他のコントロールで、これをswtがどうやって行っているのかを調べようとしていました。しかし、特定のコードを見つけるのは難しいし、テーブルなどのネイティブコントロールのネイティブメソッドを呼び出すこともあります。だから誰かがアイデアを持っていれば分かち合う。

+0

セクションを右にドラッグして複数のセクションを選択しますか? –

+0

はい、指定されたコントロール(ラベルとStyledTexts)にあります。現在、私が特定のコントロールを残した後、自分自身でMouseUpイベントを送信するアプローチに取り組んでいます。その後、他のすべてのイベントが再び発生します。 – lolung

答えて

0

私の問題の解決策が見つかりました。自分でMouseUpイベントを投稿できます。その後、すべてのイベントが再び行われます。唯一の難しい部分は、独自のカスタムイベントと通常のユーザー/システムイベントを区別することです。カスタムイベントを特定するための基準をいくつか作成したり見つけたりできました。次のコード/ドキュメントで詳しく説明しています。

/** 
    * Sets up a custom {@code SWT.MouseUp} event and fires it. This is needed because a {@code SWT.MouseDown} is consuming all 
    * other events until a {@code SWT.MouseUp} event is fired. This means that it is not possible to get a e.g. 
    * {@code SWT.MouseEnter} event when entering a certain StyledText which is needed for selection. Therefore a custom {@code SWT.MouseUp} 
    * event is fired to simulate the releasing of the button on system level so that all other events can come through again. The real problem here 
    * is to distinguish between the custom event for simulation and a normal event produced by the user. Firing the event via Display.post(Event) 
    * does not fire the handed over event parameter. The system actually creates a new event instance. Therefore 2 criteria are used to distinguish the custom event: 
    * <ul> 
    *  <ol>1. The selection can only be started by dragging a border control. 
    *   A {@code SWT.DragDetect} event starts the hole selection process. All events coming in before this event are ignored.</ol> 
    *  <ol>2. The actual distinguishing of the {@code SWT.MouseUp} is performed on the cursor coordinates and the referenced/dragged {@code widget}. 
    *   The dragging event has to be started on this widget.</ol> 
    * </ul> 
    * @param the starting {@code SWT.DragDetect} event 
    * @see #isCustomMouseUpEvent(Event) 
    */ 
    private void fireCustomMouseUpEvent(Event dragDetectEvent){ 
     customMouseUpEvent = new Event(); 
     customMouseUpEvent.type = SWT.MouseUp; 
     customMouseUpEvent.button = 1; //left mouse button 
     customMouseUpEvent.widget = dragDetectEvent.widget; 

     if(dragDetectEvent.widget instanceof Control){ 
      startingControl = (Control) dragDetectEvent.widget; 
      //get cursor location relative to widget to be comparable later with the event fired by the system 
      Point cursorLocation = startingControl.toControl(startingControl.getDisplay().getCursorLocation()); 
      customMouseUpEvent.x = cursorLocation.x; 
      customMouseUpEvent.y = cursorLocation.y; 
     } 

     /* 
     * note: set attributes like Event.data or Event.x are not present 
     * in the actually firing event. SWT or the system is creating a complete new 
     * event instance without those manually added information. 
     */ 
//  mouseUpEvent.data = SELECTION_START_EVENT_IDENTIFIER; 
     if(dragDetectEvent.widget.getDisplay().post(customMouseUpEvent)) 
      System.out.println("custom MouseUp event fired!"); 
    } 

    private boolean isCustomMouseUpEvent(Event event) { 
     return customMouseUpEvent != null && event.widget == customMouseUpEvent.widget && 
       customMouseUpEvent.x == event.x && customMouseUpEvent.y == event.y; 
    } 
+0

ちょうどこれを精巧にしたい。それはWindows上で動作しますが、Linux(Ubuntu)では動作しません。 SWTのDragAndDrop(DND)メカニズムを使用してカスタム選択を実装する方法を発見しました。これは、スクロールする実装(テキストとオートスクロールの選択)のSWT(少なくともStyledTextの場合)でも使用されます。また、StyledTextクラスにはマウスイベントのスクロールを実装したデッドコードがあります。私は最初に混乱し、このコードは決して呼び出されないことがわかりました(少なくともWindowsではそうではありません)。 – lolung

関連する問題