按名称从其父级访问 Gtk3 小部件

Posted

技术标签:

【中文标题】按名称从其父级访问 Gtk3 小部件【英文标题】:Access Gtk3 widget from its parent by its name 【发布时间】:2014-09-29 19:11:29 【问题描述】:

我的程序从配置文件中读取。它根据配置文件在窗口上加载 Gtk3 小部件。

示例配置文件:

[Clock1]
format = %H:%M:%S
color = #FF0000

[Clock2]
format = %H:%M
bgColor = #00FF00

所以,我自己创建了一个类,例如时钟类型小部件,我称之为时钟。

例子:

#!/usr/bin/env python

from gi.repository import Gtk, Gdk

import output, Defaults.widget
from time import gmtime, strftime

receiver="Clock"

class Widget():
    def __init__(self, parentName, name):
        print "ADDING CLOCK"
        self.gtkwidget=Gtk.Label();
        self.format= Defaults.widget.defaultClockFormat
        self.name=name+parentName
        self.gtkwidget.set_name(self.name)

    def update(self):
        print "Setting clock text to", strftime(self.format, gmtime())
        self.gtkwidget.set_text(strftime(self.format, gmtime()))

    def runCommand(self, command, lineCount, configurationFile):
        #GMTTIME TRUE OR FALSE
        print "I am about to run", command, "from inside the Clock widget!"

        if(command.startswith("format=")):
            parts=command.split("=")
            if(len(parts)!=2):
                output.stderr(configurationFile+", line "+str(lineCount)+": Badly formatted command 'format': Format: format = format.\nSkipping...")
                return
            
            self.format=parts[1]

    def widget(self):
        return self.gtkwidget

解释:

    代码读取配置文件并看到它必须创建一个时钟小部件。因此,它创建了一个 Clock 类,其中包含一个 GtkLabel 作为变量。 runCommand 函数适用于配置文件读取的任何更多属性的小部件。例如。时钟的format 属性。

    update 函数每 1 秒从 WidgetManager 类运行一次,以保持时间更新。

    widget() 函数,一旦没有要添加的小部件的命令(属性),就会运行以返回 GtkWidget 并将其添加到主窗口。

上面的代码在一段时间内运行得很好,但是标签会在很短的随机时间(1-2 分钟或更短)内停止更新。

代码成功运行到 18:53:31,然后标签停止更新。我猜 Gtk 在内部将对象移动到另一个内存,我不能再用我的旧对象访问它(?)。

我应该如何解决这个问题?我应该做些不同的事情吗?

我想将父小部件(这是一个Gtk.Window 子类)传递给子小部件(Clock)并按名称搜索代表self.gtkwidgetGtk.Label(通过遍历子类?)。因此,获取 Gtk.Widget 的名称,将其转换为 Gtk.Label 并调用更新代码。我该如何实现?

另一方面,我认为我想多了,也许有更简单的解决方案。

编辑

经过一些测试,我决定将parent 作为参数传递给子组件(小部件)的构造函数,并在子组件的update() 函数上运行父函数并从那里检查字符串(直接从父窗口访问子 GtkWidgets)。请注意,此时,父级的唯一子级是一个标签(GtkLabel)。 有一些有趣的结果

代码如下:

#UPDATE FUNCTION OF THE CHILD
def update(self):
        print "Setting clock text to", strftime(self.format, gmtime())
        self.parent.runFromChildToParent(self.gtkwidget, strftime(self.format, gmtime()))
        self.gtkwidget.set_text(strftime(self.format, gmtime()))

#PARENT FUNCTION CALLED FROM THE CHILD
def runFromChildToParent(self, child, textToSet):
    for childd in self.get_children():
        print "The current text on the child is", childd.get_text()
        childd.set_text(textToSet)
        print childd, child

结果:

注意事项:

    即使在标签的文本停止更新之后,子窗口和父窗口子窗口上的小部件的内存地址也是相同的。即便如此,两个对象都指向同一个内存地址。

    如果您注意到,我直接从窗口的子窗口(名为 childd)调用 set_text 函数,这也不会更新值。

这不是我的代码中的错误的可能性有多大,我应该强制 Gtk 重绘?

EDIT2

即使在set_text 之后使用self.gtkwidget.queue_draw(),问题似乎仍然存在。

【问题讨论】:

【参考方案1】:

您将不得不使用 GObject timeout_add 函数来定期更新 ui...

请不要那么懒惰,下次阅读文档!你能写出上千行完美的代码,却厌倦了在 Google 中搜索“Gtk 定期更新 UI”?为什么?

【讨论】:

我喜欢提出那些明显太懒惰的问题,结果却发现它们是我的 ;-) 哈哈,我在这个问题上所付出的努力与我在谷歌上搜索正确单词所付出的努力相比……非常出色!

以上是关于按名称从其父级访问 Gtk3 小部件的主要内容,如果未能解决你的问题,请参考以下文章

透明小部件不随其父级移动

父级大小更改时如何更改子窗口小部件的大小?

在 gnome 调整工具中用作侧边菜单的 Gtk+ 小部件的名称

带有g_timeout_add服务的GTK3并不总是更新GTK小部件

Flutter:了解无状态/有状态小部件如何布局其子级?

无法将 CSS 应用于 GtkEntry 小部件(GTK3 / gi / Python)不工作