Trying to test how to implement sending external inputs got from threads to be displayed onto the Gtk GUI.
Here’s the GUI .ui
file
<?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>
<signal name="copy-clipboard" handler="displaytbuttonStatus" 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">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>
Here’s how the application window looks
First thread Generates random json
values based on when the generate function is called display on the Thread 1 Label Value
working fine
Second thread Has to set_active
status of toggle button
to either True
or False
I tested out two cases
-
Change the
toggle botton
's propertyset_active
to its complement.- The json value are displayed in its field
- The toggle button get status value displayed in its field
Here’s it’s 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
"""
Json generating class
"""
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
"""
GUI static template
"""
@Gtk.Template(filename="threads.ui")
class Window1(Gtk.Window):
# All small no captial letter for name
__gtype_name__ = "threadswindow"
# Variable where json is updated on the particular template ID
thread1JsonDisplay = Gtk.Template.Child("thread1Value")
tbutton = Gtk.Template.Child("thread2ToggleButton")
thread2StatusValue = Gtk.Template.Child("thread2Value")
@Gtk.Template.Callback()
def onDestroy(self, *args):
Gtk.main_quit()
@Gtk.Template.Callback()
def populateLabel(self):
new_json = generateJsonData.gen_json()
self.thread1JsonDisplay.set_text(json.dumps(new_json))
return True
# object then signal
@Gtk.Template.Callback()
def toggleActive(self):
self.tbutton.set_active(True) if not self.tbutton.get_active() else self.tbutton.set_active(False)
@Gtk.Template.Callback()
def displaytbuttonStatus(self):
self.thread2StatusValue.set_text(str(self.tbutton.get_active()))
def app_main():
win = Window1()
win.connect("destroy",Gtk.main_quit)
def update_json():
win.populateLabel()
return False
def thread1_func():
while(True):
GLib.idle_add(update_json)
time.sleep(0.2)
def toggleTButton():
win.toggleActive()
win.displaytbuttonStatus()
return False
def thread2_func():
while(True):
GLib.idle_add(toggleTButton)
time.sleep(0.6)
win.show_all()
thread1 = threading.Thread(target=thread1_func)
thread2 = threading.Thread(target=thread2_func)
thread1.daemon = True
thread2.daemon = True
thread1.start()
thread2.start()
if __name__=="__main__":
app_main()
Gtk.main()
I get this error message in terminal
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: Window1.toggleActive() takes 1 positional argument but 2 were given
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: Window1.toggleActive() takes 1 positional argument but 2 were given
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: Window1.toggleActive() takes 1 positional argument but 2 were given
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: Window1.toggleActive() takes 1 positional argument but 2 were given
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: Window1.toggleActive() takes 1 positional argument but 2 were given
How do I correct this?
- Changing the
toggle botton
's propertyset_active
as an external parameter supplied from outside like anevent
has occurred or not.
The toggle button gets stuck at TRUE
Here’s the 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
"""
Json generating class
"""
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
"""
GUI static template
"""
@Gtk.Template(filename="threads.ui")
class Window1(Gtk.Window):
# All small no captial letter for name
__gtype_name__ = "threadswindow"
# Variable where json is updated on the particular template ID
thread1JsonDisplay = Gtk.Template.Child("thread1Value")
tbutton = Gtk.Template.Child("thread2ToggleButton")
thread2StatusValue = Gtk.Template.Child("thread2Value")
@Gtk.Template.Callback()
def onDestroy(self, *args):
Gtk.main_quit()
@Gtk.Template.Callback()
def populateLabel(self):
new_json = generateJsonData.gen_json()
self.thread1JsonDisplay.set_text(json.dumps(new_json))
return True
# object then signal
@Gtk.Template.Callback()
def toggleActive(self,outsideToggleValue):
print("#########################")
print("FIRST: signal_recieved_var",type(outsideToggleValue),"VALUE",outsideToggleValue)
self.tbutton.set_active(True) if outsideToggleValue else self.tbutton.set_active(False)
print("SECOND: ",str(self.tbutton.get_active()))
print("#########################")
# self.tbutton.set_active(True) if not self.tbutton.get_active() else self.tbutton.set_active(False)
@Gtk.Template.Callback()
def displaytbuttonStatus(self):
self.thread2StatusValue.set_text(str(self.tbutton.get_active()))
"""
main function
1) Creates instance of the GUI app Window
2) Creates a function that updates the json field inside the GUI app Window
3) Creates a function that calls the update json field
4)
"""
def app_main(signal_recieved):
win = Window1()
win.connect("destroy",Gtk.main_quit)
signal_recieved_var = signal_recieved
def update_json():
win.populateLabel()
return False
def thread1_func():
while(True):
GLib.idle_add(update_json)
time.sleep(0.2)
def toggleTButton(sig_val):
win.toggleActive(sig_val)
win.displaytbuttonStatus()
return False
def thread2_func(signal_recieved_var):
while(True):
GLib.idle_add(toggleTButton,signal_recieved_var)
time.sleep(0.6)
signal_recieved_var = True if not signal_recieved_var else False
win.show_all()
thread1 = threading.Thread(target=thread1_func)
thread2 = threading.Thread(target=thread2_func,args=(signal_recieved_var,))
thread1.daemon = True
thread2.daemon = True
thread1.start()
thread2.start()
if __name__=="__main__":
external_signal = True
app_main(external_signal)
Gtk.main()
On printing the get_active
inside the toggleActive
function Before
and After
changing the status I get such an output
#########################
FIRST: signal_recieved_var <class 'bool'> VALUE True
#########################
FIRST: signal_recieved_var <class 'gi.repository.Gtk.ToggleButton'> VALUE <Gtk.ToggleButton object at 0x7f59ddd2e2c0 (GtkToggleButton at 0x55d59c9f12b0)>
SECOND: True
#########################
SECOND: True
#########################
#########################
FIRST: signal_recieved_var <class 'bool'> VALUE False
#########################
FIRST: signal_recieved_var <class 'gi.repository.Gtk.ToggleButton'> VALUE <Gtk.ToggleButton object at 0x7f59ddd2e2c0 (GtkToggleButton at 0x55d59c9f12b0)>
#########################
FIRST: signal_recieved_var <class 'gi.repository.Gtk.ToggleButton'> VALUE <Gtk.ToggleButton object at 0x7f59ddd2e2c0 (GtkToggleButton at 0x55d59c9f12b0)>
SECOND: True
#########################
SECOND: True
#########################
SECOND: True
#########################
#########################
FIRST: signal_recieved_var <class 'bool'> VALUE True
SECOND: True
#########################
#########################
FIRST: signal_recieved_var <class 'bool'> VALUE False
#########################
FIRST: signal_recieved_var <class 'gi.repository.Gtk.ToggleButton'> VALUE <Gtk.ToggleButton object at 0x7f59ddd2e2c0 (GtkToggleButton at 0x55d59c9f12b0)>
#########################
What is going wrong in both the cases?
PS:
I used if
condition to first check if the value got is first a boolean
value or not then update set_active
# object then signal
@Gtk.Template.Callback()
def toggleActive(self,outsideToggleValue):
if isinstance(outsideToggleValue,bool):
print("#########################")
print("Actual signal_recieved_var",type(outsideToggleValue),"VALUE",outsideToggleValue)
print("Before setting: ",str(self.tbutton.get_active()))
self.tbutton.set_active(outsideToggleValue)
print("After setting: ",str(self.tbutton.get_active()))
print("#########################")
But why do we get <class 'gi.repository.Gtk.ToggleButton'>
type when we are expecting bool
type?