My program reads from a configuration file. It loads Gtk3 widgets on the window based on the configuration file.
Example configuration file:
[Clock1]
format = %H:%M:%S
color = #FF0000
[Clock2]
format = %H:%M
bgColor = #00FF00
So, I have made a class of my own for e.g. Clock type widget and I've called it Clock.
Example:
#!/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
Explanation:
Code reads the configuration file and sees that it has to create a Clock widget. So it makes a Clock class that has a GtkLabel inside it as a variable. The
runCommand
function applies to the widget any more properties read by the configuration file. E.g. theformat
property for the clock.The
update
function is run every 1 second from aWidgetManager
class in order to keep the time updated.The
widget()
function, once there are no more commands (properties) for the widget to be added, is run in order to return the GtkWidget and add it to the main window.
The above code runs just fine for some time, but then the label stops updating in some short random time (1-2 minutes or less).
The code run successfully till 18:53:31 and then the label stopped updating. I guess that Gtk internally moves the object to another memory and I cannot longer access it with my old object(?).
How should I address this problem? Should I do something differently?
I thought of passing the parent widget (which is a Gtk.Window
subclass) to the child (Clock
) and searching by name the Gtk.Label
that represents the self.gtkwidget
(by iterating through the children?). So, get the Gtk.Widget
by its name, cast it to Gtk.Label
and call the update code to it. How can I implement this?
On the other hand, I think that I am overthinking it and maybe a simpler solution is available.
EDIT
After some tests, I decided to pass the parent
as an argument to the constructor of the child (widget) and on the update()
function of the child to run a parent's function and check the string from there (directly accessing the children GtkWidgets from the parent window). Please note that at this moment, the only child of the parent is a Label (GtkLabel). There were some interesting results.
The code is as follows:
#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
Result:
Some things to notice:
The memory addresses of the widget on the child and on the child of the parent window are the same, even after the label's text has stopped updating. Even then both objects are referring to the same memory address.
If you notice, I call the
set_text
function directly from the child (namedchildd
) of the window, and this doesn't update the value either.
What is the chance that this isn't a bug in my code and I should force a Gtk redraw?
EDIT2
Even with self.gtkwidget.queue_draw()
after set_text
, the problem seems to persist.