2014-09-29 23 views
3

我的程序从配置文件中读取。它根据配置文件在窗口上加载Gtk3小部件。从其父母的名称访问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 

说明:

  1. 代码读取配置文件,并认为它有创建一个时钟部件。所以它使Clock类成为一个变量,其中包含一个GtkLabel。 runCommand函数适用于该配置文件读取的更多属性。例如。时钟的format属性。

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

  3. widget()功能,一旦没有更多的命令(属性)的小部件被添加,运行,以返回GtkWidget并将其添加到主窗口。

上述代码运行得很好了一段时间,但随后的标签停止在一些短的随机时间更新(1-2分钟或更小)。

enter image description here

代码成功运行,直到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 

结果:

enter image description here

有些事情需要注意:

  1. 内存中的小部件对儿童的地址和在父窗口的孩子上是相同的,即使在标签的文本已经存在之后更新。即使这样,两个对象都指向相同的内存地址。

  2. 如果您注意到,我直接从窗口的子项(名为childd)调用set_text函数,并且它也不更新该值。

这是什么机会,这不是我的代码中的错误,我应该强制Gtk重绘?

EDIT2

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

回答

2

你将不得不使用GObject的timeout_add功能定期更新UI ...

请不要这么懒和阅读文档下一次!您可以编写成千上万的完美代码,但是您对Google中的“定期搜索”Gtk更新UI“感到厌倦吗?为什么?

+0

我喜欢燃烧那些显然太懒的问题,只是发现他们是我的;-) – 2017-01-15 16:00:57

+0

哈哈我把这个问题的努力与我用Google搜索正确的词语所做的努力相比是......杰出! – hakermania 2017-09-12 17:31:04