Can't update LABEL text on kivy file - kivy

I have a problem with updating a label text: id: time_ // the strange thing is , i can read(print) with self.ids.time_.text. Merci for help
class Scroll(Screen):
def __init__(self, **kwargs):
super(Scroll, self).__init__(**kwargs)
self.sec = 0
self.min = 0
def Label_updater(self,time):
print(self.ids.time_.text)
#self.ids.time_.text= str(time)
self.ids.time_.text='new_ text'
def start_timer(self, *args):
self.sec += 1
self.time = f'00:0{self.sec}'
self.Label_updater(self.time)
def on_start(self):
Clock.schedule_interval(self.start_timer, 1)
kivy file :
<Scroll>:
id: scroll_id
canvas:
Color:
rgba: 149 / 250.0, 77 / 250.0, 114 / 250.0, 0.9
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
spacing:7
padding:10
size_hint:(1,0.1)
pos_hint:{'top':1,'b':1}
Label:
id: score
text: 'Score: 00'
Label:
id: level
text: 'Level: 01'
Label:
id: time_
size_hint: (1.0, 0.83)
text: '00:00'
color: 'red'
BoxLayout:
size_hint:(1,0.9)
GamePage:
padding: 20,20,20,20
will try to explain the probleme with some pictures
in class GamePage i did create some Buttons with callback = pressed( )
in pressed from there u see the starter object activating start_timer() (( this will start the timer ))
enter image description here
enter image description here
when i push a Button ---> everything is working fine till i can print(self.ids.time_.text) and i see in logfile the timer working
but in the screen the Label text still 00:00
enter image description here
but if i press the button ( added from the kivy file ) everything is working fine
i want to start the timer when i push any button
enter image description here

Related

drag file onto bounding area of kivy widget

