如何在不窃取其事件的情况下在小部件上绘制一个矩形?

How can I draw a rectangle over a widget without stealing its events?

我正在尝试使用放置在 Gtk.Overlay 上的 Gtk.DrawingArea 来实现自定义对接解决方案,但是当我尝试在小部件的 drag_motion 期间显示 Gtk.DrawingArea 时] 事件触发 drag_leave 事件。这里的问题是我正在使用 drag_leave 事件来隐藏叠加层,这意味着我只是在光标移动时在可见性状态之间切换。如何防止叠加层在可见后触发底部小部件的 drag_leave 事件?

另外,有没有更有效的方法来对接?我应该使用 Gtk.Window 而不是 Gtk.DrawingArea 吗?在一个区域上绘制一个简单的矩形并在拖动项目时让它移动的最佳方法是什么?

using Gtk;
using Gdk;

public const Gtk.TargetEntry[] targets = {
    { "INTEGER", 0, 0 },
};

void main (string[] args) {
    Gtk.init (ref args);

    var window = new Gtk.Window ();
    window.set_default_size (400, 400);
    window.window_position = Gtk.WindowPosition.CENTER;

    var container = new Gtk.Overlay ();

    var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);

    container.add (box);
    var box_overlay = new Gtk.DrawingArea ();
    box_overlay.realize.connect (() => {
        box_overlay.get_window ().set_pass_through (true);
        box_overlay.hide ();
    });

    container.add_overlay (box_overlay);
    container.set_overlay_pass_through (box_overlay, true);

    var dest_drag_widget = new Gtk.Button ();
    dest_drag_widget.vexpand = true;
    var src_drag_widget = new Gtk.Button ();
    src_drag_widget.vexpand = true;

    Gtk.drag_source_set (src_drag_widget, Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY);
    Gtk.drag_dest_set (dest_drag_widget, Gtk.DestDefaults.MOTION, targets, Gdk.DragAction.COPY);

    dest_drag_widget.drag_motion.connect (() => {
        if (!box_overlay.visible) {
            print ("show\n");
            box_overlay.show ();
        }
        return false;
    });
    dest_drag_widget.drag_leave.connect (() => {
        if (box_overlay.visible) {
            print ("hide\n");
            box_overlay.hide ();
        }
    });

    box.add (dest_drag_widget);
    box.add (src_drag_widget);

    window.add (container);
    window.show_all ();

    Gtk.main ();
}

  1. 运行 以上与 valac --pkg gtk+-3.0
  2. 将底部按钮拖到顶部并四处移动
  3. 注意 "show" 和 "hide" 被多次打印。

我希望 "show" 和 "hide" 只打印一次。

编辑:

我尝试实现的总体效果类似于 Atom 编辑器如何定位其窗格。

我想正确的答案可能取决于您正在寻找什么样的效果。

您可以将源小部件渲染到 pixbuf 并调用 Gtk.drag_source_set_icon_pixbuf()1 将其设置为四处拖动。

您可以尝试从现有容器中取消源小部件的父级设置,然后将其重新添加到叠加层,然后使用绝对定位移动整个小部件。

或者使用 libdazzle 中现有的停靠小部件可能会更容易。

抱歉缺乏具体的建议!

好的,所以我想到了以下解决方案:

  1. 默认隐藏叠加层
  2. 将叠加层作为原始目标旁边的拖动目标
  3. 当用户拖动到原始目的地时,显示叠加层并告诉它通过传递原始目的地的矩形来处理 drag_motion
  4. 当光标离开矩形时隐藏叠加层

这可能有一些我尚未考虑的陷阱,但至少它有效。