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.
Related
I am making an app where I will have many different labels for dropdown lists. These dropdown lists will be activated by a button that will show the dropdown.
My problem is that I do not know how to have multiple dropdowns using only one class in my python code. Currently, I have to make multiple classes and multiple methods to activate different dropdown menus and to have those dropdown menus come from different classes.
Trying to modify the show_dropDown() didn't work since i couldn't get the labels to show and the button to link the dropdown menu from.
main.py
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.dropdown import DropDown
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import Screen
Window.size = (286.110236, 570.33070866)
class HomeScreen(Screen):
pass
class CustomDropDown(DropDown):
pass
class CustomDropDown2(DropDown):
pass
class ButtonGrid(ButtonBehavior, GridLayout):
def show_dropDown(self):
dropdown = CustomDropDown()
dropdown.open(self)
def show_dropDown2(self):
dropdown = CustomDropDown2()
dropdown.open(self)
GUI = Builder.load_file("main.kv")
class MainApp(App):
def build(self):
return GUI
MainApp().run()
kv-file:
#:import utils kivy.utils
#:import Factory kivy.factory.Factory
<ButtonGrid>:
<CustomDropdown>:
id: dropdown
Label:
id: label1
text: 'Dropdown 1'
size_hint_y: None
height: 400
background_color: (0, 1, 0, .9)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
<CustomDropdown2>:
id: dropdown2
Label:
id: label2
text: 'Dropdown 2'
size_hint_y: None
height: 400
background_color: (1, 0, 1, .9)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
<HomeScreen>:
FloatLayout:
canvas:
Color:
rgb: utils.get_color_from_hex("#FFFFFF")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
rows: 8
cols: 1
spacing: 10
size_hint_y: None
height: 1200
width: self.minimum_width
ButtonGrid:
id: button1
cols:1
rows:1
size_hint: 1, None
height: 185.71
on_press:
self.show_dropDown()
background_color: (1,0,0,1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
Label:
text: "Button 1"
ButtonGrid:
id: button2
cols:1
rows:1
size_hint: 1, None
height: 185.71
on_press:
self.show_dropDown2()
background_color: (0,0,1,1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
Label:
text: "Button 2"
You can add property (or properties) to your CustomDropDown class (or may be to ButtonGrid) and link it to associated widget as follows:
First in .py
class CustomDropDown(DropDown):
text = StringProperty("")
Then in .kv
<CustomDropdown>:
id: dropdown
Label:
id: label1
text: root.text
size_hint_y: None
...
Now call them as you need with some added args/kwargs,
...
GridLayout:
rows: 8
cols: 1
spacing: 10
size_hint_y: None
height: 1200
width: self.minimum_width
ButtonGrid:
id: button1
cols:1
rows:1
size_hint: 1, None
height: 185.71
on_press:
self.show_dropDown('Dropdown 1')
background_color: (1,0,0,1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
Label:
text: "Button 1"
ButtonGrid:
id: button2
cols:1
rows:1
size_hint: 1, None
height: 185.71
on_press:
self.show_dropDown(value='Dropdown 2')
background_color: (0,0,1,1)
And handle those calls in one go,
class ButtonGrid(ButtonBehavior, GridLayout):
def show_dropDown(self, value = ""):
dropdown = CustomDropDown(text = value)
dropdown.open(self)
After a question that was answered yesterday, this code can now set the height of the layout/widgets within the recycle view correctly. However, after 1 or 2 updates to the list, the widgets overlap. This is vital to my app working and it is super close.
I read in the Kivy documentation that the recycle view reuses widgets, which is why it is more efficient than the scroll view. However, I have not been able to understand what it means by reusing them, or how it may affect my program.
I would encourage anyone, who thinks they may be able to help, to run the code below to get a better understanding of what I have attempted to describe, but any comments, pointers, or solutions will be massively apreciated.
What currently works:
The new layouts that contain widgets are added to the recycle view successfully
The layouts resize correctly to fit the amount of text they contain
What doesn't currently work
The layouts with widgets moving to the correct position and not overlapping
main.py
from kivy.app import App
from kivy.properties import ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
example_string = 'jshdfjhsdkjfhjkshfjkshjfhsjkdhfkjshfkjshdfjkshjkdfhsjkdhfkjshfjhsjkfhskjhfjkhfkjhdjfkhsjdkhfkjshdkjhsdjhfsjkdhfjkshdjkfhsdkjhfjksdhfkjshdf)£++£(0'
class MASTER(BoxLayout):
def example_button(self, Button): # Demo of list updating
global example_string # I know
example_string += ')+££+(test\n\n\nsdhfsjdgfj)£++£(0'
temp = []
id_num = 0
for post in example_string.split(')+££+('): # The string is an example of the input data
temp.append({'message_id':id_num, 'text':('[font=Nunito-Bold.ttf][color=161616]Someone:[/color][/font]\n' + post.split(')£++£(')[0]), '_group':str(id_num), '_score':int(post.split(')£++£(')[1])})
id_num = id_num + 1
App.get_running_app().posts = temp
class DemoApp(App):
# One post format = {'message_id':0, 'text':'post_test_here','_size':[0,0], '_group':str(0), '_score':20}
# Text fromat string = [font=Nunito-Bold.ttf][color=161616]Someone:[/color][/font]\n
posts = ListProperty([])
def up_vote(self, button, mode): # Not part of the problem
if button.state == 'down':
if mode == 'all':
print("+1 upvote for message index:" + str(button.parent.parent.message_id) + ' in all posts')
else:
print("+1 upvote for message index:" + str(button.parent.parent.message_id) + ' in top posts')
def down_vote(self, button, mode): # Not part of the problem
if button.state == 'down':
if mode == 'all':
print("-1 upvote for message index:" + str(button.parent.parent.message_id) + ' in all posts')
else:
print("-1 upvote for message index:" + str(button.parent.parent.message_id) + ' in top posts')
if __name__ == '__main__':
DemoApp().run()
demo.kv
MASTER:
<MASTER>:
Button:
text: 'Add items'
on_press: root.example_button(self)
RecycleView:
viewclass: 'PostGrid'
scroll_y: 1
id: rv
data: app.posts
canvas.before:
Color:
rgba: 0, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
RecycleBoxLayout:
id: box
default_size_hint: 1, None
default_size: None, dp(50) #
size_hint_y: None
padding: ["10dp", "16dp"]
spacing: "20dp"
height: self.minimum_height
orientation: 'vertical'
<PostGrid#BoxLayout>:
message_id: -1
orientation: "horizontal"
text: ''
_group: ''
_score: 0
spacing: "6dp"
text_size: None, None
size_hint_y: None
height: self.minimum_height
BoxLayout:
id: voting_menu
orientation: "vertical"
spacing: "2dp"
size_hint: .2, None
height: label.height # This binding will force voting_menu to resize.
# size: self.size # I don't think it has any effect.
ToggleButton:
id: button_up
on_state: app.up_vote(self, 'all')
group: str(root._group)
text: "UP"
color: (1,1,1,1) if self.state=='normal' else (.8,0,0,1)
font_size: "10dp"
size_hint: 1, .3
background_color: .2, .2, .2, 0
canvas.before:
Color:
rgba: (.1,.1,.1,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [6,]
canvas:
Color:
rgba: .2,.2,.2,1
Line:
width: 1.4
rounded_rectangle:(self.x,self.y,self.width,self.height, 5)
Label:
id: vote_count
text: str(root._score)
size_hint: 1, .4
multiline: False
ToggleButton:
id: button_down
on_state: app.down_vote(self, 'all')
group: str(root._group)
text: "DOWN"
color: (1,1,1,1) if self.state=='normal' else (.8,0,0,1)
font_size: "10dp"
size_hint: 1, .3
background_color: .2, .2, .2, 0
canvas.before:
Color:
rgba: (.1,.1,.1,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [6,]
canvas:
Color:
rgba: (.2,.2,.2,1)
Line:
width: 1.4
rounded_rectangle:(self.x,self.y,self.width,self.height, 5)
Label:
id: label # For reference.
text: root.text
padding: "10dp", "12dp"
size_hint: .9, None
height: self.texture_size[1]
font_size: "12dp"
text_size: self.width, None
color: 0,0,0,1
multiline: True
markup: True
# on_texture_size: app.update_message_size(root.message_id, self.texture_size)
pos: self.x, self.y
canvas.before:
Color:
rgba: (0.8, 0.8, 0.8, 1)
RoundedRectangle:
size: self.texture_size
radius: [5, 5, 5, 5]
pos: self.x, self.y
canvas:
Color:
rgba:0.8,0,0,1
Line:
width: 1.4
rounded_rectangle:(self.x,self.y,self.width,self.height, 5)
Image of overlap
Guesses
Adding items instead of updating all of the items stored in 'posts' at once
Finding a way to refresh the recycleview to update the widgets
Creating a custom widget in place of the widgets in layouts for every item in the recycleview
This is a strange problem. I noticed that you are using self.minimum_height and label.height to try to adjust the size, and I believe your code should work. But it only seems to work sometimes. I have added a hack to work around this problem by setting the height of the PostGrid instances via python code. Here is that hack:
class MASTER(BoxLayout):
def example_button(self, Button): # Demo of list updating
global example_string # I know
example_string += ')+££+(test\n\n\nsdhfsjdgfj)£++£(0'
temp = []
id_num = 0
for post in example_string.split(')+££+('): # The string is an example of the input data
temp.append({'message_id': id_num, 'text': (
'[font=Roboto-Bold.ttf][color=161616]Someone:[/color][/font]\n' + post.split(')£++£(')[0]),
'_group': str(id_num), '_score': int(post.split(')£++£(')[1])})
id_num = id_num + 1
App.get_running_app().posts = temp
Clock.schedule_once(self.fix_sizes)
def fix_sizes(self, dt):
rbl = self.ids.box
for w in rbl.walk():
if isinstance(w, Factory.PostGrid):
w.height = max(w.ids.label.height, w.ids.voting_menu.height)
My idea its create a order list. This have to be posible of expand or reduce if the order needed. So I was trying how to do a button that can add a 'Box Label' to a grid, at the same time that this 'Box Label' have the property of delete by itself by a button. I tried a lot of things, but I am really new in this, so nothing work for me.
class OperatorWindow(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Window.size = (1366, 768)
def remove_item(self):
self.ids.parent.clear_widgets()
def add_more(self):
prod_addmore = self.ids.product_inputs
product = BoxLayout(size_hint_x=1, height=30, spacing=5)
prod = TextInput(size_hint_x=.2)
qty = TextInput(size_hint_x=.1)
price = TextInput(size_hint_x=.1)
delete = Button(text='-', size_hint_x=.05)
product.add_widget(prod)
product.add_widget(qty)
product.add_widget(price)
product.add_widget(delete)
prod_addmore.add_widget(product)
delete.bind(on_release=self.deleting(prod_addmore, product))
def deleting(self, prod_addmore, product):
prod_addmore.remove_widget(product)
class OperatorApp(App):
def build(self):
return OperatorWindow()
if __name__ == "__main__":
oa = OperatorApp()
oa.run()
Kivy File
...
BoxLayout:
id: products_labels
size_hint_y: None
size_hint_x: .45
height: 40
spacing: 5
FlatButton:
size_hint_x: .2
text: 'Producto'
canvas.before:
Color:
rgba: (.30,.30,.30,1)
Rectangle:
size: self.size
pos: self.pos
FlatButton:
size_hint_x: .1
text: 'Cantidad'
canvas.before:
Color:
rgba: (.30,.30,.30,1)
Rectangle:
size: self.size
pos: self.pos
FlatButton:
size_hint_x: .1
text: 'Precio'
canvas.before:
Color:
rgba: (.30,.30,.30,1)
Rectangle:
size: self.size
pos: self.pos
FlatButton:
text: '+'
size_hint_x: .05
on_release: root.add_more()
canvas.before:
Color:
rgba: (.30,.30,.30,1)
Rectangle:
size: self.size
pos: self.pos
ScrollView:
size_hint_y: .15
do_scroll_x: False
do_scroll_y: True
GridLayout:
id: product_inputs
size:(self.width, self.height)
size_hint_x: .45
spacing: 5
size_hint_y: None
cols: 1
height: self.minimum_height
row_default_height: 30
row_force_default: True
Please refer to this link! For some refreshers about widgets.
Your code is fine you just need some minor adjustments here and there.
Firstly change
product
To
self.product
It always makes it easier to call functions since the self indicates ownership okay.
Secondly change this line
delete.bind(on_release=self.deleting(prod_addmore, product))
to
delete.bind(on_release=self.deleting)
the reason for the error is because of the parenthesis. And lastly
Chang this
def deleting(self, prod_addmore, product):
prod_addmore.remove_widget(product)
to
def deleting(self, widget):
prod_addmore = self.ids.product_inputs
prod_addmore.remove_widget(self.product)
Hope this helps if you need more indept explano please let me know :)
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
I have created a login screen in kivy and I want to hiding or disabling canvas and rectangle after pressing button,please help me. Here is my code
:
name: "cany"
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
size: self.size
pos: self.pos
source: 'rect4190.png'
Label:
id:user_lbl
text:"User Name: "
color: .9,.1,.1,1
pos: 40,400
TextInput:
id:username_txt
size: cm(4),cm(0.66)
pos: 125,437
write_tab: False
multiline: False
Label:
id:pass_lbl
text: 'Password:'
color: .9, 0.12, .1, 1
pos: 40,350
TextInput:
id:password_txt
size: cm(4),cm(0.66)
pos: 125,387
write_tab: False
multiline: False
Button:
id:btn_login
size: cm(2.33),cm(0.66)
text: 'Login'
pos: 160,200
focus: True
on_press:
root.validate(username_txt.text,password_txt.text)
user_lbl.opacity = 0
pass_lbl.opacity = 0
username_txt.opacity = 0
password_txt.opacity = 0
btn_login.opacity = 0
In your python file:
from kivy.properties import NumericProperty
In your Login class in your python file:
canvas_opacity = NumericProperty(1, rebind=True)
def vanish_canvas(self):
self.canvas_opacity = 0
In your kv file,
<LoginScreen>:
name: "cany"
canvas.before:
Color:
rgba: 1,1,1, root.canvas_opacity
Rectangle:
size: self.size
pos: self.pos
source: 'rect4190.png'
Button:
text: 'clear canvas'
on_press: root.clear_canvas()
What this does isn't remove the images but it makes everything that's part of the canvas in question invisible.
Canvas does have an inbuilt clear function but it seems that it will clear everything, including widgets you don't want to get rid of.