I want to display an Image when I drag a .png into a specific area of my Kivy window. I've been trying to visualize the bounding area of my widgets and layouts using
canvas.before:
Color:
rgb: 1, 0, 0
Rectangle:
pos: self.pos
size: self.size
However I'm not convinced I understand this yet, because of the behavior I get with the following:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 20 08:42:50 2022
#author: erik
"""
import kivy
kivy.require('2.1.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.core.window import Window
Builder.load_string('''
<MyLayout>:
padding: 20,20, 20, 20
id: img_box
orientation: 'vertical'
size_hint_min_x: self.minimum_width
size_hint_min_y: self.minimum_height
canvas.before:
Color:
rgb: 1, 0, 0
Rectangle:
pos: self.pos
size: self.size
Splitter:
sizable_from: 'bottom'
id: dig_img_spltr
canvas.before:
Color:
rgb: 1, 1, 0
Rectangle:
pos: self.pos
size: self.size
#keep_within_parent: True
rescale_with_parent: True
Image:
id: dig_img
Button:
text: 'hello'
size_hint: .6,.6
pos_hint: {'center_x': .5, 'center_y':.5}
''')
class MyLayout(BoxLayout):
digimgfilePath = StringProperty('')
def __init__(self, **kwargs):
super(MyLayout, self).__init__(**kwargs)
Window.bind(on_drop_file=self._on_file_drop)
def _on_file_drop(self, window, filename, x, y):
'''
Documentataion for on_drop_file
doesn't show window parameter. I
found this out with locals()
'''
print(f'x: {x}')
print(f'y: {y}')
x_lower_bound = self.ids.dig_img_spltr.pos[0]
x_upper_bound = self.ids.dig_img_spltr.pos[0] + self.ids.dig_img_spltr.width
y_lower_bound = self.ids.dig_img_spltr.pos[1]
y_upper_bound = self.ids.dig_img_spltr.pos[1] + self.ids.dig_img_spltr.height
print(f'xlb {x_lower_bound}')
print(f'xub {x_upper_bound}')
print(f'ylb {y_lower_bound}')
print(f'yub {y_upper_bound}')
print()
#if x_lower_bound < x < x_upper_bound and y_lower_bound < y < y_upper_bound:
if self.ids.dig_img_spltr.collide_point(x,y):
self.digimgfilePath = filename.decode("utf-8") # convert byte to string
self.ids.dig_img.source = self.digimgfilePath
self.ids.dig_img.reload() # reload image
class sliderdropApp(App):
def build(self):
return MyLayout()
if __name__ == '__main__':
sliderdropApp().run()
What I want, and expect, is for a image (.png for example) to be displayed when I drop the file into the area above the splitter. But I can't make sense of the area where collide_point returns True. It returns True when I drop the file within some un-explainable margin above and below the splitter. After I do get an image to display, the splitter canvas does to turn yellow above the splitter. Is this yellow area defined by the canvas not the same area of the splitter? Why doesn't collide_point return True when I drop on the area colored by the splitter's canvas?
The y dimension from the on_drop_file event is inverted from the window coordinates. If I send (x, Window.size[1] - y) to collide_point, it works as I expect and intent it to.

Im making a multiple choice question using kivy. I dont know how to track correct answers

I am a newbie in programming and badly needed help for our activity.
Im making a multiple choice question using kivy. I dont know how to track correct answers.
class OneQuestion(Screen):
correct = 0
mistake = 0
def checkbox_click(self, instance, value, answer):
if answer == 1:
correct = + 1
else:
mistake = + 1
global current_answer
answer= "You made " + str(correct) + " correct answers"
global current_error
error= "You made " + str(mistake) + " wrong answers"
current_answer = answer
current_error = error
def show_data(self):
self.dialog = MDDialog(title = "Result", text =current_answer,
pos_hint={'center_x': 0.5, 'center_y': 0.5},
buttons=[MDFlatButton(text='Close', on_release=self.close_dialog),
MDFlatButton(text='Return', on_release=self.close_dialog2)]
)
self.dialog.open()
def close_dialog(self, obj):
self.dialog.dismiss()
def close_dialog2(self, obj):
self.dialog.dismiss()
self.manager.current = 'exercise'
Kivy file:
<OneQuestion>
name: 'quest1'
GridLayout:
cols: 2
canvas:
MDLabel
text:"option 1"
font_size:20
CheckBox:
color: 0,0,1
on_active: root.checkbox_click(self,self.active, 0)
MDLabel
text:"option 2"
font_size:20
CheckBox:
color: 0,0,1
on_active: root.checkbox_click(self,self.active,1)
MDLabel
text:"option 3"
font_size:20
CheckBox:
color: 0,0,1
on_active: root.checkbox_click(self,self.active,0)
MDLabel
text:"option 4"
font_size:20
CheckBox:
color: 0,0,1
on_active: root.checkbox_click(self,self.active,1)
BoxLayout:
orientation: 'horizontal'
size_hint_y: 0.2
Button:
text: 'Back'
on_press: root.manager.current = 'exercise'
Button:
text: 'Submit'
on_release: root.show_data()

Add function to button in kivy file

I am trying to bind my calculations function to the submit button. I am new to Kivy and trying to get in some practice. Any tips or tricks for learning are greatly appreciated. Here is my code:
Python File:
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
class MyGrid(Widget):
pass
class MyApp(App):
def build(self):
return MyGrid()
def calculations(self):
org_amount = float(self.ids.orgamount.text)
org_tip = int(self.ids.orgtip.text)
org_split = int(self.ids.split1.text)
tip1 = org_tip/100
tip = round(tip1 * org_amount, 2)
total = round(tip + org_amount, 2)
if org_split == 0:
split = org_split
else:
split = round(total/org_split,2)
if __name__ == "__main__":
MyApp().run()
KIVY FILE:
<MyGrid>:
title: 'tipBot v1.0'
auto_dismiss: False
GridLayout:
cols:2
size: root.width * 0.8, root.height * 0.8
row_default_height: 30
row_force_default: True
center: root.width/2, root.height/2
Label:
text: "Enter orginal bill amount: "
TextInput:
id: orgamount
hint_text: 'Enter number w/ 2 decimal places'
hint_text_color: 'blue'
multiline:False
Label:
text: "How much tip will you leave: "
TextInput:
id: orgtip
hint_text: 'Enter whole number'
hint_text_color: 'blue'
multiline:False
Label:
text: "How many patrons will split the bill: "
TextInput:
id: split1
multiline: False
Label:
text: "Orignal Bill Amount: "
TextInput:
id: amount
multiline: False
Label:
text: "Amount of tip: "
TextInput:
id: tip
multiline: False
Label:
text: "Total with tip: "
TextInput:
id: withtip
multiline: False
Label:
text:"Amount for each patron split: "
TextInput:
id:patronsplit
multiline: False
Button:
id: Clear
text: "Clear"
size_hint_x: 0
on_release:
orgamount.text = ''
orgtip.text = ''
split1.text = ''
amount.text = ''
tip.text = ''
withtip.text = ''
patronsplit.text =''
Button:
id: Submit
text: "Submit"
size_hint_x:0.5
on_press: root.calculations()
enter code here
The problem is that in your kv, the line:
on_press: root.calculations()
is trying to call the calculations() method of the root object of the kv rule, which is MyGrid. The fix is to just move the calculations() method into MyGrid:
class MyGrid(Widget):
def calculations(self):
org_amount = float(self.ids.orgamount.text)
org_tip = int(self.ids.orgtip.text)
org_split = int(self.ids.split1.text)
tip1 = org_tip / 100
tip = round(tip1 * org_amount, 2)
total = round(tip + org_amount, 2)
if org_split == 0:
split = org_split
else:
split = round(total / org_split, 2)
class MyApp(App):
def build(self):
return MyGrid()

How do I use widget collision to switch screens in kivy?

Im trying to create a game which consists of several areas, accessed by moving the circle onto the boundaries of the screen. I created a transit widget and defined a function to switch screens when there's a collision but it keeps giving errors. The error I got is that WindowManager does not have an attribute manager.
.py file:
class Transit(Widget):
def transit(self,circle):
if self.collide_widget(circle):
WindowManager.manager.current = "a1"
pass
class Wall(Widget):
def collision(self, circle):
if circle.collide_widget(self):
if circle.center_x > (self.pos[0] + self.size[0]) or circle.center_x < self.pos[0]:
circle.velocity_x = -1 * circle.velocity_x
elif circle.center_x > self.pos[0] and circle.center_x < (self.pos[0] + self.size[0]):
circle.velocity_y = -1 * circle.velocity_y
class Circle(Widget):
velocity_x = NumericProperty(0)
velocity_y = NumericProperty(0)
velocity = ReferenceListProperty(velocity_x, velocity_y)
def move(self):
self.pos = Vector(*self.velocity) + self.pos
class Move(Widget):
circle = ObjectProperty(None)
wall1 = ObjectProperty(None)
wall2 = ObjectProperty(None)
wall3 = ObjectProperty(None)
wall4 = ObjectProperty(None)
transit1 = ObjectProperty(None)
def __init__(self, **kwargs):
super(Move, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
self._keyboard.bind(on_key_down = self._on_keyboard_down)
Clock.schedule_interval(self.update, 0)
def update(self, dt):
self.circle.move()
self.wall1.collision(self.circle)
self.wall2.collision(self.circle)
self.wall3.collision(self.circle)
self.wall4.collision(self.circle)
self.transit1.transit(self.circle)
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == 'left':
self.circle.velocity_x -= 0.1
elif keycode[1] == 'right':
self.circle.velocity_x += 0.1
elif keycode[1] == 'up':
self.circle.velocity_y += 0.1
elif keycode[1] == 'down':
self.circle.velocity_y -= 0.1
return True
class Menu(Screen):
pass
class Start(Screen):
pass
class area1(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("dw.kv")
class Adventure(App):
def build(self):
return kv
Adventure().run()
and heres my .kv file
Circle:
size: 30,30
canvas:
Ellipse:
pos: self.pos
size: self.size
WindowManager:
Menu:
Start:
area1:
Menu>:
name: "menu"
#Adding gridlayout
GridLayout:
rows :3
cols : 1
AnchorLayout:
anchor_x : "center"
anchor_y : "center"
Label:
text: "Adventure"
font_size: 40
AnchorLayout:
anchor_x : "center"
anchor_y : "center"
TextInput:
id: ign
size_hint : (.4, None)
height : 30
hint_text : "Enter your name"
multiline : False
AnchorLayout:
anchor_x : "center"
anchor_y : "center"
Button:
text: "Start"
font_size: 40
size: 100, 75
size_hint: (None, None)
on_release: app.root.current = "start"
Start>:
name: "start"
Move:
wall1 : r1
wall2 : r2
wall3 : r3
wall4 : r4
transit1 : t1
circle : circle
Circle:
id : circle
pos: root.center_x , root.center_y
Wall:
id : r1
pos: 0, 400
size: 350, 250
canvas:
Rectangle:
pos: self.pos
size: self.size
Wall:
id : r2
pos: 0 , 0
size: 350, 250
canvas:
Rectangle:
pos: self.pos
size: self.size
Wall:
id : r3
pos: 500 , 400
size: 800, 250
canvas:
Rectangle:
pos: self.pos
size: self.size
Wall:
id : r4
pos: 500 , 0
size: 800, 250
canvas:
Rectangle:
pos: self.pos
size: self.size
Transit:
id : t1
pos: 0, root.center_y
size: 1, 600
area1>:
name: 'a1'
Your only problem is that the line:
WindowManager.manager.current = "a1"
is trying to access the manager attribute of the WindowManager class. You actually want to access that attribute of the WindowManager instance. To do that, you can replace that line with:
App.get_running_app().root.current = "a1"

How to code for a variable in the Kivy label?

I'm trying to create a simple Kivy function that counts and updates the display in the label as either a variable or a variable that has been converted to string. Using Python 3.7 and Kivy 1.10.1
I've been reading previous questions related to labels, but they don't seem to fix my issue. Thanks.
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
import time
class SomeData():
num = 0
while num < 1000:
time.sleep(1)
num+=1
class FirstScreen (Screen):
runTouchApp(Builder.load_string('''
ScreenManager:
FirstScreen:
<FirstScreen>
BoxLayout:
orientation: 'vertical'
GridLayout:
cols: 3
spacing: '10dp'
Button:
Button:
Button:
Label:
size_hint_y: None
text: "Below is a scroll of numbers."
ScrollView:
Label:
text_size: self.width, None
size_hint_y: None
height: self.texture_size[1]
halign: 'left'
valign: 'top'
text: (num)
'''))
The file never creates the Kivy screen and num variable is considered an error in the text label.
Here is a version for your code that will, at least, display:
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.screenmanager import Screen
#import time
# class SomeData:
# num = 0
# while num < 1000:
# time.sleep(1)
# num+=1
class FirstScreen (Screen):
num = NumericProperty(7)
runTouchApp(Builder.load_string('''
ScreenManager:
FirstScreen:
<FirstScreen>
BoxLayout:
orientation: 'vertical'
GridLayout:
cols: 3
spacing: '10dp'
Button:
Button:
Button:
Label:
size_hint_y: None
text: "Below is a scroll of numbers."
ScrollView:
Label:
text_size: self.width, None
size_hint_y: None
height: self.texture_size[1]
halign: 'left'
valign: 'top'
text: str(root.num)
'''))
The SomeData class is commented out, since it does nothing but delay the display. Also, note that changing the value of num in a loop will not create a list of numbers, but will just change the number that is displayed in the Label. There is no need to import the time too. So, commented it.

Resources