Reference attribute of element that is embedded in canvas (Kivy) - python

I am trying to reference the source image of a Rectangle object in a canvas. I don't seem to find the correct code that will correctly reference it. Trying with ids doesn't work because the rectangle cant be given an id, only a group. Therefore, I need to use a group, but this is complex because I have several embedded attributes. Can anyone help? The current solution using self.canvas.get_group("firstQelement")[0].source I found online when a user had an issue with a similar problem. I have tried using different paths to get to the group, including referencing ids and layouts.
AnswerCycle refers to a pre formatted toggle button
Kivy File:
<QuestionDisplay>:
name: "questionDisplay"
RelativeLayout:
canvas.before:
Color:
rgba: utils.get_color_from_hex('#90E0EF')
Rectangle:
pos: self.pos
size: self.size
GridLayout:
padding: 20
spacing: 20
cols: 1
size: root.width, root.height
Title:
id: questionTitle
Image:
canvas.before:
Color:
rgba: utils.get_color_from_hex('#0077B6')
Rectangle:
size: self.size
pos: self.pos
id: mainQuestion
source: "empty.png"
size_hint_y: None
size: root.width, 195
GridLayout:
size_hint_y: None
size: root.width, 200
cols: 2
AnswerCycle:
id: firstQ
canvas.after:
Rectangle
group: "firstQelement"
pos: self.pos
size: self.size
source: "empty.png"
AnswerCycle:
id: secondQ
canvas.after:
Rectangle
group: "secondQelement"
pos: self.pos
size: self.size
source: "empty.png"
AnswerCycle:
id: fourthQ
canvas.after:
Rectangle
group: "thirdQelement"
pos: self.pos
size: self.size
source: "empty.png"
AnswerCycle:
id: thirdQ
canvas.after:
Rectangle
group: "fourthQelement"
pos: self.pos
size: self.size
source: "empty.png"
Python Code:
if Value.correctButtonNumber == 1: self.canvas.get_group("firstQelement")[0].source = "cAnswer.png"
if Value.correctButtonNumber == 2: self.canvas.get_group("secondQelement")[0].source = "cAnswer.png"
if Value.correctButtonNumber == 3: self.canvas.get_group("thirdQelement")[0].source = "cAnswer.png"
if Value.correctButtonNumber == 4: self.canvas.get_group("fourthQelement")[0].source = "cAnswer.png"
Error:
if Value.correctButtonNumber == 1: self.canvas.get_group("firstQelement")[0].source = "cAnswer.png"
IndexError: list index out of range
Minimal Reproducible Example:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
import random
APP_KV = """
<CanvasTest>:
BoxLayout:
canvas.after:
Color:
rgba: 0, 1, 0, 1
Rectangle:
group: 'rectangle'
size: 400, 200
pos: self.pos
Color:
rgba: 1, 0, 0, 1
Ellipse:
group: 'ellipse'
size: 200, 100
pos: self.pos
"""
class CanvasTest(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
print(self.BoxLayout.canvas.after.get_group('rectangle'))
class MainApp(App):
def build(self):
self.root = Builder.load_string(APP_KV)
return CanvasTest()
if __name__ == '__main__':
MainApp().run()
When BoxLayout: is removed, from both the KV script and the print statement, this code works correctly.

Here is a modified version of your code that changes the source attribute of the Rectangle:
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
APP_KV = """
<CanvasTest>:
BoxLayout:
id: box
canvas.after:
Color:
rgba: 0, 1, 0, 1
Rectangle:
group: 'rectangle'
size: 400, 200
pos: self.pos
Color:
rgba: 1, 0, 0, 1
Ellipse:
group: 'ellipse'
size: 200, 100
pos: self.pos
"""
class CanvasTest(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self.info, 2)
def info(self, dt):
rect = self.ids.box.canvas.after.get_group('rectangle')[0]
rect.source = 'tester.png'
class MainApp(App):
def build(self):
self.root = Builder.load_string(APP_KV)
return CanvasTest()
if __name__ == '__main__':
MainApp().run()
I added the id of box to the BoxLayout in the APP_KV to allow access to that BoxLayout. Note that you shouldn't try to access ids in the __init__() method because they typically have not been set yet at that point. That is why I used Clock.schedule_once().

Related

KIvy using a circles position to place a button

I have drawn a circle. I want to place a button at the same position of the circle. How can I get the circle's x and y coordinates. My code(in kv file):
MainWidget:
<MainWidget>:
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
id: point
size: 100, 100
pos: 100, root.y1
Button:
id: No1
pos: point.pos
on_press: root.move()
It shows "NameError: name 'point' is not defined"
Put your widgets in BoxLayout. You can't use id for canvas, you should use groups.
Circle above the button.
from kivy.lang import Builder
from kivy.app import App
KV = '''
Screen:
BoxLayout:
orientation: 'vertical'
spacing: 10
BoxLayout:
size_hint_x: None
pos_hint: {'center_x': .5}
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
size: 100, 100
pos: self.pos
BoxLayout:
Button:
id: No1
on_press: pass
'''
class Test(App):
def build(self):
return Builder.load_string(KV)
Test().run()
Circle in the button.
from kivy.lang import Builder
from kivy.app import App
KV = '''
Screen:
BoxLayout:
padding: 50
Button:
on_press: pass
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
size: self.size
pos: self.pos
'''
class Test(App):
def build(self):
return Builder.load_string(KV)
Test().run()
So you can place the circle at the same position as the button.
Ellipse:
size: 100, 100
pos: self.pos

Image display blank upon being updated

I am using a timer to update the image on the UI after every second. After starting the UI the first image is being displayed. After the timer thread kicks in to display the next image, the widget is displayed blank (i cannot see the image). I can see the image if i start the index from a different value. I do not have an issue with the images. I am unable to update the image on the UI screen. Can anyone help me figure out the issue?
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.image import AsyncImage
from kivy.properties import StringProperty, ListProperty, ObjectProperty
import json, timer
import threading
data = json.load(open('demotest.json'))
Builder.load_file('dv_demo.kv')
class DVDemo(Widget):
message = StringProperty()
image = StringProperty('')
sms = ListProperty()
idx = 0
def __init__(self, **kwargs):
super(DVDemo, self).__init__(**kwargs)
self.update_data_index(self.idx)
def schedule_screens(self):
self.idx = self.idx + 1
if self.idx >= len(data):
time.sleep(500)
temp = threading.Thread(target=self.update_data_index, args=(self.idx,))
threading.Timer(1, temp.start).start()
def update_data_index(self, idx):
# self.image = data[idx]['picture_url']
self.message = data[idx]['message']
self.sms = data[idx]['sms']
message_layout = self.ids.message_panel
message_btn = Button(text=self.message, background_color=[0, 1, 1, 1])
message_layout.add_widget(message_btn)
sms_layout = self.ids.sms_panel
sms_layout.clear_widgets()
for sms_msg in self.sms:
sms_btn = Button(text=sms_msg['sms'], background_color=[0, 0, 2, 1])
sms_layout.add_widget(sms_btn)
self.ids.image_object.source = data[idx]['picture_url']
self.schedule_screens()
class DVDemoApp(App):
def build(self):
self.title = 'DV Demo App'
return DVDemo()
if __name__ == "__main__":
DVDemoApp().run()
<ColoredLabel#Label>:
text_size: self.size
halign: 'left'
valign: 'top'
padding: 4, 4
bold: True
color: (.6, .6, .6, 1)
canvas.before:
Color:
rgb: (.9, .9, .9)
Rectangle:
pos: self.pos
size: self.width - sp(2), self.height - sp(2)
<DVDemo>:
FloatLayout:
id: demo_panels
size: root.width - 50, root.height - 50
pos: root.x + 25, root.y + 25
BoxLayout:
id: message_panel
pos_hint: {"x":0, "top":1}
size_hint: 0.5, 1
orientation: 'vertical'
canvas.before:
Color:
rgb: (.9, .9, .9)
Rectangle:
pos: self.pos
size: self.width - sp(2), self.height - sp(2)
#ColoredLabel:
# id: message_panel
# text: root.message
# pos_hint: {"x":0, "top":1}
# size_hint: 0.5, 1
BoxLayout:
id: image_panel
#text: "Image"
pos_hint: {"x":0.5, "top":1}
size_hint: 0.5, 0.5
Image:
id: image_object
source: root.image
center_x: self.parent.center_x
center_y: self.parent.center_y
size: self.parent.height,self.parent.width
BoxLayout:
id: sms_panel
pos_hint: {"x":0.5, "top":0.5}
size_hint: 0.5, 0.5
orientation: 'vertical'
canvas.before:
Color:
rgb: (.9, .9, .9)
Rectangle:
pos: self.pos
size: self.width - sp(2), self.height - sp(2)
Setting the GUI properties must be done on the main thread. Conveniently, there is a Clock.schedule_once() method that schedules a call on the main thread after a delay. So, I would suggest modifying part of the DVDemo class as:
class DVDemo(Widget):
message = StringProperty()
image = StringProperty('')
sms = ListProperty()
idx = 0
def __init__(self, **kwargs):
super(DVDemo, self).__init__(**kwargs)
self.update_data_index()
def schedule_screens(self):
self.idx = self.idx + 1
Clock.schedule_once(self.update_data_index, 5)
def update_data_index(self, *args):
idx = self.idx
.
.
.
The above code uses Clock.schedule_once() and eliminates the passing of idx among methods, since it is an attribute of the DVDemo instance.

Kivy: Buttons in GridLayout have gap

Inside of GridLayout, odd numbered Button children do not appear.
I've tried several configurations of both Button and GridLayout size, size_hint, height, etc, and cant seem to fix this. Removing the Button class from the children fixes this, but I'd like the functionality of a button widget.
main.py:
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import NumericProperty, StringProperty, ListProperty
from kivy.uix.behaviors.focus import FocusBehavior
from kivy.uix.button import Button
class Tube(Button, RelativeLayout, FocusBehavior):
pass
class TubeMapView(GridLayout, FocusBehavior):
orderNumber = NumericProperty()
customerName = StringProperty("")
tubeList = ListProperty([])
bundleList = ListProperty([])
def add_tube(self):
self.tubeList.append(Tube())
self.add_widget(self.tubeList[-1])
def _on_focusable(self, instance, value):
self.add_tube()
def keyboard_on_key_down(self, window, keycode, text, modifiers):
print(keycode)
if keycode[1] is 'enter':
self.add_tube()
class LengthView(GridLayout):
pass
class AppView(GridLayout):
pass
class TubeMapApp(App):
pass
if __name__ == '__main__':
TubeMapApp().run()
tubemap.kv:
<Tube>:
size_hint_y: None
height: dp(60)
canvas.before:
Color:
rgba: (0,1,0,1)
Rectangle:
size: self.size
<LengthView>:
size_hint_x: 1
size_hint_y: 1
canvas.before:
Color:
rgba: (0,0,1,1)
Rectangle:
size: self.size
<TubeMapView>:
cols: 1
rows: None
size_hint_max_x:
size_hint_y: None
height: self.minimum_height
canvas.before:
Color:
rgba: (0,1,0,1)
Rectangle:
pos: self.pos
size: self.size
AppView:
cols: 2
rows: None
RelativeLayout:
size_hint_x: 0.75
ScrollView:
size: self.size
TubeMapView:
focus: True
Tube:
Tube:
Tube:
RelativeLayout:
size_hint_x: 0.25
ScrollView:
LengthView:
I would expect each one to render, but instead only every other Button renders, starting with the first one:
You can inherit from Button, RelativeLayout and FocusBehavior, and create your own style.
Snippets - py file
class Tube(Button, RelativeLayout, FocusBehavior):
pass
Snippets - kv fie
<-Tube>:
text: ''
focus: False
size_hint_y: None
height: dp(60)
canvas.before:
Color:
rgba: (0,1,0,1)
# rgba: (1,0,1,0.5) if self.focus else (0,1,0,1)
Rectangle:
size: self.size
state_image: self.background_normal if self.state == 'normal' else self.background_down
disabled_image: self.background_disabled_normal if self.state == 'normal' else self.background_disabled_down
canvas:
Color:
rgba: (1,0,1,1) if self.focus else self.background_color
BorderImage:
border: self.border
pos: self.pos
size: self.size
source: self.disabled_image if self.disabled else self.state_image
Color:
rgba: 1, 1, 1, 1
Rectangle:
texture: self.texture
size: self.texture_size
pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)
Output
Example
The following kv file is a mock-up.
poc.kv
<-Tube>:
text: ''
focus: False
size_hint_y: None
height: dp(60)
canvas.before:
Color:
rgba: (0,1,0,1)
Rectangle:
size: self.size
state_image: self.background_normal if self.state == 'normal' else self.background_down
disabled_image: self.background_disabled_normal if self.state == 'normal' else self.background_disabled_down
canvas:
Color:
rgba: (1,0,1,1) if self.focus else self.background_color
BorderImage:
border: self.border
pos: self.pos
size: self.size
source: self.disabled_image if self.disabled else self.state_image
Color:
rgba: 1, 1, 1, 1
Rectangle:
texture: self.texture
size: self.texture_size
pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)
<LengthView>:
size_hint_x: 1
size_hint_y: 1
canvas.before:
Color:
rgba: (0,0,1,1)
Rectangle:
size: self.size
<TubeMapView>:
cols: 1
rows: None
size_hint_y: None
height: self.minimum_height
canvas.before:
Color:
rgba: (0,1,0,1)
Rectangle:
pos: self.pos
size: self.size
AppView:
cols: 2
rows: None
RelativeLayout:
size_hint_x: 0.75
ScrollView:
size: self.size
TubeMapView:
Tube:
focus: True
text: 'tube 1'
Tube:
text: 'tube 2'
Tube:
text: 'tube 3'
RelativeLayout:
size_hint_x: 0.25
ScrollView:
LengthView:
If you want your Tube to be a RelativeLayout that behaves like a Button, change the declaration of your Tube class to:
class Tube(ButtonBehavior, FocusBehavior, RelativeLayout):
pass
Note that the documentation says Behavior class must precede the Widget class in inheritance.
This change does what I think you want.

