Home > Software design >  Printing colored string in class python and kivy
Printing colored string in class python and kivy

Time:02-24

CODE WITHOUT CLASS

import sys
from termcolor import colored
string="admin"
lista=["W","W","W","W","G"]
string1=""
for i in range(5):
    if lista[i]=="W":
        string1 =colored(string[i],'red')
    elif lista[i]=="G":
        string1 =colored(string[i],'green')
    else:
        string1 =colored(string[i],'blue')
print(string1)

With this code, I am able to print out letters in certain color, depending on list variable in corresponding index. However:

.PY file

import kivy
kivy.require('1.11.1')
from kivy.app import App
from kivy.config import Config
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.app import App
from random import choice
from termcolor import colored

Builder.load_file('GuessWord.kv')


class GuessWord(Widget):
    words=["words","crown","ideal"]
    word=choice(words)
    attempts=0
    listofguesses=[]
    accuratecolor=[]
    
    def ClearLetters(self):
        t1=self.ids['t1']
        t2=self.ids['t2']
        t3=self.ids['t3']
        t4=self.ids['t4']
        t5=self.ids['t5']
        listofletters=[t1,t2,t3,t4,t5]
        for i in range(5):
            listofletters[i].background_color=(1,1,1,1)
            listofletters[i].text=""
        
    def StartGame(self):
        self.attempts=0        
        self.word=choice(self.words)
        l1=self.ids['OUTPUT']
        l1.text=""
        listofletters=[]
        for i in range(5):
            name="t" str(i)
            letter=self.ids[name]
            listofletters.append(name)
              
        for i in range(5):
            listofletters[i].background_color=(1,1,1,1)
            listofletters[i].text=""
        self.listofguesses=[]
        l2=self.ids['ATTEMPTS']
        l2.text=""
    
    def ShowPreviousWord(self):
        t1=self.ids['t1']
        t2=self.ids['t2']
        t3=self.ids['t3']
        t4=self.ids['t4']
        t5=self.ids['t5']
        listofletters=[t1,t2,t3,t4,t5]
        string=""
        for i in listofletters:
            string =i.text
        coloredstring=""
        print(string)
        print(self.accuratecolor)
        
        for i in range(len(string)):
            if self.accuratecolor[i]=="W":
                coloredstring =colored(string[i],'white')
            elif self.accuratecolor[i]=="Y":
                coloredstring =colored(string[i],'yellow')
            elif self.accuratecolor[i]=="G":
                coloredstring =colored(string[i],'green')            
        print(coloredstring)
        self.listofguesses.append(coloredstring)
        attempts=""
        for i in range(len(self.listofguesses)):
            attempts =f'Attempt {i 1}: {self.listofguesses[i]}\n'           
        l1=self.ids['ATTEMPTS']
        l1.text=attempts
        
        
        
            
        
        
    def Check(self):
        self.attempts =1
        t1=self.ids['t1']
        t2=self.ids['t2']
        t3=self.ids['t3']
        t4=self.ids['t4']
        t5=self.ids['t5']
        listofletters=[t1,t2,t3,t4,t5]
        outputstring=""
        accurateletters=0
        accuratecolor=[]
        for i in range(5):
            listofletters[i].background_color=(1,1,1,1)
        for i in range(len(listofletters)):
            if listofletters[i].text.lower()=="":
                outputstring =f'You have not filled {i 1} letter\n'
                accuratecolor.append("W")
            elif listofletters[i].text.lower() in self.word:
                if listofletters[i].text.lower() == self.word[i]:
                    accuratecolor.append("G")
                    listofletters[i].background_color=(0, 255/256, 0, 1)
                    accurateletters =1
                    outputstring =f'{listofletters[i].text.upper()} - letter in accurate spot\n'
                else:
                    accuratecolor.append("Y")
                    listofletters[i].background_color=(228/256, 245/256, 39/256, 1)
                    outputstring =f'{listofletters[i].text.upper()} - letter is in word, but not in this spot\n'
            else:
                accuratecolor.append("W")
                outputstring =f'{listofletters[i].text.upper()} - no letter in the word\n'
                listofletters[i].bacground_color=(1,1,1,1)
        l1=self.ids['OUTPUT']
        l2=self.ids['ATTEMPTS']
        self.accuratecolor=accuratecolor
        if accurateletters==5:
            l1.text=f'You have won! You guessed the word after {self.attempts} attempts'
            l2.text=""
        else:
            l1.text=outputstring
        
        
        


