Trying to set_active property of toggle button in gtk python based on external parameters/bool value not working properly

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
threadsdia

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

  1. Change the toggle botton's property set_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?

  1. Changing the toggle botton's property set_active as an external parameter supplied from outside like an event 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?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.