Kivy: Can I freely change the position of text within a button? and add another text in the button?

t3.py
#-*- coding: utf-8 -*-
__version__ = "1.0"
import kivy
import os
kivy.require('1.10.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.core.window import Window
Window.size = (540, 960)
class StationTest(Screen):
def __init__(self, **kwargs):
super(StationTest, self).__init__(**kwargs)
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("t3.kv")
class Test2App(App):
def build(self):
return presentation
Test2App().run()
t3.kv
# -*- coding: utf-8 -*-
#:kivy 1.10.0
#:import NoTransition kivy.uix.screenmanager.NoTransition
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
#:import Button kivy.uix.button.Button
ScreenManagement:
transition: SlideTransition(direction='left')
StationTest:
<StationTest>:
name: 'StationTest'
canvas:
Rectangle:
pos: self.pos
size: self.size
source: 'image/background.png' #backgroundimage
header: _header
ScrollView:
FloatLayout:
size_hint_y: None
height: 500
BoxLayout:
id: _header
orientation: 'vertical'
size_hint: 1, 0.10
pos_hint: {'top': 1.0}
anchor: _anchor
canvas:
Color:
rgba: 0.8, 0.6, 0.4, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "STATION > STATION"
font_size: 40
BoxLayout
id: _anchor
size_hint_y: 0.3
canvas.before:
Color:
rgba: 0.3, 0.5, 0.8, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "TEST1234"
BoxLayout:
orientation: 'vertical'
#size_hint: 1, 0.35
size: 1,0.35
spacing: 10
pos_hint:{"center_x":0.5,"y":-0.6}
padding: 0, -200, 0, 0
GridLayout:
cols: 1
rows: 10
spacing: 0
padding: [0,100]
on_parent:
for i in range(10): txt = 'abcdef'; self.add_widget(Button(text = txt, text_size=(cm(2), cm(2)), background_color=(255,255,255,1),
pos=self.pos, id=txt, color=(0,0,0,1))) # 0~1.0
i want add '123456' text apart from 'abcdef' in one button. i can code txt = 'abcdef' + '123456' but this is not i wanted. I would like to add the texts in the button and apply the desired options to each text, but it is not easy.
on_parent:
for i in range(10): txt = 'abcdef'; self.add_widget(Button(text = txt, text_size=(cm(2), cm(2)), background_color=(255,255,255,1),
pos=self.pos, id=txt, color=(0,0,0,1))) # 0~1.0
So I have two questions.
1.Can I put two texts that can move independently in one button?
2.Is it possible to set the position of the text freely within the button?
Can I put two texts that can move independently in one button? No, you cannot
Is it possible to set the position of the text freely within the button? No, you cannot
Solution
Create custom button with inheritance of ButtonBehavior and BoxLayout. Inside the BoxLayout, there are three Label widgets.
Snippet
<CustomLabel#Label>:
text_size: root.width, None
size: self.texture_size
valign: 'center'
halign: 'right'
<CustomButton>:
color: 0, 0, 0, 1 # black color text
orientation: 'vertical'
canvas.before:
Rectangle:
size: self.size
pos: self.pos
size_hint: 1, None
height: 60
padding: 5, 5, 5, 5
background_color: [0.50196, 0.50196, 0.50196, 1] if self.state == 'normal' else [0, 1, 1, 1]
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
AnchorLayout:
anchor_x: 'left'
anchor_y: 'top'
CustomLabel:
text: root.route
color: root.color
halign: 'left'
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
CustomLabel:
text: root.stations
color: root.color
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
anchor_x: 'right'
anchor_y: 'bottom'
CustomLabel:
text: root.commute
color: root.color
Example
main.py
#-*- coding: utf-8 -*-
__version__ = "1.0"
import os
import kivy
kivy.require('1.11.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
Window.size = (540, 960)
from kivy.uix.button import ButtonBehavior
from kivy.properties import StringProperty
def oopath(ndid, uor):
path = os.path.join(os.path.dirname(__file__), ndid + '.txt')
return path
##############################################################################################################
class StationTest(Screen):
def __init__(self, **kwargs):
super(StationTest, self).__init__(**kwargs)
oo = oopath('TESTTEST', 0)
self.rpandgv(oo)
def rpandgv(self, path):
with open(path) as businfo:
Businfo = []
for line in businfo:
Businfo.append(line.rstrip())
self.businfolist = Businfo
self.lenbil = int(len(Businfo))
self.numberoflist = int(len(Businfo)/3)
def populate_businfo(self, instance):
for x in range(0, self.lenbil, 3):
instance.add_widget(CustomButton(route=self.businfolist[x], stations=self.businfolist[x+1], commute=self.businfolist[x+2]))
class ScreenManagement(ScreenManager):
pass
class CustomButton(ButtonBehavior, BoxLayout):
route = StringProperty('')
stations = StringProperty('')
commute = StringProperty('')
def on_release(self):
print("\troute={0}, stations={1}, commute={2}".format(self.route, self.stations, self.commute))
presentation = Builder.load_file("test.kv")
class Test2App(App):
def build(self):
return presentation
Test2App().run()
test.kv
# -*- coding: utf-8 -*-
#:kivy 1.11.0
#:import NoTransition kivy.uix.screenmanager.NoTransition
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
#:import Button kivy.uix.button.Button
ScreenManagement:
transition: SlideTransition(direction='left')
StationTest:
<StationTest>:
name: 'StationTest'
canvas:
Rectangle:
pos: self.pos
size: self.size
source: 'image/background.png' #backgroundimage
header: _header
ScrollView:
FloatLayout:
size_hint_y: None
height: 500
BoxLayout:
id: _header
orientation: 'vertical'
size_hint: 1, 0.10
pos_hint: {'top': 1.0}
anchor: _anchor
canvas:
Color:
rgba: 0.8, 0.6, 0.4, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "STATION > STATION"
font_size: 40
BoxLayout
id: _anchor
size_hint_y: 0.3
canvas.before:
Color:
rgba: 0.3, 0.5, 0.8, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "TEST1234"
BoxLayout:
orientation: 'vertical'
#size_hint: 1, 0.35
size: 1,0.35
spacing: 10
pos_hint:{"center_x":0.5,"y":-0.6}
padding: 0, -200, 0, 0
GridLayout:
cols: 1
rows: 10
spacing: 0
padding: [0,100]
on_parent:
root.populate_businfo(self)
<CustomLabel#Label>:
text_size: root.width, None
size: self.texture_size
valign: 'center'
halign: 'right'
<CustomButton>:
color: 0, 0, 0, 1 # black color text
orientation: 'vertical'
canvas.before:
Rectangle:
size: self.size
pos: self.pos
size_hint: 1, None
height: 60
padding: 5, 5, 5, 5
background_color: [0.50196, 0.50196, 0.50196, 1] if self.state == 'normal' else [0, 1, 1, 1]
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
AnchorLayout:
anchor_x: 'left'
anchor_y: 'top'
CustomLabel:
text: root.route
color: root.color
halign: 'left'
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
CustomLabel:
text: root.stations
color: root.color
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
anchor_x: 'right'
anchor_y: 'bottom'
CustomLabel:
text: root.commute
color: root.color
Output

Kivy - Black Screen between transitions

I'm trying to copy this gif, which is done in Kivy (here's the link to the full page )
Just as I started, I noticed a black screen between transition (link to what it looks like so you don't have to copy-paste and run)
Why does that black screen appear?
EDIT: I must work without buttons.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
# Create both screens. Please note the root.manager.current: this is how
# you can control the ScreenManager from kv. Each screen has by default a
# property manager that gives you the instance of the ScreenManager used.
Builder.load_string("""
<MenuScreen>:
canvas.before:
Color:
rgba: 122,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
<SettingsScreen>:
canvas.before:
Color:
rgba: 0,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
""")
# Declare both screens
class MenuScreen(Screen):
def on_touch_down(self, touch):
sm.current = 'settings'
class SettingsScreen(Screen):
def on_touch_down(self, touch):
sm.current = 'menu'
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
EDIT: I've tried this but still not working
<sm>:
canvas:
Color:
rgb: (0, 255, 255)
Rectangle:
size: self.size
pos: self.pos
You are not supposed to use the Screen subclasses directly. Instead you must add a component first (e.g. Button or Layout), for example use RelativeLayout:
Builder.load_string("""
<MenuScreen>:
RelativeLayout:
canvas.before:
Color:
rgba: 122,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
<SettingsScreen>:
RelativeLayout:
canvas.before:
Color:
rgba: 0,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
""")
That black area is a canvas of the screen manager. If you don't like it black, then you can paint it, just like you did with screens; or change transition type to NoTransition to hide it.
Also, you should consider building your screen manager inside that kv lang string.
Old, but in case anyone runs into this issue:
To clarify the vague responses in the comments, you need to paint your screen manager the same way you would paint a screen.
Example in kvlang:
ScreenManagement:
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
size: self.size
pos: self.pos
id: screen_manager
transition: NoTransition()
Screen1:
Screen2:
Settings_:

Categories