Raspberry pi python label.set_text()

I’m trying for several days now, but I can’t figure this out. The label in my window is initially set to “Hello”. when I push a hardware button, the mp3 “siren.mp3” is played and a global variable “counter” is incremented by one. With the print instructions I can see how te program runs and everything seems fine. Except for the label that only updates once to ‘1’ and after that the counter is not reflected in the label anymore.

What am I doing wrong? I really tried dozens of things but can’t get it working…

import time
import gi
import RPi.GPIO as GPIO
import vlc

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(11, GPIO.IN,pull_up_down=GPIO.PUD_UP)

song = "/home/proindustries/Muziek/siren.mp3"
counter = 0

def callbackmethod(callback):
  return callback

class gui:
  global counter

  @callbackmethod
  def SongFinished(self, data):
    print('counter:', counter)
    self.label.set_text(str(counter))
    while Gtk.events_pending():
      Gtk.main_iteration()

  def pin_callback (self, channel):
    global song, counter

    inputValue = GPIO.input(11)
    if inputValue == False and self.mediaplayer.get_state() != 3:
       print ('pressed')
       counter += 1
       self.SongFinished(1)
       self.media = self.instance.media_new(song)
       self.mediaplayer.set_media(self.media)
       self.media.parse()
       self.mediaplayer.play()
       print(counter)
       print("Finished")
       time.sleep(0.1)

  def on_window1_destroy(self, object, data=None):
    print( "quit with cancel")
    Gtk.main_quit()

  def __init__(self):
    self.gladefile = "m.glade"
    self.builder = Gtk.Builder()
    self.builder.add_from_file(self.gladefile)
    self.builder.connect_signals(self)
    self.window = self.builder.get_object("Window1")
    self.label = self.builder.get_object("Counter")
    self.label.set_text("Hello")
    self.window.show_all()

    GPIO.add_event_detect(11, GPIO.FALLING, callback=self.pin_callback)

    self.instance = vlc.Instance()
    self.media = None
    self.mediaplayer = self.instance.media_player_new()

    self.counter = 0

    events = self.mediaplayer.event_manager()
    events.event_attach(vlc.EventType.MediaPlayerEndReached, self.SongFinished)

if __name__ == "__main__":
  main = gui()
  Gtk.main()

Here is the glade file:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkWindow" id="Window1">
    <property name="width-request">400</property>
    <property name="height-request">50</property>
    <property name="can-focus">False</property>
    <property name="title" translatable="yes">Lichtwandeling Mol</property>
    <property name="resizable">False</property>
    <property name="window-position">center</property>
    <property name="gravity">static</property>
    <child>
      <object class="GtkLabel" id="Counter">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="label" translatable="yes">label</property>
        <attributes>
          <attribute name="font-desc" value="Sans Bold 48"/>
        </attributes>
      </object>
    </child>
  </object>
</interface>

If I add some code in function "SongFinished(…) as below:

  def SongFinished(self, data):
    print('counter:', counter)
    self.label = self.builder.get_object("Counter")
    print('Label "Counter"= ', self.label.get_text())
    self.label.set_text(str(counter))
    while Gtk.events_pending():
      Gtk.main_iteration()

it outputs the correct number, only not on my window :face_with_raised_eyebrow:
image

May you have multiple different counter variables? One local in pin_callback function, and one in class gui? But I am not sure, as I am not using Python.

[EDIT] No, you can ignore the comment above, as it seems to make no sense. Can you tell me what

<property name="label" translatable="yes">label</property>

does?

In my m.glade file, I create a GtkLabel object named “Counter”

<object class="GtkLabel" id="Counter">

After creation I set properties of the object. In this case the property “label” (text that initially will be displayed in the label) is set to the text “label”. The ‘Translatable=“yes”’ part of the property marks the text that will be displayed as translatable. This makes it possible to translate the marked strings at compile time. It would take me to far to explain this proces here. But I made two small changes in my source and .glade file:

Marked out the following line in the initialiser part of the gui class (line 59)

#    self.label.set_text("Hello")

And changed the “label” property in the .glade file

<property name="label" translatable="yes">Welkom in Mol</property>

This results in this:
image

But this is all off topic.

As far as I can figure out for the moment, it has nothing to do with the label itself. Marking out all the vlc code and calling the callback function ‘SongFinished’ in code works fine.
I’m going to try to run the vlc code in another tread.

Ah yes. I was confused by the fact, that the “label” string is given in the XML file without quotes, and that you said "The label in my window is initially set to “Hello”. "

Your issue looks a bit strange indeed, I have no idea, sorry.

@StefanSalewski

Your issue looks a bit strange indeed, I have no idea, sorry.

No problem, thanks anyway.

I’ve been testing for another day without any progres :confused:

I’ve some new code:

import time
import gi
import RPi.GPIO as GPIO

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(11, GPIO.IN,pull_up_down=GPIO.PUD_UP)

counter = 0

def callbackmethod(callback):
  return callback

class gui:
  global counter

  @callbackmethod
  def SongFinished(self, data):
    print('counter:', counter)
    self.label.set_text(str(counter))

  def pin_callback (self, channel):
       global counter

#    inputValue = GPIO.input(11)
#    if inputValue == False and self.mediaplayer.get_state() != 3:
       print ('pressed')
       counter += 1
       self.SongFinished(1)
       print("Finished")

  def on_window1_destroy(self, object, data=None):
    print( "quit with cancel")
    Gtk.main_quit()

  def __init__(self):
    self.gladefile = "m.glade"
    self.builder = Gtk.Builder()
    self.builder.add_from_file(self.gladefile)
    self.builder.connect_signals(self)
    self.window = self.builder.get_object("Window1")
    self.label = self.builder.get_object("Counter")
    self.window.connect("destroy", Gtk.main_quit)
    self.window.show_all()

    GPIO.add_event_detect(11, GPIO.FALLING, callback=self.pin_callback)

    self.counter = 0

if __name__ == "__main__":
  main = gui()
  Gtk.main()

This Code does what it is supposed to do :slight_smile:

image

For testing I installed mpg123 and used the os.system(“mpg123 Muziek/siren.mp3”) as in the following code (rest of the code is the same, only import os at the beginning of the script):

       global counter

       os.system("mpg123 Muziek/siren.mp3")

       print ('pressed')
       counter += 1
       self.SongFinished(1)
       print("Finished")
       time.sleep(3)

If I start this code, the problem arises :cry:

Now the song plays when the button is pushed, but the label is not updated anymore, only the first time the song plays…

Someone… Anny idea? If I can’t find a solution I’ll have to quit the GUI approach and work in the command line interface :frowning_face:

Tomorrow I’ll give it a last try… Thanks in advance if someone can help me out. For now I’m gone take a break, I’ll be back tomorrow.

The os.system() call is synchronous. By calling it, you’re blocking the flow of your program until the process you spawn finishes. Since GTK is a single threaded toolkit, blocking calls prevent anything else from happening: input handling, drawing, layout, etc.

If you want to call a process without blocking, you should look at Python’s Popen, or use Gio.Subprocess.

1 Like

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