【问题标题】:Java/SWT - Want to detect the Drop area in a SWT DnD operationJava/SWT - 想要在 SWT DnD 操作中检测 Drop 区域
【发布时间】:2014-11-04 11:24:05
【问题描述】:

大家好 Stackoverflow !

我正在为项目管理工具实现 Java RCP 插件,使用 SWT 并接近 MVC 逻辑。

我需要制作一种时序时间表,其中可以拖放里程碑(项目管理中的某种截止日期事件)。

我使用几个 SWT 标签实现了这一点(基本上,水平线上的 36 个标签数组,一年中每月 3 个)。

这是实际 GUI 的屏幕截图:

用户必须从拖动标签(左侧的 (X))中拖动里程碑,并将其放在所需的标签/月份的部分上。然后,目前唯一的作用是将放置目标标签的文本字段设置为 (X)。

我创建了 2 个“模型”类:一个 Milestone 类(稍后将使用其他元素进行改进,例如有关在此日期必须完成的项目的信息)和一个类 Square(广场有与放置标签链接)。 Square 类的特点:

  • boolean isEmpty(检查标签或方块是否已经有里程碑)
  • int nbMilestone(标签/正方形上的里程碑数)
  • int id(0到35之间的标签或方块的编号)

里程碑类功能:

  • 年份(获取当前年份)
  • positionId(里程碑被放置在哪个标签或方块上)

我想要的是当用户在标签上拖放里程碑时,它会更新 Milestone 和 Square 类,至少包含位置信息。我很难获得信息用户在哪个标签上放弃了里程碑?

这 36 个标签是在 for(;;) 循环中创建的,在此循环中包含一些拖放侦听器。


编辑#2:这是我的实际代码:

    // Drag source label in order to create milestones by a Drag'n'Drop
    // operation
    final Label milestone_drag_label = new Label(compA, SWT.NONE);
    milestone_drag_label.setText("(X)");
    milestone_drag_label.setData("milestone", milestone);

    // Setting up the Drag Listener for the milestone label
    DragSource ds_ms_label = new DragSource(milestone_drag_label,
            DND.DROP_MOVE);
    ds_ms_label.setTransfer(new Transfer[] { TextTransfer.getInstance() });
    ds_ms_label.addDragListener(new DragSourceAdapter() {
        public void dragSetData(DragSourceEvent event) {
            // event.data = milestone_drag_label.getText();
            event.data = (Milestone) event.widget.getData("milestone");
            from_ms_label = true;
        }
    });

    // Display configuration for the labels (3 labels per months, so they're
    // called
    // third, as third of a month)
    GridData gd_third = new GridData();
    gd_third.grabExcessHorizontalSpace = true;
    gd_third.widthHint = 15;

    for (w = 0; w < 36; w++) {

        final Label third = new Label(compA, SWT.BORDER);
        third.setLayoutData(gd_third);
        board[w] = third;
        square[w] = new Square();
        square[w].setId(w);

        third.setData("square", square);

        DropTarget dt = new DropTarget(board[w], DND.DROP_MOVE);
        // DropTarget dt = new DropTarget(third, DND.DROP_MOVE);
        dt.setTransfer(new Transfer[] { TextTransfer.getInstance() });
        dt.addDropListener(new DropTargetAdapter() {
            public void drop(DropTargetEvent event) {
                if (event.data == null) {
                    event.detail = DND.DROP_NONE;
                } else {
                    // third.setText((String) event.data);
                    Milestone milestone = (Milestone) event.data;
                    Square square = event.widget.getData("square");
                    milestone.setPositionId(square.getId());
                    printMilestone(milestone);
                }
            }
        });

printMilestone() 方法最后只是将属性 year 和 positionId 写入 .txt 文件。

我在线路上遇到错误:Square square = event.widget.getData("square");

所以我添加了演员表:Square square = (Square) event.widget.getData("square");

但是当我运行我的 RichClient 应用程序时,我收到了这个错误:

org.eclipse.swt.SWTException:数据的格式不正确 输入

【问题讨论】:

  • “标签文本字段上的添加修饰符”是什么意思?每个可能的放置目标都由一个Label 小部件表示,对吧?还是您使用Text 小部件?
  • 是的,我使用 36 个标签作为放置目标(全部在一行中)。这样声明:Label[] board = new Label[36];然后在 drawView() 方法中,我使用 for(;;) 循环实例化这 36 个标签,每次创建一个拖放侦听器。我想将这些标签链接到我的 Square 和 Milestone bean。换句话说,如何获取有关里程碑已被删除的标签的信息?
  • third.setData("square", square);应该是third.setData("square", square[w]);

标签: java drag-and-drop swt rcp


【解决方案1】:

据我了解:用户应该能够拖动用作拖动源的 里程碑 标签并将其放在 36 个非里程碑标签之一上仅作为投放目标。因此,应该更新与放置目标标签关联的模型元素。

所有里程碑标签都应该有一个拖动监听器,不需要放置监听器,因为它们从不用作放置目标。 所有 36 个标签都应该分配一个下拉监听器,它们不用作拖动源,因此不需要拖动监听器。 要了解基本的拖放功能是如何工作的,我认为this snippet 会有所帮助。

要将标签与其各自的模型元素相关联,您可以使用Map 或使用setData()

创建里程碑标签的代码如下所示:

Labe label = new Label( ... );
label.setData( "milesone", milestone );
label.addDragListener ( new DragSourceListener () {
  @Override
  public void dragSetData( DragSourceEvent event ) {
    event.data = ( Milestone )event.widget.getData( "milestone" );
  }
  @Override
  public void dragFinished( DragSourceEvent event ) {
    // mark the milestone label as 'assigned' if desired
  }
} );

每个 square 标签的代码如下所示:

Label label = new Label( ... );
label.setData( "square", square );
label.addDropListener ( new DropTargetAdapter() {
  @Override
  public void drop( DropTargetEvent event ) {
    if( event.data == null ) {
      event.detail = DND.DROP_NONE;
    } else {
      Milestone milestone = ( Milestone )event.data;
      Square square = event.widget.getData( "square" );
      milestone.setPositionId( square.getId() ); // or whatever it takes to update the model
      // update label text if necessary
    }
  }

上面的 sn-ps 使用setData() 来关联模型元素和小部件,同样适用于Maps。

还有more DnD snippetsarticle 和出色的DnD Example,可让您详细了解所有小部件的 DnD 机制并尝试不同的设置。

【讨论】:

  • 我编辑了我的第一条消息,我不得不承认它不够清楚!
  • 重新阅读更新后的问题后,我详细修改了我的答案,但一般方法应该有效。答案到底哪里不合适?
  • 其实你是对的,你的回答已经足够好了!但是仍然有一些东西不起作用,似乎无法向标签添加拖放侦听器。唯一可用的方法是 addDragDetectListener,但我更愿意为 drop 操作添加监听器,这样应该更安全。
  • 我添加了一个简短的编辑,其中包含您感激地编写的代码 sn-ps,如果您对我收到的错误有任何想法,也将不胜感激。
猜你喜欢
  • 2013-10-16
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多