GTK检测用户调整窗口大小

18

在GTK (或pygtk或gtkmm...)中

我要如何检测到应用程序窗口已被用户手动调整大小,通常是通过拖动窗口的边缘完成的?

我需要找到一种方法来区分手动调整大小和源自GTK的调整大小,例如窗口内容的更改。


你想到了一种方法来做这件事吗? - clahey
不,如果我这样做,它会显示在这里。 - Drew Dormann
5个回答

8
你尝试过连接GDK_CONFIGURE事件吗?
在“移动窗口”部分查看此示例。 示例展示了一个回调函数在窗口移动时执行某些操作,但是configure事件可以捕获移动、调整大小和堆栈顺序等所有事件。

2
以下代码可解决此问题: g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(callback_func), NULL); - Sean
1
我认为你可以使用“check-resize”而不是“configure-event”。 - boldnik
但是这并没有提供一种检查事件类型(调整大小或移动)的方法。所以如果用户没有找到某种确定方式,这将产生虚假结果。@boldnik:根据此文,这样做行不通,因为它会因为各种其他原因而触发:https://ubuntuforums.org/showthread.php?t=1100803&p=6927690#post6927690 - underscore_d
给定的链接已失效,编辑队列已满。这是示例的当前链接:http://zetcode.com/gui/gtk2/ - Romário
@boldnik 我这边不断触发check_resize。我认为configure-event很可能是正确的方向。 - Melroy van den Berg

7
我通过监听 GtkWindow 的 size_allocate 和 size_request 信号来实现了这一点。如果 size_request 变小,我调用 resize(1,1)。如果 size_allocate 比预期的大,我关闭系统。
我确保处理了 size_request 先返回大值,然后是小值,而 size_allocate 先变大再变小的情况,但我不知道这是否可能发生。我通过确保只在获得更小的 size_allocate 时才减少 size_allocate 的预期值(而不是在获得更小的 size_request 时),来解决这个问题。
确保你的 size_request 处理程序在基类处理程序之后执行,以便你得到正确的值。我通过覆盖方法并首先调用基类方法来实现这一点。
我尝试过在一维和二维中使用此方法,它似乎可以在任何情况下都工作。

5
在我的情况下,我试图区分用户调整 Gtk.Paned 与用户调整整个窗口的操作。两者都会发出 notify::position 信号。
我的解决方案是,由于无法知道用户是否从窗口小部件中调整了窗口大小,因此反转我想要知道的内容。记录用户是否重新定位了窗口小部件,如果用户没有在我的小部件上启动更新,则忽略更新。
也就是说,我记录了本地的 button-press-eventbutton-release-event,而不是测试“窗口是否正在调整大小”。因此,我可以测试“小部件是否正在重新定位”。
from gi.repository import Gtk

class MyPaned(Gtk.Paned):
    _user_activated = False

    def on_position(self, _, gparamspec):
        if self._user_activated:
            # widget touched

        else:
            # window resized (probably)

    def on_button_press(self, *_):
        self._user_activated = True

    def on_button_release(self, *_):
        self._user_activated = False


    dev __init__(self, *args):
        super(MyPaned, self).__init__(*args)
        self.connect('notify::position', self.on_position)
        self.connect('button-press-event', self.on_button_press)
        self.connect('button-release-event', self.on_button_release)

通过记录用户开始和结束与我的小部件的交互来有效地推断其余时间是由于调整窗口大小引起的。(直到我找到更多情况)


在 API 参考文档中,我可以在哪里找到 notify::position - buhtz
1
@buhtz 我认为我在野外偶然发现了一个"notify::<type>"的例子,然后从Lazka的PGI文档中推断出了其余部分:https://lazka.github.io/pgi-docs/#Gtk-3.0/classes/Paned.html - ThorSummoner
@ThorSummoner 在文档中我找不到 notify::* 事件。这就是我感到困惑的原因。 - buhtz
@ThorSummoner 是的,我想在您的代码片段中添加Python3语法突出显示,但SE告诉我您的回答的编辑队列已满。 - Scrooge McDuck
@ScroogeMcDuck 我已经进行了编辑(非常好的建议),也许这样可以清除编辑队列?当我查看此答案的编辑历史记录时,我没有看到任何明显的解决方法。 - ThorSummoner
2
如果有一个用户使用平铺式窗口管理器,那么这段代码将无法按预期工作。 - Melroy van den Berg

4
在PyGTK中,我一直关注窗口调整大小的expose_event,然后使用get_allocation方法获取新的大小。

1
我正在查看GdkEventExpose结构...是send_event字段告诉我用户是否执行了它? - Drew Dormann
2
实际上,你可能想要使用event_configure而不是event_expose...我的错。我认为这适用于移动和调整大小,所以如果你只关心先前的大小,那么你必须记住它。 - eduffy

1

你可以使用gdk_window_get_root_origin获取窗口左上角的位置,再使用gdk_window_get_geometry获取宽度和高度,从而拼凑出一个解决方案。然后,你可以将回调函数挂钩到GDK_BUTTON_PRESS_MASK中,并检查按钮是否在窗口的边缘附近/上。

当然,这种方法似乎有些hackish,我真的很困扰,因为我在GdkWindow文档中找不到更简单的方法来实现这一点。虽然有一个gdk_window_begin_resize_drag函数,但它让我认为应该有更简洁的方法来完成这个任务,但我没有看到比我的答案更明显的东西。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接