I want to create a label in python with a background color, after I press a button, in a kivy setup.
I have written below code and it is running without error however because of a mistake I cound not find, when I press the button, canvas is not created behind the label. How can I correct it ?
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle
class MyWinMan(ScreenManager):
pass
class W_MainMenu(Screen):
def button_press(self):
lbl_info = Label(
text = 'Please select the file...',
size_hint = ( 1, 0.6),
font_size = 18,
color = ( 180/255, 180/255, 180/255, 1),
)
with lbl_info.canvas:
Color( 50/255, 50/255, 50/255, 1)
Rectangle(pos=lbl_info.pos, size=lbl_info.size)
self.manager.get_screen("win_Main").ids.scr_Main_lvl_A.add_widget(lbl_info)
kv = Builder.load_string("""
MyWinMan:
W_MainMenu:
<W_MainMenu>:
name: "win_Main"
BoxLayout:
id: scr_Main_lvl_A
orientation: "vertical"
size: root.width, root.height
padding: 40
spacing: 10
Button:
text: 'Test'
id: btn_chk
font_size: 20
on_release: root.button_press()
""")
Window.size = (700, 460)
Window.top = 50
Window.left = 100
class MyApp(App):
def build(self):
return kv
if __name__ == '__main__':
MyApp().run()
CodePudding user response:
I solved it by utilizing Clock.schedule_once as the pos and size values should be obtained after the creation of label but as I guess it was trying to get them before. Therefore I added a bit delay. However a better solution is always welcome...
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle
from kivy.clock import Clock
class MyWinMan(ScreenManager):
pass
class W_MainMenu(Screen):
lbl_info = ""
def create_my_label(self):
self.lbl_info = Label(
text = 'Please select the file...',
size_hint = ( 1, 0.6),
font_size = 18,
color = ( 180/255, 180/255, 180/255, 1),
)
self.manager.get_screen("win_Main").ids.scr_Main_lvl_A.add_widget(self.lbl_info)
def set_canvas(self, dt=0):
with self.lbl_info.canvas:
Color( 50/255, 50/255, 50/255, 1)
Rectangle(pos=self.lbl_info.pos, size=self.lbl_info.size)
def button_press(self):
self.create_my_label()
Clock.schedule_once(self.set_canvas)
kv = Builder.load_string("""
MyWinMan:
W_MainMenu:
<W_MainMenu>:
name: "win_Main"
BoxLayout:
id: scr_Main_lvl_A
orientation: "vertical"
size: root.width, root.height
padding: 40
spacing: 10
Button:
text: 'Test'
id: btn_chk
font_size: 20
on_release: root.button_press()
""")
Window.size = (700, 460)
Window.top = 50
Window.left = 100
class MyApp(App):
def build(self):
return kv
if __name__ == '__main__':
MyApp().run()
CodePudding user response:
The Rectangle
that you are creating in the canvas
is using the size of the Label
at the moment that the Label
is created. At that moment the size and position of the Label
are the default size of (100,100)
and default position of (0,0)
. The Rectangle
is not automatically updated when the Label
size/position is updated. So you must either write code to do the updating, or use kv
(it will handle the updating for you). So, I suggest creating a custom Label
class that does what you want. First create a new Label
class and use it in the py
code:
class LabelInfoButton(Button):
pass
class W_MainMenu(Screen):
def button_press(self):
lbl_info = LabelInfoButton(
text='Please select the file...',
size_hint=(1, 0.6),
font_size=18,
color=(180 / 255, 180 / 255, 180 / 255, 1),
)
# with lbl_info.canvas:
# Color(50 / 255, 50 / 255, 50 / 255, 1)
# Rectangle(pos=lbl_info.pos, size=lbl_info.size)
self.manager.get_screen("win_Main").ids.scr_Main_lvl_A.add_widget(lbl_info)
and set the desired behavior in your kv
:
<LabelInfoButton>:
canvas.before:
Color:
rgba: 50 / 255, 50 / 255, 50 / 255, 1
Rectangle:
pos: self.pos
size: self.size