Saw this example of using threads to update a value in this link Threads
Code
import threading
import time
from gi.repository import GLib, Gtk, GObject
def app_main():
win = Gtk.Window(default_height=50, default_width=300)
win.connect("destroy", Gtk.main_quit)
progress = Gtk.ProgressBar(show_text=True)
win.add(progress)
def update_progess(i):
progress.pulse()
progress.set_text(str(i))
return False
def example_target():
for i in range(50):
GLib.idle_add(update_progess, i)
time.sleep(0.2)
win.show_all()
thread = threading.Thread(target=example_target)
thread.daemon = True
thread.start()
if __name__ == "__main__":
app_main()
Gtk.main()
I want to show case two labels on GUI updating their content based on two threads
1) First thread updating the 1st label based on random json generated
2) Second thread updating the 2nd label based on the external signal toggling the toggle button
I have used glade to design a layout I want saved it using GtkBuilder File
with .ui
extension.
Saw this example where Gtk widgets
can be targeted using decorators
This is my example.ui
file where I have added <template class="threadswindow" parent="GtkWindow">
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="threadswindow" parent="GtkWindow">
<property name="can_focus">False</property>
<signal name="destroy" handler="onDestroy" swapped="no"/>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkGrid" id="threadsGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox" id="threadsCell">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="threadLabelBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<child>
<object class="GtkLabel" id="thread1Label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">24</property>
<property name="label" translatable="yes">Thread 1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="thread2Label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">24</property>
<property name="label" translatable="yes">Thread 2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="threadContentBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">50</property>
<property name="margin_bottom">50</property>
<child>
<object class="GtkLabel" id="thread1Value">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">5</property>
<property name="label" translatable="yes">Thread 1 Label Value</property>
<signal name="copy-clipboard" handler="populateLabel" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="thread2Value">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="label" translatable="yes">Thread 2 Label Value</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="threadDescriptionBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="thread1DataLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Json Data</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="thread2ToggleButton">
<property name="label" translatable="yes">togglebutton</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<signal name="toggled" handler="toggleActive" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</template>
</interface>
This is my python code
import json
from faker import Faker
import random
from random import randint
fake = Faker('en_US')
import threading
import time
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk,GLib
class generateJsonData():
@staticmethod
def gen_json():
my_dict = { 'foo': randint(0, 100), 'bar': {'baz': fake.name(), 'poo': float(random.randrange(155, 389))/100 } }
return my_dict
@Gtk.Template(filename="threads.ui")
class Window1(Gtk.Window):
# All small no captial letter for name
__gtype_name__ = "threadswindow"
@Gtk.Template.Callback()
def onDestroy(self, *args):
Gtk.main_quit()
@Gtk.Template.Callback()
def populateLabel(self):
new_json = generateJsonData.gen_json()
self.set_text(new_json)
def updateJsonLabel():
while(True):
GLib.idle_add(populateLabel)
time.sleep(0.4)
# object then signal
@Gtk.Template.Callback("toggleActive")
def toggleActive(self,togglebutton):
print("toggle working")
thread = threading.Thread(target=updateJsonLabel)
thread.daemon = True
thread.start()
window = Window1()
window.connect("destroy",Gtk.main_quit)
window.show()
Gtk.main()
I get this error
Exception in thread Thread-5 (updateJsonLabel):
Traceback (most recent call last):
File "/home/sa/miniconda3/envs/gtktest/lib/python3.10/threading.py", line 1009, in _bootstrap_inner
self.run()
File "/home/sa/miniconda3/envs/gtktest/lib/python3.10/threading.py", line 946, in run
self._target(*self._args, **self._kwargs)
File "/tmp/ipykernel_8296/3732065122.py", line 42, in updateJsonLabel
NameError: name 'populateLabel' is not defined
I have set copy-clipboard
signal handle name populateLabel
and have a function with same name to set text.
I am new to it don’t know what is going wrong, any kind of guidance would be appreciated