First I'm new to kivy. myApp is based on kivy-example/demo/kivycatlog and I was modifying PopupContainer.kv, but my code doesn't work.
PopupContainer.kv
BoxLayout:
id: bl
orientation: "vertical"
popup: popup.__self__
canvas:
Color:
rgba: .18, .18, .18, .91
Rectangle:
size: self.size
pos: self.pos
Button:
id: showPopup1
text: 'press to show popup'
on_release: root.popup.open()
Button:
id: showPopup2
text: 'press to show popup'
on_release: root.popup.open()
Popup:
id: popup
on_parent: if self.parent == bl: bl.remove_widget(self)
title: "An example popup"
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
Button:
id: accept
text: "yes"
on_release: status.text = self.text
Button:
id: cancel
text: "no"
on_release: status.text = self.text
Label:
id: status
text: "yes or no?"
Button:
text: "press to dismiss"
on_release: popup.dismiss()
I want to change the text(showPopup) when I click on "yes" or "no"
on the showPopup's text.
You could get the text of your ShowPopup's buttons from your code. I mean declare a variable in your code named popups_text and in your .kv file try accesing it using root.popups_text. then create a method in your code that changes this text every time the button is pressed.
Related
I have a dropdown menu in which I would like to know which value the user has selected so I can use it later in my program. This is my .kv code:
BoxLayout:
orientation: 'horizontal'
size_hint_x: 1
Button:
pos_hint:{'center_x': .5, 'center_y': .5}
id: units_num_btn
text: '0'
size_hint_y: None
height: 44
on_parent: drop_player_numbers_units.dismiss()
on_release: drop_player_numbers_units.open(self)
DropDown:
id: drop_player_numbers_units
on_select: units_num_btn.text = '{}'.format(args[1])
on_select: app.return_player_numbers()
Button:
id: units_num_btn_1
text: '1'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('1')
Button:
id: units_num_btn_2
text: '2'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('2')
and so on.
My .py code is here:
class drop_content(DropDown):
pass
class PlayerScreen(Screen):
pass
class TheApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(PlayerScreen(name='player_setup'))
sm.current = 'player_setup'
return sm
def main():
Builder.load_file('menu.kv')
app = TheApp()
app.run()
if __name__ == '__main__':
main()
I have previously used a function such as this:
# .py example
def return_text(self):
text = self.root.get_screen('screen').ids.specific_id.text
print(text)
# .kv example
TextInput:
id: input
text: "2"
on_text: app.return_text()
which did return text using a Textinput type in my .kv file. I know it doesn't work for the dropdown menu since the text is not inputted in the same way. Do you know how I would do this?
Thanks in advance
from kivy.app import App
from kivy.uix.dropdown import DropDown
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.lang.builder import Builder
class TestScreen(Screen):
def return_player_numbers(self,play_number):
print('Test : ',play_number)
kv = '''
ScreenManager:
TestScreen:
<TestScreen>:
BoxLayout:
orientation: 'horizontal'
size_hint_x: 1
Button:
pos_hint:{'center_x': .5, 'center_y': .5}
id: units_num_btn
text: '0'
size_hint_y: None
height: 44
on_parent: drop_player_numbers_units.dismiss()
on_release: drop_player_numbers_units.open(self)
DropDown:
id: drop_player_numbers_units
on_select:
units_num_btn.text = '{}'.format(args[1])
app.root.current_screen.return_player_numbers(args[1])
app.return_player_numbers(args[1])
Button:
id: units_num_btn_1
text: '1'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('1')
Button:
id: units_num_btn_2
text: '2'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('2')
'''
class TheApp(App):
def return_player_numbers(self,play_number):
print('App : ',play_number)
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
TheApp().run()
I have found a way that I think is simpler than the current answer provided. This method uses that fact that the text on the button used to initiate the drop down changes as another button is selected. This is to show the user what they have selected. Since I want to know the text the user has selected from the drop down menu, and this is in fact the same thing that is updated on the initial button, I can just read the text from the button to obtatin my result like so:
(in .kv file)
<player_setup>
BoxLayout:
orientation: 'horizontal'
size_hint_x: 0.2
pos_hint: {'x':.4, 'y':0}
Button:
pos_hint:{'center_x': .5, 'center_y': .5}
id: tens_num_btn
text: '0'
size_hint_y: None
# size_hint_x: 0.1
height: 44
on_parent: drop_player_numbers_tens.dismiss()
on_release: drop_player_numbers_tens.open(self)
DropDown:
id: drop_player_numbers_tens
on_select:
#######
tens_num_btn.text = '{}'.format(args[1])
# this line here ^ is the one that re-formats the text of the button above to
# the selected text
app.return_player_numbers()
max_height: 120
(.py file)
def return_player_numbers(self):
player_number = self.root.get_screen('player_setup').ids.tens_num_btn.text
return player_number
This also allows me to concatenate multiple dropdown results using a single function, however it is menu specific. In my case, this works better for me
I am trying to type in text from one screen. Press a button and move to another screen and have that text be shown in a label. I've seen a few questions that are similar to mine, but have not been able to figure out how to use the posted solutions and have been stuck for hours (Link One, Link Two, Link Three). I believe that I need to use the __init__ method somewhere because this is an instance? I tried using the first link, but the label ends up blank (the code does run). Any Advice?
main.py
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.app import App
from kivy.lang.builder import Builder
class SecondWindow(Screen):
def get_unique_text(self):
x = self.manager.get_screen("first")
y = x.ids.unique.text
return str(y)
class FirstWindow(Screen):
pass
class MainWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv_main = Builder.load_file('main.kv')
class MyApp(App):
def build(self):
return kv_main
if __name__ == '__main__':
MyApp().run()
main.kv
#:include First.kv
#:include Second.kv
WindowManager:
MainWindow:
FirstWindow:
SecondWindow:
<MainWindow>
name: "main"
BoxLayout:
Button:
text: "Press"
on_release:
app.root.current = "first"
First.kv
<FirstWindow#Screen>:
name: "first"
BoxLayout:
orientation: "vertical"
Label:
text: "Enter Unique Text for Saving"
font_size: 20
text_size: self.width, None
halign: 'center'
TextInput:
id: unique
hint_text: 'example: Stand25'
Button:
text: "Press"
on_release:
app.root.current = "second"
Second.kv
<SecondWindow#Screen>:
name: "second"
BoxLayout:
orientation: "vertical"
Label:
text: "Unique Text"
font_size: 20
text_size: self.width, None
halign: 'center'
Label:
text: root.get_unique_text()
font_size: 16
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
color: 0,0,0,1
Button:
text: "Go Back"
on_release:
app.root.current = "first"
Another approach is to use the on_enter() method of a Screen in order to fetch the text. This also requires an id for the unique Label:
<SecondWindow#Screen>:
name: "second"
BoxLayout:
orientation: "vertical"
Label:
text: "Unique Text"
font_size: 20
text_size: self.width, None
halign: 'center'
Label:
id: unique # added id
# text: root.get_unique_text()
font_size: 16
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
color: 0,0,0,1
Button:
text: "Go Back"
on_release:
app.root.current = "first"
Just add an on_enter() method to the SecondWindow class:
class SecondWindow(Screen):
def on_enter(self, *args):
self.ids.unique.text = self.get_unique_text()
def get_unique_text(self):
x = self.manager.get_screen("first")
y = x.ids.unique.text
return str(y)
In your Second.kv you can reference the text of the TextInput in the First.kv by making a couple changes to the kv files. First, in the main.kv, add an id for the FirstWindow (and eliminate the SecondWindow for now):
WindowManager:
MainWindow:
FirstWindow:
id: first # added id
# SecondWindow: # this gets added later
<MainWindow>
name: "main"
BoxLayout:
Button:
text: "Press"
on_release:
app.root.current = "first"
Then, in the Second.kv, set up the reference to the text of the TextInput:
<SecondWindow#Screen>:
name: "second"
BoxLayout:
orientation: "vertical"
Label:
text: "Unique Text"
font_size: 20
text_size: self.width, None
halign: 'center'
Label:
text: app.root.ids.first.ids.unique.text # reference to unique text
font_size: 16
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
color: 0,0,0,1
Button:
text: "Go Back"
on_release:
app.root.current = "first"
Since the kv for SecondWindow uses app.root, it will cause an error if SecondWindow is instantiated before the root widget of the App is assigned. To avoid that, add the SecondWindow after a slight delay:
class MyApp(App):
def build(self):
Clock.schedule_once(self.add_second_screen)
return kv_main
def add_second_screen(self, dt):
self.root.add_widget(SecondWindow())
I am trying to create a two screen Kivy touchscreen interface on a Raspberry Pi that acts like a selectable Menu interface to do a function depending on the Selection.
Screen 1:
Shows Eight Blocks - each block is made up by a BoxLayout that consists of Label, Image, Timer, Button.
Screen 2:
A pre defined list of blocks with names and pictures and a timer value.
Now lets say I want block 2 on screen one to have its values set to whatever I select on Screen2, I would like to press on the Button of Block2 on screen 1, it opens screen2 and I select one of the items. Now depending on what I selected on screen2, it should now load the values of that item and update block 2 on screen1 with Label, Image, Timer. The Timer should be a countdown timer.
I have the basic Layout that works showing screen1 and screen2 but am batteling with the value update concept and the multiple Blocks. The Code is still a bit of a mess but hope it gives an idea of what I am trying to do - will past it after posting the question. Screen Two still has no values..
main.py
# class for aqua.kv file
class MainScreen(Screen):
pass
# class for screen.kv file
class SelectScreen(Screen):
pass
class Tray1(Screen):
pass
# class for date.kv file
class Date(BoxLayout,EventDispatcher):
def __init__(self,**kwargs):
super(Date,self).__init__(**kwargs)
Builder.load_file('date.kv')
Builder.load_file('tray1.kv')
class MyApp(App):
time = StringProperty()
def update(self,*args):
self.time = str(time.asctime())
def build(self):
Clock.schedule_interval(self.update,1)
# Set up the layout:
return Builder.load_file('screen.kv')
if __name__ == '__main__':
MyApp().run()
screen.kv
ScreenManager:
id: screen_manager
MainScreen:
id: main_screen
name: 'MainScreen'
manager: 'screen_manager'
SelectScreen:
id: select_screen
name: 'SelectScreen'
manager: 'screen_manager'
# on_release: background_color = 1,0,0,1
<MainScreen>:
BoxLayout:
canvas.before:
Color:
rgba: .5,.6,.7,1
Rectangle:
pos: self.pos
size: self.size
orientation:'vertical'
BoxLayout:
size_hint:1,.2
Date:
BoxLayout:
orientation: 'horizontal'
# size_hint: .2,1
BoxLayout:
orientation: 'vertical'
Label:
id:btn_tray1
font_size: 30
Image:
source:"logo.png"
Tray1:
Button:
id:btn_tray1_1
font_size: 30
text:"Tray1"
on_release: app.root.current = "SelectScreen"
#on_release: app.root.current = "SelectScreen"
# on_release: btn_tray1.background_color = 1,0,0,1
Button:
id:btn_tray2
font_size: 30
text:"Tray2"
on_release: app.root.current = "SelectScreen"
Button:
id: btn_tray3
font_size: 30
text:"Tray3"
on_release: app.root.current = "SelectScreen"
<SelectScreen>:
BoxLayout:
canvas.before:
Color:
rgba: .5,.6,.7,1
Rectangle:
pos: self.pos
size: self.size
orientation:'vertical'
BoxLayout:
orientation: 'horizontal'
BoxLayout:
orientation: 'horizontal'
# size_hint: .2,1
Button:
size_hint:1,.2
id:btn_tray5
font_size: 30
text:"Tray5"
on_release: app.root.current = "MainScreen"
# on_release: btn_tray1.background_color = 1,0,0,1
Button:
size_hint:1,.2
id:btn_tray6
font_size: 30
text:"Tray6"
on_release: app.root.current = "MainScreen"
Button:
size_hint:1,.2
id: btn_tray7
font_size: 30
text:"Tray7"
on_release: app.root.current = "MainScreen"
# on_release: btn_tray3.background_color = 1,0,0,1
Button:
size_hint:1,.2
id: btn_tray8
font_size: 30
text:"Tray8"
on_release: app.root.current = "MainScreen"
# on_release: btn_tray4.background_color = 1,0,0,1
I recently started to get in to Kivy and now I am trying to create app for me and my friends which is a D&D sheet. I wanted to have all the important stats in one tab in which you can scroll down so that the text font doesn't have to be that small but I can't get it working with the self.minimum_height property of the GridLayout that will contain other elements.
I am running kivy version 1.10.0
If I set the height manually the ScrollView works just fine.
Here is my .kv file
<TabbedPanel>:
do_default_tab: False
tab_pos: 'bottom_mid'
tab_width: self.width / 4
TabbedPanelItem:
text: "Character"
ScrollView:
size_hint: (1, None)
height: root.height
GridLayout:
cols: 1
size_hint_y: None
height: self.minimum_height
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
TabbedPanelItem:
text: "Weap's & Mods"
TabbedPanelItem:
text: "Vehicle"
TabbedPanelItem:
text: "Vehicle Upgr"
You need to also set an explicit height for each contained widget, so that the GridLayout can add them together to calculate its minimum height. For instance, in your example you could add the following lines to each button:
size_hint_y: None
height: dp(30)
Cant comment yet, so have to make a separate answer:
You could make:
<My_button>(Button):
size_hint_y: None
height: dp(30)
And use that in your Gridlayout. That would save repeating it for each entry.
The screen has multiple layouts all child of a box layout. I am trying to add a button in the last sub layout (grid-layout) when a button in other layout is clicked. The code does not crash but nothing happens too. I want to add buttons to the layout with id drinkslayout when a button is clicked eg pepsi,sprite
Python:
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class Stacks(StackLayout):
pass
present=Builder.load_file('hellokivy2.kv') #Specifying location of kv file
class MainApp(App):
def build(self):
return present
def drinksSelect(self,value): #creating a button by referring the id of the layout in which to create button
print(value)
yolo = AnotherScreen()
yolo2 = yolo.ids.newButtonLayout
button = Button(text="value",size_hint= (0.2,0.4))
yolo2.add_widget(button)
if __name__ == "__main__":
MainApp().run()
KV
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size:root.size
Button:
text: "Slideshow"
GridLayout:
cols: 2
Button:
text: "Burger"
Button:
text: "Drinks"
on_release: app.root.current = "other"
Button:
text: "Fries"
Button:
text: "Others"
Label:
text: "Your Cart"
font_size: 40
color:(0,0,0,1)
size_hint_y: None
canvas.before:
Color:
rgba:150,10,200,0.5
Rectangle:
pos: self.pos
size: self.size
<AnotherScreen>:
name: "other"
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size:root.size
orientation: 'vertical'
GridLayout:
size_hint_y:0.1
orientation: 'vertical'
rows: 1
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Back Home"
on_release: app.root.current = "main"
Label:
text: "Project BAM"
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Profile"
on_release: app.root.current = "main"
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.9
text: "Whats New"
on_release: app.root.current = "main"
GridLayout:
rows: 2
Button:
text: "Pepsi"
on_release: app.drinksSelect(1)
Button:
text: "7up"
on_release: app.drinksSelect(2)
Button:
text: "Fanta"
on_release: app.drinksSelect(3)
Button:
text: "Mountain Dew"
on_release: app.drinksSelect(4)
Button:
text: "Diet Pepsi"
on_release: app.drinksSelect(5)
Button:
text: "Sprite"
on_release: app.drinksSelect(6)
GridLayout:
id: drinksLayout
size_hint_y: 0.3
orientation: 'horizontal'
rows: 1
Button:
id: label1
size_hint: 0.2,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label2
size_hint: 0.2,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label3
size_hint: 0.2,0.4
background_normal:'1.jpg'
text: 'B1'
Ok the problem was your drinksSelect method, also you need to keep the value of your screens
Try this:
py:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
dl = ObjectProperty()
l = 0
limit = 3 # Fix your limit here 3 is an example
class ScreenManagement(ScreenManager):
m_s = ObjectProperty() # Here I will keep the value of the MainScreen
a_s = ObjectProperty() # Here the AnotherScreen so I can use them later
class Stacks(StackLayout):
pass
present = Builder.load_file('hellokivy2.kv') # Specifying location of kv file
class MainApp(App):
def build(self):
return present
def drinksSelect(self,value): # creating a button by referring the id of the layout in which to create button
print(value)
if self.root.a_s.l < self.root.a_s.limit: # You know what I mean
button = Button(text=str(value), size_hint= (0.2,0.4))
self.root.a_s.ids['place_remaining'].add_widget(button)
self.root.a_s.l += 1
if __name__ == "__main__":
MainApp().run()
kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
m_s: m_s # so I can use it in the .py file
a_s:a_s # same here
transition: FadeTransition()
MainScreen:
id: m_s
AnotherScreen:
id: a_s
<MainScreen>:
name: "main"
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size:root.size
Button:
text: "Slideshow"
GridLayout:
cols: 2
Button:
text: "Burger"
Button:
text: "Drinks"
on_release: app.root.current = "other"
Button:
text: "Fries"
Button:
text: "Others"
Label:
text: "Your Cart"
font_size: 40
color:(0,0,0,1)
size_hint_y: None
canvas.before:
Color:
rgba:150,10,200,0.5
Rectangle:
pos: self.pos
size: self.size
<AnotherScreen>:
name: "other"
dl : drinksLayout
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size:root.size
orientation: 'vertical'
GridLayout:
size_hint_y:0.1
orientation: 'vertical'
rows: 1
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Back Home"
on_release: app.root.current = "main"
Label:
text: "Project BAM"
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Profile"
on_release: app.root.current = "main"
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.9
text: "Whats New"
on_release: app.root.current = "main"
GridLayout:
rows: 2
Button:
text: "Pepsi"
on_release: app.drinksSelect(1)
Button:
text: "7up"
on_release: app.drinksSelect(2)
Button:
text: "Fanta"
on_release: app.drinksSelect(3)
Button:
text: "Mountain Dew"
on_release: app.drinksSelect(4)
Button:
text: "Diet Pepsi"
on_release: app.drinksSelect(5)
Button:
text: "Sprite"
on_release: app.drinksSelect(6)
GridLayout:
id: drinksLayout
size_hint_y: 0.3
orientation: 'horizontal'
rows: 1
GridLayout:
id: place_remaining
rows: 1
size_hint_x: 80
Button:
id: label1
width: 40 # Set the size_hint_x to None and then set the width if you want a fixed dimension
size_hint: None,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label2
width: 40
size_hint: None,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label3
width: 40
size_hint: None,0.4
background_normal:'1.jpg'
text: 'B1'
Outputs:
I hope that the code is a bit clear now