Changing kv label text with Python code

64 views
Skip to first unread message

Edward Anderson

unread,
Jun 2, 2026, 12:43:39 PMJun 2
to Kivy users support
I have attached the kv and py file for the third screen created through ScreenManager. I am attempting to use StringProperty (marked with ??????????????) and a variable assignment in the load_prb method (marked with ????????????????). The print of the final question variable produces the correct string but the label text is not changed (remains the same as set by the StringProperty function. It seems to have something to do with Setting the variable to a global variable or no action is performed immediately prior to reassigning the variable. All suggestions are appreciared.
solve.kv
solve.py

ElliotG

unread,
Jun 2, 2026, 8:08:33 PMJun 2
to Kivy users support
Let me know if this solves your problem.  If not please share a minimal runnable example.

class Solve(Screen):
    final_question = StringProperty('TEST')
#    def load_prb(q_id):  This is wrong... need self.
    def load_prb(self, q_id):  # This is a class method, self gets passed in 
        ...
        # global final_question       # Delete this
        self.final_question = question   #Kivy properties are accessed as instance variables, use self.
        print('OK222  ', self.final_question)

Edward Anderson

unread,
Jun 3, 2026, 10:29:13 AMJun 3
to kivy-...@googlegroups.com
Unfortunately, these changes did not change the output or the text displayed in the label.  The "final_question" variable is set to a stringproperty in the root class "Solve". This variable is calculated in the method "load_prb". So, it needs to be updated in the Solve class.I thought that declaring the variable as a global variable would do this but it didn't. Thoughts?

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/kivy-users/d65c233e-fe81-4dce-b6bd-09e686ebf30bn%40googlegroups.com.

pedro h

unread,
Jun 3, 2026, 2:38:19 PMJun 3
to Kivy users support

Hope this helps with your project.

Best regards, Pedro

StringUtils.py
main.py
solve.py
solve.kv

pedro h

unread,
Jun 3, 2026, 3:10:43 PMJun 3
to Kivy users support
from kivy.uix.screenmanager import Screen
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.app import App
import xml.etree.ElementTree as ET
from StringUtils import Bold_Face, Sub_Script, Sup_Script, ReplaceVars, Greek
from kivy.properties import StringProperty

class Solve(Screen):

    def on_enter(self):
        self.load_prb("ID123")

    final_question = StringProperty('Test') #?????????????????????
    def load_prb(self,q_id):
        print("LOAD_PRB WIRD AUSGEFÜHRT")
        prob_url = 'XML/Directory.xml' # inport directory XML
        tree = ET.parse(prob_url)
        root = tree.getroot()
        id_arr = []
        url_arr = []
        for problem in root.findall('problem'): # Convert directory XML to a list
            id_arr.append(problem.get('pname'))
            url_arr.append(problem.get('file'))
        prb_url = url_arr[id_arr.index(q_id)]
###################### Format Question #####################
        tree = ET.parse(prb_url)
        root = tree.getroot()
        question = root.find('question').text
        bf = Bold_Face
        question = bf.Bold_Face(question)
        ss = Sub_Script
        question = ss.Sub_Script(question)
        sp = Sup_Script
        question = sp.Sup_Script(question)
        gr = Greek
        question = gr.Greek(question)
        if question.find('var') > -1:
            var = ReplaceVars
            question = var.Replace_Two(question, root)
            print('OK ', question)
####################### Display Question ######################
#??????????????????????
        self.final_question = question#??????????????????????
        #self.ids.question_lbl.text = final_question
        print('OK222 ', self.final_question)

     In the previous version I set the label text via ids, but in this version I update the property directly. Both work, but this one is cleaner.

ElliotG

unread,
Jun 3, 2026, 11:07:32 PMJun 3
to Kivy users support
Here is a simple example.  If you need more assistance, please share a minimal runnable example.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.properties import NumericProperty

kv ="""
<LabelScreen@Screen>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: root.name
           
<CalculationScreen>:
    BoxLayout:
        orientation: 'vertical'
        AnchorLayout:
            BoxLayout:
                orientation: 'vertical'
                size_hint: None, None
                size: dp(200), dp(48 * 2)
                Label:
                    text: str(root.value)
                Button:
                    text: 'Calculate'
                    on_release: root.calc()

BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Simple Example'
        size_hint_y: None
        height: '50dp'
    ScreenManager:
        id: sm
        LabelScreen:
            name: 'screen one'
        CalculationScreen:
            name: 'calculation screen'
        LabelScreen:
            name: 'screen three'
    Button:
        text: 'Next Screen'
        size_hint_y: None
        height: '48dp'
        on_release: sm.current = sm.next()
"""

class CalculationScreen(Screen):
    value = NumericProperty(0)

    def calc(self):
        self.value+=1

class ShowDataApp(App):
    def build(self):
        return Builder.load_string(kv)


ShowDataApp().run()

Edward Anderson

unread,
Jun 7, 2026, 6:27:08 PMJun 7
to kivy-...@googlegroups.com
Pedro & Elliot:
Your solutions work but you need to hard code q_id in the load_prb method through your on_enter method. q_id is passed to load_prb with a button callback on the previous screen. q_id is passed correctly, the XML file containing the q_id unformatted question is correct and the correctly formatted question is correct. But, I am unable to pass the final_question to the solve.kv label. I am willing to send all the files but this involves 2 directories (1 for XML and 1 for screen files), 4 py files and 4 kv files. I am trying to modularlize my code. My solution works through all screens and when I hard code the final_question in a StringProperty. Perhaps this helps.

ElliotG

unread,
Jun 7, 2026, 6:52:16 PMJun 7
to Kivy users support
There is no reason that the parameter needs to be hardcoded.  
I'll talk a look at your code if you want to share a repository or a zip file.

A minimal executable that can showcase the issue is always best. 

ElliotG

unread,
Jun 7, 2026, 7:08:51 PMJun 7
to Kivy users support
I've extended my example below.  I hope this helps.  It passes a value into the calculate screen.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.properties import NumericProperty

kv ="""
<SetValueScreen@Screen>:
    AnchorLayout:
        BoxLayout:
            size_hint: None, None
            size: '200dp', '48dp'
            TextInput:
                id: ti
                input_filter: 'int'
                padding: dp(14)
            Button:
                text: 'set value'
                on_release:
                    root.manager.get_screen('calculation screen').set_value(ti.text)
                    ti.text = ''
                    root.manager.current = root.manager.next()
 
<CalculationScreen>:
    BoxLayout:
        orientation: 'vertical'
        AnchorLayout:
            BoxLayout:
                orientation: 'vertical'
                size_hint: None, None
                size: dp(200), dp(48 * 2)
                Label:
                    text: str(root.value)
                Button:
                    text: 'Calculate'
                    on_release: root.calc()

BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Simple Example'
        size_hint_y: None
        height: '50dp'
    ScreenManager:
        id: sm
        SetValueScreen:
            name: 'set screen'
        CalculationScreen:
            name: 'calculation screen'

    Button:
        text: 'Next Screen'
        size_hint_y: None
        height: '48dp'
        on_release: sm.current = sm.next()
"""

class CalculationScreen(Screen):
    value = NumericProperty(0)

    def calc(self):
        self.value+=1

    def set_value(self, value):
        self.value = int(value)


class ShowDataApp(App):
    def build(self):
        return Builder.load_string(kv)


ShowDataApp().run()

Edward Anderson

unread,
Jun 8, 2026, 2:31:24 PMJun 8
to kivy-...@googlegroups.com
It is difficult to communicate my challenge.  So, I have taken all my files, eliminated external file loading and processing, imaging loading, added comments and tested the result.  It works fine except for the very last step of the solve.py and solve,kv files. I cannot get it to correctly update the final_question in the solve.kv file when a selected problem button on the directory screen has been pressed. The problem may be in one of the other screens. To run my files, load all 8 files into one directory (project) and execute the mmodel.py file. After that I believe it is self-explanatory. I know you have already put a lot of time and effort into this on my behalf. I appreciate this and look forward to solving my issues.

mmodel.py
solve.kv
mmodel.kv
directory.py
directory.kv
welcome.kv
solve.py
welcome.py

ElliotG

unread,
Jun 9, 2026, 12:13:05 PMJun 9
to Kivy users support
I suspect your problem is in directory.py
You need to declare the StringProperty as a class attribute.
I would also suggest you move the on_kv_post from kv to directory.py  that will be cleaner.

I'll have some more time later today to take a closer look.


ElliotG

unread,
Jun 9, 2026, 2:21:10 PMJun 9
to Kivy users support
The core problem is that in directory.py, the advance_scr() method is not accessing the instanced Solve screen.

as below:

    def advance_scr(self, button):
        solve = self.manager.get_screen('solve')  # this accesses the instanced screen
        solve.load_prb(button.text)
        if self.manager:
            self.manager.current = "solve"

I made a few other changes.  I added in id: grid to the GridLayout in directory.kv and then used that to add the buttons dynamically:


    def on_kv_post(self, base_widget):
        prb_name = ('Btn 1', 'Btn 2', 'Btn 3')
        grid = self.ids.grid
        for name in prb_name:
            grid.add_widget(Button(text=str(name), on_press=self.advance_scr))  #hint ignored by grid

Also note that your mmodel.kv file is not being used.  What you have in the file is redundant with what you have in the build() method.  

I've attached the files I modified.  Happy to answer any follow on questions.
directory.py
directory.kv
solve.kv

Edward Anderson

unread,
Jun 10, 2026, 2:08:44 PM (13 days ago) Jun 10
to kivy-...@googlegroups.com
Removed the XML lookup and preparation for button and label text. It works as intended. Thanks for your time and effort. BTW, how did you determine "the advance_scr() method is not accessing the instanced Solve screen" was the problem? I am trying to learn PyCharm diagnostic methods. 

ElliotG

unread,
Jun 11, 2026, 11:13:27 AM (12 days ago) Jun 11
to Kivy users support
I simply reviewed your code.  I saw that you were accessing the class, not the instance.  
The PyCharm debugger is quite nice - but I did not use it in this case.

In object orientated code like kivy it is important to understand the class is like a recipe that describes how to make instances.   To access the instance you usually will need to navigate the widget tree. 
Reply all
Reply to author
Forward
0 new messages