R. Duke
R. Duke

Reputation: 363

Kivy: updating displayed button text from Python code

Short version: How can I alter button text displayed onscreen from the main.py file of a Kivy application?

Longer version: I'm putting togther a multiple-choice game using Kivy.

I have the gameplay working as I want it to at the python level: when the user clicks on the correct answer button they are awarded points and the answers attached to the buttons are changed. Under the bonnet everything seems to be fine.

My problem is that I can't work out how to update the text on the buttons displayed onscreen from the main.py file. The game plays fine, but the text displayed on the buttons never alters. How do I fix my code to do this?

Below is a simplified version of what I'm tring to do:

My main.py file:

# -*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.properties import ObjectProperty
from functools import partial

import random


vocabDict = {'latte': 'milk', 'mela': 'apple', 'melograno': 'pomegranate', 'fragola': 'strawberry', 'acqua': 'water'}

vocabList = ['acqua', 'latte', 'mela', 'melograno', 'fragola']

currentWord = 'acqua'

score = 0

class ScreenOne(Screen):
    pass

class ScreenTwo(Screen):

    def __init__(self,**kwargs):
        super(ScreenTwo, self).__init__(**kwargs)
        Screen.currentWord = self.getCurrentWord()
        Screen.questionText = Screen.currentWord
        Screen.vocabDict = self.getVocabDict()
        Screen.currentScore = self.getCurrentScore()
        Screen.possibleAnswerList = [Screen.currentWord]
        self.playHand(Screen.currentWord,Screen.vocabDict,Screen.currentScore)

    def getCurrentWord(self):
        return currentWord

    def getVocabDict(self):
        return vocabDict 

    def getCurrentScore(self):
        return score

    def playHand(self,currentWord,vocabDict,score):
        possibleAnswerList = [currentWord]
        currentWord = currentWord
        vocabDict = vocabDict
        currentScore = score
        while len(possibleAnswerList) < 3:
            potentialChoice = random.choice(vocabDict.keys())
            if potentialChoice not in possibleAnswerList:
                possibleAnswerList.append(potentialChoice)
        random.shuffle(possibleAnswerList)          

        # How do I visualize these changes on screen?
        Screen.button1Text = vocabDict[possibleAnswerList[0]]
        Screen.button2Text = vocabDict[possibleAnswerList[1]]
        Screen.button3Text = vocabDict[possibleAnswerList[2]]   

        Screen.possibleAnswerList = possibleAnswerList

        print "Screen.button1Text = " + Screen.button1Text
        print "Screen.button2Text = " + Screen.button2Text
        print "Screen.button3Text = " + Screen.button3Text

    def button1Pressed(instance):
        print "Screen.possibleAnswerList[0] = " + Screen.possibleAnswerList[0]
        print "Screen.currentWord = " + Screen.currentWord
        if Screen.possibleAnswerList[0] == Screen.currentWord:
            print "Correct!"  
            Screen.currentScore += 1
            print Screen.currentScore
            instance.playHand(Screen.currentWord,Screen.vocabDict,Screen.currentScore)
        else:
            print "Incorrect!"

    def button2Pressed(instance):
        if Screen.possibleAnswerList[1] == Screen.currentWord:
            print "Correct!"  
            Screen.currentScore += 1
            print instance.currentScore
            instance.playHand(Screen.currentWord,Screen.vocabDict,Screen.currentScore)
        else:
            print "Incorrect!"

    def button3Pressed(instance):
        if instance.possibleAnswerList[2] == currentWord:
            print "Correct!"  
            instance.currentScore += 1
            print instance.currentScore
            instance.playHand(Screen.currentWord,Screen.vocabDict,Screen.currentScore)
        else:
            print "Incorrect!"

class Manager(ScreenManager):

    screen_one = ObjectProperty(None)
    screen_two = ObjectProperty(None)

class ScreensApp(App):

    def build(self):
        m = Manager(transition=NoTransition())
        return m

if __name__ == "__main__":
    ScreensApp().run()

My screens.kv file:

#:kivy 1.8.0

<ScreenOne>:

    BoxLayout:
        orientation: "vertical"
        size: root.size
        spacing: 20
        padding: 20

        Label:
            text: "Main Menu"
        Button:
            text: "Button 1"
            on_release: root.manager.current = "screen2"

<ScreenTwo>:        

    BoxLayout:
        orientation: "vertical"
        size: root.size
        spacing: 20
        padding: 20

        Label:
            id: label
            text: root.questionText
        Button:
            id: button1
            text: root.button1Text
            on_release: root.button1Pressed()           
        Button:
            id: button2
            text: root.button2Text
            on_release: root.button2Pressed()            
        Button:
            id: button3
            text: root.button3Text
            on_release: root.button3Pressed()           

<Manager>:
    id: screen_manager

    screen_one: screen_one
    screen_two: screen_two

    ScreenOne:
        id: screen_one
        name: "screen1"
        manager: screen_manager

    ScreenTwo:
        id: screen_two
        name: "screen2"
        manager: screen_manager

As should be pretty evident, I'm a total beginner at Kivy, so I'd really appreciate it if you could show me exactly what I need to change, including the specific syntax that should be used.

Thanks in advance for your time and wisdom.

Upvotes: 0

Views: 268

Answers (1)

Yoav Glazner
Yoav Glazner

Reputation: 8066

You need to make button1/2/3Text a StringProperty such as

from kivy.properties import StringProperty # <---- (:

class ScreenTwo(Screen):
    button1Text = StringProperty ('some text')
    button2Text = StringProperty ('some text2')
    button3Text = StringProperty ('some text3')



    def __init__(...):
        ...

    #notice that Screen was replaced by "self"

    # How do I visualize these changes on screen?
    self.button1Text = vocabDict[possibleAnswerList[0]]
    self.button2Text = vocabDict[possibleAnswerList[1]]
    self.button3Text = vocabDict[possibleAnswerList[2]]

Please also replace Screen with self in all other places as well since you are putting variables on a kivy class and its weird ;)

I hope this will help you

Upvotes: 1

Related Questions