class GuessWordApp(App):
    def build(self):
        return GuessWord()

if __name__ == '__main__':
    GuessWordApp().run()

.KV file

<GuessWord>   
    RelativeLayout:
        size: root.width, root.height
        Label:
            pos_hint: {'center_x':0.5,'y':0.7}
            size_hint: 0.2,0.2
            text: "Guess the word!"
        Button:
            pos_hint: {'center_x':0.5,'y':0.67}
            size_hint: 0.5,0.1
            text: "Click here to start!"
            on_press: root.StartGame()
        GridLayout:
            id: word
            cols:5
            pos_hint:{'center_x':0.5,'y':0.5}
            size_hint:(1,0.15)                    
            TextInput:
                halign: "center"
                font_size: 70
                id: t1
                multiline: False
                focus: True
                on_text: t2.focus = True                    
            TextInput:
                halign: "center"
                font_size: 70
                id: t2 
                multiline: False
                on_text: t3.focus = True               
            TextInput:
                halign: "center"
                font_size: 70
                id: t3
                multiline: False
                on_text: t4.focus = True 
            TextInput:
                halign: "center"
                font_size: 70
                id: t4
                multiline: False
                on_text: t5.focus = True 
            TextInput:
                halign: "center"
                font_size: 70
                id: t5
                multiline: False
                on_text:
                    root.Check()
                    root.ShowPreviousWord()
                    t1.focus = True 
        GridLayout:
            cols:1
            pos_hint:{'center_x':0.5,'y':0.3}
            size_hint:(1,0.2)
            Button: 
                pos_hint:{'center_x':0.5,'y':0.4}
                text: "Check if it's your word!"
                on_press: 
                    root.Check()
                    root.ShowPreviousWord()
                    
                    
        Label:
            pos_hint:{'center_x':0.5,'y':-0.35}
            id: OUTPUT
        Label:
            pos_hint:{'center_x':0.2,'y':-0.35}
            id:ATTEMPTS

Focusing mainly on function ShowPreviousWord in .py file, at the start of the function (which starts, while the last of 5 letters is being put on) it is being given a string to print and the listofcolors is being passed from different function. The code for that is exactly the same as without class, however print doesn't give the same result.

For example, for word "admin" and list=["W","W","W","W","G"] it prints out: ←[37ma←[0m←[37md←[0m←[37mm←[0m←[37mi←[0m←[32mn←[0m

In the same moment, the first code works as I would like it. To add to the problem, I want to pass the colored string to kivy label and show it on screen. Why doesn't it work?

CodePudding user response:

Here colouring is done using Label's markup prop. and setting colour (in hex) with a new function.

First define a function for setting colour (color) as,

def set_color(letter, color):
    COLORS_DICT  = {"W" : "ffffff", "Y" : "ffff00", "G" : "00ff00"}
    c = COLORS_DICT.get(color, "W")
    return f"[color={c}]{letter}[/color]"

Now use it in method ShowPreviousWord as,

    def ShowPreviousWord(self):
        ...
        print(string)
        print(self.accuratecolor)

        coloredstring = "".join((set_color(l, c) for l, c in zip(string, self.accuratecolor)))

        print(coloredstring)
        ...

Lastly, activate markup in Label for rendering,

        Label:
            pos_hint:{'center_x':0.2,'y':-0.35}
            id:ATTEMPTS
            markup: True
  • Related