Kivy FileChooser Overlapping - python

I am using the FileChooserListView from kivy and have run into a overlapping text on scroll with screens that another user came across as well. I looked through their post on GitHub and read that some people are using the plyer FileChooser. I also saw that someone mentioned that it has to do with the Building function of the .kv file. I created a new kivy app and the problem did not occur, but when I return to my older app (no changes of any kind) the problem still occurs.
Sorry for the long post, but I am unsure how these two kivy app codes are different. Am I calling something twice that is causing the FileChooser to "hold" it's position? I am not oppose to using plyer's FileChooser, but could someone give me an example on how to implement it?
testing_kivy.py
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
import os
def train_load(path, filename):
download_path = os.path.join(path, filename[0])
print(download_path)
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
class TrainingWindow(Screen):
def show_load_list(self):
content = LoadDialog(load=train_load, cancel=self.dismiss_popup)
self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
self._popup.open()
def dismiss_popup(self):
self._popup.dismiss()
class WindowManager(ScreenManager):
pass
kv_training = Builder.load_file('testing_kivy.kv')
class MyApp(App):
def build(self):
return kv_training
if __name__ == '__main__':
MyApp().run()
testing_kivy.kv
WindowManager:
TrainingWindow:
<TrainingWindow>
name: "training"
BoxLayout:
orientation: "vertical"
Button:
text: "Select Training Images"
font_size: 32
on_release: root.show_load_list()
Button:
text: "Select Training Annots"
font_size: 32
on_release: root.show_load_list()
Button:
text: "Set Parameters"
font_size: 32
on_release:
app.root.current = "parameters_train"
root.manager.transition.direction = "up"
Button:
text: "Back"
font_size: 16
on_release:
app.root.current = "select"
root.manager.transition.direction = "right"
<LoadDialog>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Load"
on_release: root.load(filechooser.path, filechooser.selection)
Older_app.py
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.spinner import SpinnerOption
import os
import pandas as pd
def invalid_login():
app = App.get_running_app()
app.root.current = "main"
# Create a BoxLayout to add multiple lines or buttons to a PopUp
box = BoxLayout()
# Create PopUp
pop = Popup(
title="Invalid Password",
size_hint=(None, None), size=(200, 100),
content=box,
auto_dismiss=False
)
# Dismiss PopUp
box.add_widget(Button(text="Close", on_release=pop.dismiss))
pop.open()
def model_load(path, filename):
download_path = os.path.join(path, filename[0])
print(download_path)
def train_load(path, filename):
download_path = os.path.join(path, filename[0])
print(download_path)
def train_model_load(path, filename):
download_path = os.path.join(path, filename[0])
print(download_path)
class MainWindow(Screen):
def login(self):
if self.ids.password.text == "password":
self.ids.password.text = ""
app = App.get_running_app()
app.root.current = "select"
else:
self.ids.password.text = ""
invalid_login()
class SelectWindow(Screen):
pass
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
class TrainingWindow(Screen):
def show_load_list(self):
content = LoadDialog(load=train_load, cancel=self.dismiss_popup)
self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
self._popup.open()
def dismiss_popup(self):
self._popup.dismiss()
class ModelWindow(Screen):
def show_load_list(self):
content = LoadDialog(load=model_load, cancel=self.dismiss_popup)
self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
self._popup.open()
def dismiss_popup(self):
self._popup.dismiss()
class TrainModelWindow(Screen):
def show_load_list(self):
content = LoadDialog(load=train_model_load, cancel=self.dismiss_popup)
self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
self._popup.open()
def dismiss_popup(self):
self._popup.dismiss()
class ParametersTrainModelWindow(Screen):
pass
class ParametersTrainWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class OverViewTrainWindow(Screen):
pass
class OverViewTrainModelWindow(Screen):
pass
class OverViewModelWindow(Screen):
pass
class MyOption(SpinnerOption):
pass
kv_main= Builder.load_file('main.kv')
class MyApp(App):
def build(self):
return kv_main
if __name__ == '__main__':
MyApp().run()
main.kv
#:import utils kivy.utils
#:include select.kv
#:include training.kv
#:include model.kv
#:include train_model.kv
#:include parameters_train.kv
#:include parameters_train_model.kv
#:include overview_train_model.kv
#:include overview_train.kv
#:include overview_model.kv
WindowManager:
MainWindow:
SelectWindow:
TrainingWindow:
ModelWindow:
TrainModelWindow:
ParametersTrainWindow:
ParametersTrainModelWindow
OverViewTrainWindow:
OverViewTrainModelWindow:
OverViewModelWindow:
<MainWindow>
name: "main"
GridLayout:
cols: 1
BoxLayout:
orientation: "vertical"
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint: 1, 1
text: "SPECPHASE"
font_size: 50
color:
utils.get_color_from_hex('#FF0000')
Label:
size_hint: 1, 1
text: "Object Detection App"
font_size: 40
BoxLayout:
size_hint: 1, 0.005
canvas.before:
Color:
rgba: (1,1,1,1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
orientation: "horizontal"
size_hint: (0.35, 0.35)
padding: (0,0,25,0)
Label:
font_size: 20
text: "Password"
size_hint: (0.5, 0.35)
pos_hint: {'x': 1, 'y': 0.4}
background_color: (0,0,0,1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
TextInput:
id: password
multiline: False
size_hint: (0.5, 0.35)
pos_hint: {'x': 1, 'y': 0.4}
focus: True
background_color:
utils.get_color_from_hex('#18B8D9')
cursor_color: (0,0,0,1)
password: True
Button:
text: "Submit"
on_release: root.login()
select.kv
<SelectWindow#Screen>:
name: "select"
GridLayout:
cols: 1
GridLayout:
cols: 2
Button:
text: "Train"
font_size: 32
on_release:
app.root.current = "training"
root.manager.transition.direction = "right"
Button:
text: "Model"
font_size: 32
on_release:
app.root.current = "model"
root.manager.transition.direction = "left"
Button:
text: "Train & Model"
font_size: 32
on_release:
app.root.current = "train_model"
root.manager.transition.direction = "up"
training.kv
<TrainingWindow#Screen>:
name: "training"
BoxLayout:
orientation: "vertical"
Button:
text: "Select Training Images"
font_size: 32
on_release: root.show_load_list()
Button:
text: "Select Training Annots"
font_size: 32
on_release: root.show_load_list()
Button:
text: "Set Parameters"
font_size: 32
on_release:
app.root.current = "parameters_train"
root.manager.transition.direction = "up"
Button:
text: "Back"
font_size: 16
on_release:
app.root.current = "select"
root.manager.transition.direction = "right"
<LoadDialog>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Load"
on_release: root.load(filechooser.path, filechooser.selection)

After taking a break from this for while and restarting my brain, I was able to find the problem.
Not included in my question, I have a couple more .kv files that have a similar layout to the training.kv. They are used to access other screens. I found that I was calling FileChooserListView in each screen and I belive that is why I was seeing the stacking problem. I ended up removing all of them except for the one in my training.kv file and all is working.

Related

Kivy Incorporating Video to Navigation Drawer

I have been trying off and on for two weeks to figure this out with no luck. This is the first time in my coding learning journey i've felt actually completely stuck. Any help is incredibly appreciated.
Right now my issue is changing screens outside of my .kv file. Right now I am trying to use:
class RootScreen(Screen):
def onNextScreen(self, btn, fileName):
MDApp.get_running_app().root.current = "ScreenVideo1"
MDApp.get_running_app().root.ScreenVideo1.test_on_enter(r'C:\file\location' + fileName + '.MOV')
But that gives the error code:
'RootScreen' object has no attribute 'ScreenVideo1'
main.py
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemableBehavior
from kivymd.uix.list import MDList
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.properties import ObjectProperty
from kivy.uix.videoplayer import VideoPlayer
from kivy.uix.actionbar import ActionBar
from kivy.uix.button import Button
from kivy.core.window import Window
#remove after dev
Window.size = (300,500)
Window.clearcolor = (.976, .980, .996, 1)
screen_helper = r"""
RootScreen:
MDNavigationLayout:
ScreenManager:
id: screen_manager
ScreenHome:
id: screen_home
manager: screen_manager
name: "Home"
ScrollView:
pos_hint: {'bottom':1}
do_scroll_y: True
BoxLayout:
orientation: 'vertical'
padding: 15
spacing: 20
#size_hint: None, None
height: self.minimum_height
size_hint: (1, 2)
MDToolbar:
title: "POTUS"
left_action_items:[["menu",lambda x: nav_drawer.set_state("open")]]
elevation: 8
Widget:
StrokeButton:
text: "Video Category 1"
back_color: (0.576, 0.698, 0.996, 1) if self.state == 'normal' else (0.502, 0, 0.502, .75)
on_release: screen_manager.current = "Video1"
ScreenAbout:
id: screen_about
manager: screen_manager
name: "About"
MDLabel:
text: "About"
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: "POTUS"
left_action_items:[["menu",lambda x: nav_drawer.set_state("open")]]
elevation: 8
Widget:
ScreenHelp:
id: screen_help
manager: screen_manager
name: "Help"
MDLabel:
text: "Help"
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: "POTUS"
left_action_items:[["menu",lambda x: nav_drawer.set_state("open")]]
elevation: 8
Widget:
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: "POTUS"
left_action_items:[["menu",lambda x: nav_drawer.set_state("open")]]
elevation: 8
Widget:
ScreenVideo1:
id: screen_video1
manager: screen_manager
name: "Video1"
GridLayout:
pos_hint: {'top': 1}
cols:1
rows:5
ActionBar:
pos_hint: {'top': 1}
height:'100sp'
ActionView:
ActionPrevious:
with_previous: True
on_release: screen_manager.current = "Home"
StrokeButton:
text: " Video option 1"
back_color: (0.576, 0.698, 0.996, 1) if self.state == 'normal' else (0.502, 0, 0.502, .75)
on_release: root.onNextScreen(self, 'heart')
StrokeButton:
text: "Video option 2"
back_color: (0.576, 0.698, 0.996, 1) if self.state == 'normal' else (0.502, 0, 0.502, .75)
on_release:
StrokeButton:
text: "Video option 3"
back_color: (0.576, 0.698, 0.996, 1) if self.state == 'normal' else (0.502, 0, 0.502, .75)
on_release:
MDNavigationDrawer:
id: nav_drawer
BoxLayout:
orientation: 'vertical'
spacing: '8dp'
padding: '8dp'
MDLabel:
text: "blah blah blah"
font_style: 'Subtitle1'
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: "blah blah blah"
font_style: "Caption"
size_hint_y: None
height: self.texture_size[1]
ScrollView:
MDList:
OneLineIconListItem:
on_release:
screen_manager.current = "Home"
text: 'Home'
IconLeftWidget:
icon:"folder-home"
on_release:
screen_manager.current = "Home"
OneLineIconListItem:
on_release:
screen_manager.current = "Help"
text: 'Help'
IconLeftWidget:
icon:"help-circle-outline"
on_release:
screen_manager.current = "Help"
OneLineIconListItem:
on_release:
screen_manager.current = "About"
text: 'About'
IconLeftWidget:
icon: "doctor"
on_release:
screen_manager.current = "About"
<StrokeButton#Button>:
background_color:(0,0,0,0)
background_normal:''
back_color:(1,0,1,1)
border_radius: 18
color: self.back_color
bold: True
canvas.before:
Color:
rgba: self.back_color
Line:
rounded_rectangle: (self.pos[0],self.pos[1],self.size[0],self.size[1],self.border_radius)
width: 1.2
"""
class RootScreen(Screen):
def onNextScreen(self, btn, fileName):
MDApp.get_running_app().root.current = "ScreenVideo1"
MDApp.get_running_app().root.ScreenVideo1.test_on_enter(r'C:\file\location' + fileName + '.MOV')
class ScreenHome(Screen):
pass
class ScreenAbout(Screen):
pass
class ScreenHelp(Screen):
pass
class ScreenVideo1(Screen):
def test_on_enter(self, vidname):
#self.add_widget(Button(text="Back"))
self.vid = VideoPlayer(source=vidname, state='play',
options={'allow_stretch':True,
'eos': 'loop'})
self.add_widget(self.vid)
def on_leave(self):
pass
def onBackBtn(self):
self.vid.state = 'stop'
self.remove_widget(self.vid)
MDApp.get_running_app().root.current = "ScreenVideo1"
class DemoApp(MDApp):
def build(self):
screen = Builder.load_string(screen_helper)
return screen
DemoApp().run()
It used to be very easy when I was building my app with Manager
class Manager(ScreenManager):
transition = NoTransition()
screen_one = ObjectProperty(None)
screen_two = ObjectProperty(None)
screen_home = ObjectProperty(None)
def __init__(self, *args, **kwargs):
super(Manager, self).__init__(*args, **kwargs)
# list to keep track of screens we were in
self.list_of_prev_screens = []
class ScreensApp(MDApp):
def build(self):
return Manager()
if __name__ == "__main__":
ScreensApp().run()
And then I would just change screens using manager. But now that I am using the navigation drawer I can no longer build my app with manager.
class ScreenOne(Screen):
def onNextScreen(self, btn, fileName):
self.manager.list_of_prev_screens.append(btn.parent.name)
self.manager.current = 'screen2'
self.manager.screen_two.test_on_enter(r'C:\file\location' + fileName + '.MOV')
Your code:
class RootScreen(Screen):
def onNextScreen(self, btn, fileName):
MDApp.get_running_app().root.current = "ScreenVideo1"
MDApp.get_running_app().root.ScreenVideo1.test_on_enter(r'C:\file\location' + fileName + '.MOV')
is trying to treat the root widget of the App as a ScreenManager, but it isn't, it is a RootScreen. So, you need to access the ScreenManager, like this:
class RootScreen(Screen):
def onNextScreen(self, btn, fileName):
MDApp.get_running_app().root.ids.screen_manager.current = "Video1"
MDApp.get_running_app().root.ids.screen_manager.current_screen.test_on_enter(r'C:\file\location' + fileName + '.MOV')

MDExpansion Panel - kivy.properties.DictProperty' object has no attribute 'panel_container'

I am currently building a mobile app with kivy. In one of my screens I am trying to include an MDExpansionPanel, although I have tried with a lot of different codes, and searched on the web for solutions, either I get an error, or simply the Expansion Panel is not rendered in my screen. I am using ScreenManager since I have 5 screens, with the possibility of increasing such number.
The relevant Python code is the following:
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.app import MDApp
from kivymd.theming import ThemeManager
from kivymd.toast import toast
from kivymd.uix.picker import MDDatePicker, MDTimePicker
from kivymd.uix.expansionpanel import MDExpansionPanel
from kivymd.uix.boxlayout import MDBoxLayout
class LoginWindow(Screen):
pass
class CreateAccountWindow(Screen):
pass
class MainWindow(Screen):
pass
class TravelManagerWindow(Screen):
pass
class IngActivWindow(Screen):
panel_container = ObjectProperty(None)
def on_pre_enter(self, *args):
self.add_panels()
def show_timepicker(self):
picker = MDTimePicker()
picker.bind(time=self.got_time)
picker.open()
def got_time(self, picker_widget, time):
self.text = str(time.hour) + ":" + str(time.minute)
self.focus = False
# selectedTime= self.text
print(self.text)
self.ids.tiempoActiv.text = self.text
def add_panels(self):
for i in range(5):
IngActivWindow.ids.panel_container.add_widget(
MDExpansionPanel(
icon="actividades.png",
content=MyContent(),
panel_cls=MDExpansionPanelOneLine(
text="Text",
)
)
)
class MyContent(MDBoxLayout):
pass
class WindowManager(ScreenManager):
ScreenManager().add_widget(LoginWindow(name='login'))
ScreenManager().add_widget(CreateAccountWindow(name='create'))
ScreenManager().add_widget(MainWindow(name='main'))
ScreenManager().add_widget(IngActivWindow(name='ingActiv'))
ScreenManager().add_widget(TravelManagerWindow(name='travelManager'))
class powerApp1(MDApp):
def build(self):
self.theme_cls.primary_palette = "Teal"
return WindowManager()
if __name__ == "__main__":
powerApp1().run()
The relevant kv code is the following:
(I have an image on the background and an Action Bar before the MDBoxLayout where I am trying to add the Expansion Panel)
<WindowManager>:
LoginWindow:
CreateAccountWindow:
MainWindow:
IngActivWindow:
TravelManagerWindow:
<IngActivWindow>:
name: 'ingActiv'
panel_container: panel_container
FloatLayout:
cols:1
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'ingActiv_background.png'
ActionBar:
pos_hint: {'top':1}
ActionView:
use_separator: True
ActionPrevious:
title: '---------'
with_previous: False
ActionButton:
icon: 'homeIcon.png'
on_press:
root.manager.current = 'main'
root.manager.transition.direction = 'right'
ActionGroup:
text: 'Gastos de Viaje'
mode: 'spinner'
size_hint:(None,None)
size: root.width/5,root.height/12
ActionButton:
text: 'Solicitar'
on_release:
root.manager.current = 'solicitud'
root.manager.transition.direction = 'left'
ActionButton:
text: 'Comprobar'
on_release:
root.manager.current = 'comprobar'
root.manager.transition.direction = 'left'
ActionGroup:
text: 'Opciones'
mode: 'spinner'
size_hint:(None,None)
size: root.width/5,root.height/12
ActionButton:
text: 'Ingresar Actividad'
on_release:
root.manager.current = 'ingActiv'
root.manager.transition.direction = 'left'
ActionButton:
text: 'Enviar Reporte'
ActionButton:
text: 'Cerrar Sesion'
on_release:
root.manager.current = 'login'
root.manager.transition.direction = 'down'
MDBoxLayout:
cols:1
size_hint: 1,0.6
pos_hint: {"center_x": 0.5, "center_y": 0.5}
ScrollView:
GridLayout:
id: panel_container
cols: 1
pos_hint: {"center_x": 0.5, "center_y": 0.5}
<MyContent>:
size_hint: 1, None
height: self.minimum_height
orientation: 'horizontal'
Button:
size_hint: None, None
Thanks a lot in advance for your support,
Have a great day.

Kivy-If A button bind with callback(instance), how to call other functions

What i want is that:
Press button A >> Open choose folder dialog >> Select folder A >> Show path A in label A;
Press button B >> Open choose folder dialog >> Select folder B >> Show path B in label B.
If you run my code, it works very good. But if you read the code carefully, you will find a issue.
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty
from kivy.properties import ObjectProperty
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.11.0
<Root>:
loadFolderA: loadFolderA
loadFolderB: loadFolderB
cols: 2
rows: 2
Button:
id: selectFolderA
text: 'select folder A'
pos_hint: {'center_x': 0.21, 'center_y': .5}
on_release: root.show_select_folder_dialogA()
Button:
id: selectFolderB
text: 'select folder B'
pos_hint: {'center_x': 0.785, 'center_y': .5}
on_release: root.show_select_folder_dialogB()
Label:
id: loadFolderA
text: 'path A'
font_size: 30
pos_hint: {'center_x': 0.21, 'center_y': .5}
Label:
id: loadFolderB
text: 'path B'
font_size: 30
pos_hint: {'center_x': 0.785, 'center_y': .5}
<SelectFolder>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Choose"
on_release: root.choose(filechooser.path, filechooser.selection)
''')
class Root(GridLayout):
posixPathA = StringProperty('')
posixPathB = StringProperty('')
def dismiss_popup(self):
self._popup.dismiss()
def show_select_folder_dialogA(self):
content = SelectFolder(choose=self.chooseA, cancel=self.dismiss_popup)
self._popup = Popup(title="Select Folder", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def show_select_folder_dialogB(self):
content = SelectFolder(choose=self.chooseB, cancel=self.dismiss_popup)
self._popup = Popup(title="Select Folder", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def chooseA(self, path, filename):
self.posixPathA = path
self.loadFolderA.text = self.posixPathA
self.dismiss_popup()
def chooseB(self, path, filename):
self.posixPathB = path
self.loadFolderB.text = self.posixPathB
self.dismiss_popup()
class SelectFolder(FloatLayout):
choose = ObjectProperty(None)
cancel = ObjectProperty(None)
class DropApp(App):
def build(self):
return Root()
if __name__ == '__main__':
DropApp().run()
The function 'show_select_folder_dialog' I write in two times, one for binding with button A, one for button B. And same to the function 'choose'. It really makes me unhappy. So I want to know if I can make the Code know which button is pressed, then pass the folder path to the right label. Hope someone can help.
#
#
It takes all night, now i come to this place:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty
from kivy.properties import ObjectProperty
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.11.0
<Root>:
loadFolderA: loadFolderA
loadFolderB: loadFolderB
cols: 2
rows: 2
NewButton:
id: selectFolderA
text: 'select folder A'
pos_hint: {'center_x': 0.21, 'center_y': .5}
on_release: self.callback()
NewButton:
id: selectFolderB
text: 'select folder B'
pos_hint: {'center_x': 0.785, 'center_y': .5}
on_release: self.callback()
Label:
id: loadFolderA
text: 'path A'
font_size: 30
pos_hint: {'center_x': 0.21, 'center_y': .5}
Label:
id: loadFolderB
text: 'path B'
font_size: 30
pos_hint: {'center_x': 0.785, 'center_y': .5}
<SelectFolder>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Choose"
on_release: root.choose(filechooser.path, filechooser.selection)
''')
class NewButton(Button):
def __init__(self, **kwargs):
super(Button, self).__init__(**kwargs)
def callback(instance):
print('The button <%s> is being pressed' % instance.text)
Root.show_select_folder_dialog(Root)
class Root(GridLayout):
posixPathA = StringProperty('')
posixPathB = StringProperty('')
def dismiss_popup(self):
self._popup.dismiss()
def show_select_folder_dialog(self):
content = SelectFolder(choose=self.choose, cancel=self.dismiss_popup)
self._popup = Popup(title="Select Folder", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def choose(self, path, filename):
self.posixPathA = path
self.loadFolderA.text = self.posixPathA
self.dismiss_popup()
class SelectFolder(FloatLayout):
choose = ObjectProperty(None)
cancel = ObjectProperty(None)
class DropApp(App):
def build(self):
return Root()
if __name__ == '__main__':
DropApp().run()
My plan is that use Callback(instance) to know which button was calling the function. Then call the Function to open choose folder dialog. It's strange but this line works here:
Root.show_select_folder_dialog(Root)
But I cannot go further. Now the function report error:'TypeError: choose() missing 1 required positional argument: 'filename''
Hope someone can help me!
You can remove both the duplicate A/B methods by sending an idx with the button press:
Builder.load_string('''
#:kivy 1.11.0
<Root>:
loadFolderA: loadFolderA
loadFolderB: loadFolderB
cols: 2
rows: 2
Button:
id: selectFolderA
text: 'select folder A'
pos_hint: {'center_x': 0.21, 'center_y': .5}
on_release: root.show_select_folder_dialog("A") # send an idx here
Button:
id: selectFolderB
text: 'select folder B'
pos_hint: {'center_x': 0.785, 'center_y': .5}
on_release: root.show_select_folder_dialog("B") # send an idx here
Label:
id: loadFolderA
text: 'path A'
font_size: 30
pos_hint: {'center_x': 0.21, 'center_y': .5}
Label:
id: loadFolderB
text: 'path B'
font_size: 30
pos_hint: {'center_x': 0.785, 'center_y': .5}
<SelectFolder>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Choose"
on_release: root.choose(filechooser.path, filechooser.selection)
''')
from functools import partial
class Root(GridLayout):
posixPathA = StringProperty('')
posixPathB = StringProperty('')
def dismiss_popup(self):
self._popup.dismiss()
def show_select_folder_dialog(self, idx):
# pass the idx to the choose method
content = SelectFolder(choose=partial(self.choose, idx),
cancel=self.dismiss_popup)
self._popup = Popup(title="Select Folder", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def choose(self, idx, path, filename):
if idx == "A": # The "A" button was selected
self.posixPathA = path
self.loadFolderA.text = self.posixPathA
else: # You can use more elifs if you like
self.posixPathB = path
self.loadFolderB.text = self.posixPathB
self.dismiss_popup()
class SelectFolder(FloatLayout):
choose = ObjectProperty(None)
cancel = ObjectProperty(None)
class DropApp(App):
def build(self):
return Root()
if __name__ == '__main__':
DropApp().run()
Hey Friend i have got a simple solution for your code which makes it easier to recognise which button you have chosen for that you can use easygui module:
choice = easygui.buttonbox(title="Choose button",msg="Choose a button",choices=["Button 1","Button 2",])
which opens a box like:
And now you can use your if condition to and do the rest of the process.

random screen display with kivy

i am trying to make an app, a game actually that will display random screens when the "NEXT" button is touched, so i made the screens and the labels to be displayed on each screen but i cant get it to display a random screen when the "NEXT" button is touched, it just follows a pattern, would anyone help me here? heres the code:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import Image kivy.uix.image.Image
#: import SoundLoader kivy.core.audio.SoundLoader
ScreenManagement:
transition: FadeTransition()
MainScreen:
GameScreen:
GameScreen2:
GameScreen3:
GameScreen4:
<Button>:
font_size: 12
size_hint: 0.2, 0.1
<MainScreen>:
name: "main"
FloatLayout:
Button:
text: "START GAME"
color: 1,0,1,1
pos_hint: {"x": 0, "y":0}
on_release: app.root.current = "game"
Button:
text: "QUIT"
color: 1,0,0,1
pos_hint: {"x": .8, "y": 0}
on_release: quit()
Button:
text: "SOUND"
color: 0,1,0,1
pos_hint: {"x":.2 , "y": .4}
on_press: app.play_sound1()
<GameScreen>:
name: "game"
FloatLayout:
Label:
text: "Python\nSnowden\nMr.Robot"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y": 0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
Button:
text: "Next"
on_release: app.root.current = "game2"
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
<GameScreen2>:
name: "game2"
FloatLayout:
Label:
text: "Banana\n\nOrange\n\nTea\n\nSleep"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y": 0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
Button:
text: "Next"
on_release: app.root.current = "game3"
color: 0,1,0,1
pos_hint: {"x": 0, "y": 0}
<GameScreen3>:
name: "game3"
FloatLayout:
Label:
text: "Assembly\n\nRuby\n\nC"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
Button:
text: "Next"
on_release: app.root.current = "game4"
color: 0,1,0,1
pos_hint: {"x": 0, "y": 0}
<GameScreen4>:
name: "game4"
FloatLayout:
Label:
text: "Prolog\n\nPygame\n\nC++"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
the above is the kv code, sorry for the mess im an amateur when it comes to kivy
and heres the python side code:
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.core.audio import SoundLoader
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class MainScreen(Screen):
pass
class GameScreen(Screen):
pass
class GameScreen2(Screen):
pass
class GameScreen3(Screen):
pass
class GameScreen4(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("quora.kv")
class MainApp(App):
def build(self):
self.load_sounds()
return presentation
def load_sounds(self):
self.sounds = {}
for i in range(10):
fname = 'sound' + str(i+1) + '.wav'
self.sounds[i] = SoundLoader.load(fname)
def play_sound1(self):
sound = self.sounds.get(0)
if sound is not None:
sound.volume = 0.5
sound.play()
def play_sound2(self):
sound = self.sounds.get(1)
if sound is not None:
sound.volume = 0.5
sound.play()
if __name__ == "__main__":
MainApp().run()
this is the sample i made for you because the original one is way bigger than this i dont know how to use somewhat of a LOOP to generate screen so i made more that 20 screens on the original code so, and if you could help me figure out how can i STOP THE MENU SONG when i hit the "START" BUTTON, so that i can hit the "SONG" BUTTON on SCREEN1 to PLAY its SONG i would be gratefull. thanks you for the patience.
Display random screens when the "NEXT" button is touched
Use screen_names
screen_names
List of the names of all the Screen widgets added. The list is
read only.
screens_names is an AliasProperty and is read-only. It is updated
if the screen list changes or the name of a screen changes.
Snippets
#:import choice random.choice
...
Button:
text: "Next"
on_release:
root.manager.current = choice(root.manager.screen_names[1:])
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
Stop / Play Music
You might want to use a ToggleButton instead of Button for playing music. Please refer to the example below.
Example
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.togglebutton import ToggleButton
from kivy.core.audio import SoundLoader
from kivy.properties import ObjectProperty
class MusicScreen(Screen):
enter = ObjectProperty(None)
text_input = ObjectProperty(None)
stop = ObjectProperty(None)
musicbutton = ToggleButton()
class ScreenManagement(ScreenManager):
pass
class MainApp(App):
sound = ObjectProperty(None, allownone=True)
def build(self):
return ScreenManagement()
def on_state(self, state, filename):
print("ONSTATE!!!")
print("\tstate=", state)
if self.sound is None:
self.sound = SoundLoader.load(filename)
# stop the sound if it's currently playing
if self.sound.status != 'stop':
self.sound.stop()
if state == "down":
self.sound.volume = .5
self.sound.play()
else: # if state == "normal":
if self.sound:
self.sound.stop()
# self.sound.unload()
self.sound = None
if __name__ == "__main__":
MainApp().run()
main.kv
#:kivy 1.11.0
<ScreenManagement>:
MusicScreen:
name: 'music'
<MusicScreen>:
text_input: text_input
id: "music"
name: "music"
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
rootpath: "/home/iam/Music/"
on_selection: text_input.text = self.selection and self.selection[0] or ''
TextInput:
id: text_input
size_hint_y: None
height: 50
multiline: False
ToggleButton:
size_hint: 1, .2
text: "Play/Stop By File"
on_state: app.on_state(self.state, text_input.text)
ToggleButton:
id: musicbutton
size_hint: 1, .2
text: "Play/Stop By Title"
on_state: app.on_state(self.state, text_input.text)

Kivy: changing image source on screen

After much headbanging, I've created an app that opens the FileChooser and picks an image. A function will then transform the image and change it on the screen.
< FirstScreen > is just something to start with, relatively unimportant.
< SecondScreen > is the file chooser. The path may need editing. < ThirdScreen > shoudl show the image along with buttons that will eventually lead elsewhere.
I suspect the problem is that the line
sm.current = "_third_screen_"
is creating a new instance separate to everything else I've passed items too. How do I show the image I selected?
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
Builder.load_string("""
<MyScreenManager>:
FirstScreen:
SecondScreen:
ThirdScreen:
<FirstScreen>:
name: '_first_screen_'
BoxLayout:
orientation: "horizontal"
Label:
id: first_screen_label
text: "Hi, I'm the home page"
BoxLayout:
orientation: "vertical"
Button:
text: "Okay!"
on_press: root.manager.current = '_second_screen_'
Button:
text: "Cancel!"
on_press: app.stop()
<SecondScreen>:
name: '_second_screen_'
id: file_chooser
BoxLayout:
id: file_chooser_box_layout
orientation: "horizontal"
Button
text: "Open"
on_press:
root.callback_image_and_other_stuff(file_chooser_list_view.selection)
FileChooserListView:
id: file_chooser_list_view
<ThirdScreen>:
name: '_third_screen_'
BoxLayout:
orientation: "vertical"
id: third_screen
Label:
id: main_title
text: "Upload"
size_hint: (1, 0.1)
Image:
id: main_image
source: root.img
size_hint: (1, 0.75)
BoxLayout:
orientation: "horizontal"
padding: 10
size_hint: (1, 0.15)
Button:
text: "Okay"
size_hint: (0.5, 1)
on_press: image_viewer.image_accepted_by_user(filechooser.selection)
Button:
text: "Cancel"
size_hint: (0.5, 1)
on_press: root.manager.current = '_first_screen_'
""")
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
def callback_image_and_other_stuff(self, new_image_address):
# do other stuff here also, then pass new_image_address along
new_image_address = new_image_address[0].replace("\\", "/")
third_screen = ThirdScreen()
third_screen.callback_image(new_image_address)
class ThirdScreen(Screen):
img = ObjectProperty(None)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
def callback_image(self, new_image_address):
sm.current = "_third_screen_"
self.img = new_image_address
self.ids.main_image.source = self.img
print(self.img)
# Create the screen manager
sm = ScreenManager() # Problem?
sm.add_widget(FirstScreen(name='_first_screen_'))
sm.add_widget(SecondScreen(name='_second_screen_'))
sm.add_widget(ThirdScreen(name='_third_screen_'))
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()
Every time you use some_obj = SomClass() you are creating a new object, in your case that is what you are doing, you are creating a new ThirdScreen different from the one shown by that you do not observe the image, the solution is that you have to access to the initial object using the ScreenManager and name screen.
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
Builder.load_string("""
<FirstScreen>:
BoxLayout:
orientation: "horizontal"
Label:
id: first_screen_label
text: "Hi, I'm the home page"
BoxLayout:
orientation: "vertical"
Button:
text: "Okay!"
on_press: root.manager.current = '_second_screen_'
Button:
text: "Cancel!"
on_press: app.stop()
<SecondScreen>:
id: file_chooser
BoxLayout:
id: file_chooser_box_layout
orientation: "horizontal"
Button
text: "Open"
on_press:
root.callback_image_and_other_stuff(file_chooser_list_view.selection)
FileChooserListView:
id: file_chooser_list_view
<ThirdScreen>:
BoxLayout:
orientation: "vertical"
id: third_screen
Label:
id: main_title
text: "Upload"
size_hint: (1, 0.1)
Image:
id: main_image
source: root.img
size_hint: (1, 0.75)
BoxLayout:
orientation: "horizontal"
padding: 10
size_hint: (1, 0.15)
Button:
text: "Okay"
size_hint: (0.5, 1)
on_press: image_viewer.image_accepted_by_user(filechooser.selection)
Button:
text: "Cancel"
size_hint: (0.5, 1)
on_press: root.manager.current = '_first_screen_'
""")
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
def callback_image_and_other_stuff(self, new_image_address):
if new_image_address:
third_screen = self.manager.get_screen("_third_screen_")
# do other stuff here also, then pass new_image_address along
new_image_address = new_image_address[0].replace("\\", "/")
third_screen.callback_image(new_image_address)
class ThirdScreen(Screen):
img = ObjectProperty(None)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
def callback_image(self, new_image_address):
sm.current = "_third_screen_"
self.img = new_image_address
self.ids.main_image.source = self.img
print(self.img)
# Create the screen manager
sm = ScreenManager() # Problem?
sm.add_widget(FirstScreen(name='_first_screen_'))
sm.add_widget(SecondScreen(name='_second_screen_'))
sm.add_widget(ThirdScreen(name='_third_screen_'))
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()

Categories

Resources