Kivy Inherit ScreenManager from FloatLayout - python

I am having trouble understanding how to inherit the functionality of one class into another with Kivy. I understand the error message ('LoadDialog_Directory' object has no attribute 'manager'), but I'm just not grasping exactly how to fix it. I believe I need to do something with the function below, but ultimately, I do not know.
def __init__(self, **kwargs):
super().__init__(**kwargs)
The goal of this script is to be able to select a specific driver as the path for the filechooser. I choose this method vs. others because most were using Kivy 1.11.1, this version has a lot of deprecated functions that do not work with 2.0.
.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.spinner import SpinnerOption
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
from kivy.utils import platform
from kivy.properties import StringProperty
import os
import string
class WindowManager(ScreenManager):
pass
class MyOption(SpinnerOption):
pass
class LoadDialog_Directory(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
def dir_driver(self):
x = self.manager.get_screen("first")
return str(x.ids.drive_dir.text)
class FirstWindow(Screen):
def get_drives(self):
drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
return drives
def dismiss_popup(self):
self._popup.dismiss()
def show_load_directory(self):
content = LoadDialog_Directory(load=self.directroy_path, cancel=self.dismiss_popup)
self._popup = Popup(title="Load file", content=content, size_hint=(0.9, 0.9))
self._popup.open()
def directroy_path(self, path, filename):
self.ids.text_input_directory.text = str(filename[0])
self.dismiss_popup()
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
WindowManager:
FirstWindow:
<LoadDialog_Directory>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
dirselect: True
path: root.dir_driver()
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)
first.kv
<FirstWindow>
name: 'first'
GridLayout:
cols: 1
BoxLayout:
orientation: "horizontal"
TextInput:
BoxLayout:
orientation: "horizontal"
Spinner:
id: drive_dir
text: "Root Drive"
halign: 'center'
option_cls: "MyOption"
values: root.get_drives()
Button:
text: "Set Result Directory"
on_release: root.show_load_directory()
TextInput:
id: text_input_directory
disabled: True
text: text_input_directory.text
BoxLayout:
size_hint: (0.01, 1)
orientation: "horizontal"
TextInput:
Side Note: The reason for the extra blank TextInput is because the Spinner will not function (show drivers) if it is taking too much of the App.

After a few hours of trail and error I finally got it to work, but I have no idea why it works. Here is what changed:
New variable in class LoadDialog_Directory(FloatLayout) - input_pth
Called input_pth into my content variable within class FirstWindow(Screen) function show_load_directory(self)
Set my filechooser.path to root.input_pth in the main.kv file.
I do not understand how the input_pth variable within content is able to reference the class LoadDialog_Directory(FloatLayout) without having to pass something like:
def __init__(self, input_pth, **kwargs):
super(LoadDialog_Directory, self).__init__()
self.input_pth = input_pth
.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.spinner import SpinnerOption
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
from kivy.utils import platform
from kivy.properties import StringProperty
import os
import string
class WindowManager(ScreenManager):
pass
class MyOption(SpinnerOption):
pass
class LoadDialog_Directory(FloatLayout):
input_pth = StringProperty()
load = ObjectProperty()
cancel = ObjectProperty()
class FirstWindow(Screen):
def drive_list(self):
drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
return drives
def dismiss_popup(self):
self._popup.dismiss()
def show_load_directory(self):
content = LoadDialog_Directory(load=self.directroy_path, cancel=self.dismiss_popup, input_pth=self.ids.drive_dir.text)
self._popup = Popup(title="Load file", content=content, size_hint=(0.9, 0.9))
self._popup.open()
def directroy_path(self, path, filename):
self.ids.text_input_directory.text = str(filename[0])
self.dismiss_popup()
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
WindowManager:
FirstWindow:
<LoadDialog_Directory>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
dirselect: True
path: root.input_pth
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)
first.kv
<FirstWindow>
name: 'first'
GridLayout:
cols: 1
BoxLayout:
orientation: "horizontal"
TextInput:
BoxLayout:
orientation: "horizontal"
Spinner:
id: drive_dir
halign: 'center'
option_cls: "MyOption"
values: root.drive_list()
Button:
text: "Set Result Directory"
on_release: root.show_load_directory()
TextInput:
id: text_input_directory
disabled: True
text: text_input_directory.text
BoxLayout:
size_hint: (0.01, 1)
orientation: "horizontal"
TextInput:

Related

Geeting error in reading a file and pronting it as Label in kivy

I am trying to read text from a file and show it as Label in another screen but i am getting error that text file's content in not str even after using str() function.
Error:
ValueError: Screen1.usename accept only str
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
class Screen1(Screen):
def gb(self):
f=open('test.txt','r')
b=f.read()
t=str(b)
return t
usename = StringProperty("")
class Screen2(Screen):
username = StringProperty("")
root = Builder.load_string('''
<Screen1>:
BoxLayout:
orientation: "vertical"
Button:
text:'ue'
on_release: root.usename = root.gb; root.manager.current = "screen2"
<Screen2>:
name: "screen2"
Label:
text: root.username
ScreenManager:
Screen1:
id: loginscreen
Screen2:
username: loginscreen.usename
''')
class MyApp(App):
def build(self):
return root
r=MyApp()
r.run()
Your code:
on_release: root.usename = root.gb
is trying to set the usename to a method (root.gb). You probably want to set usename to the return value of that method. Try just adding (), like this:
on_release: root.usename = root.gb()
I finally solved the issue, this's how we can read a text file and display it as label in another screen in kivy.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
class Screen1(Screen):
f=open('test.txt','r')
t=f.readlines()
b=t[0]
f.close()
class Screen2(Screen):
username = StringProperty("")
root = Builder.load_string('''
<Screen1>:
name:'xy'
id:loginscreen
BoxLayout:
orientation: "vertical"
Button:
text:'Execution button'
on_release: root.manager.current = "screen2"
<Screen2>:
name: "screen2"
FloatLayout:
Label:
text: root.username
Button:
text:'Back to menu'
size_hint:.3,.3
on_release: root.manager.current = "xy"
ScreenManager:
Screen1:
id:loginscreen
Screen2:
username: loginscreen.b
''')
class MyApp(App):
def build(self):
return root
r=MyApp()
r.run()

IconRightWidget in the wrong place

I'm coding a book reader app with kivymd. I tryied making a MDList with the avaliable chapters and a button to download in every ListItem.
This is a piece of my code:
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.list import TwoLineListItem
from kivy.lang import Builder
from kivymd.uix.list import IconRightWidget
class Library(Screen):
pass
class Book(Screen):
pass
class SM(ScreenManager):
pass
KV = '''
SM:
Library:
Book:
<Library>:
MDFloatingActionButton:
pos_hint: {"center_x": 0.5, "center_y": 0.5}
on_release:
app.root.current = "book"
app.list_chapters()
<Book>:
name: "book"
MDBoxLayout:
orientation: "vertical"
MDToolbar:
id: toolbar
ScrollView:
MDList:
id: chap
'''
class Aplication(MDApp):
def build(self):
screen = Builder.load_string(KV)
self.chaps = True
return screen
def list_chapters(self):
if self.chaps:
for chap in range(0, 11):
chapter = TwoLineListItem(text= f'Chapter {chap}')
rightIcon = IconRightWidget(icon="arrow-down-circle-outline")
self.root.get_screen("book").ids.chap.add_widget(chapter)
chapter.add_widget(rightIcon)
self.chaps = False
Aplication().run()
For some reason, all of the IconRightWidget Buttons are getting in the corner of the last TwoListItem. What should I do?

Switching between kivy classes inside one screen

I'm looking for a way to change a part of a screen between 'DownPanel1' and 'DownPanel1' but I would like to avoide creating nex screen class 'ToAvoid'. Is it possible?
from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
kv = '''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
SomeScreen:
ToAvoid:
<Menu#RelativeLayout>
id: main_menu
size_hint_x: None
width: 120
Button:
size_hint_y: None
pos: root.x, root.top - self.height
text: 'SomeScreen'
on_press: app.root.current = "SomeScreen"
<UpScreen>:
BoxLayout:
Button:
text: 'switch'
on_press: app.root.current = "ToAvoid"
<DownPanel1>:
Button:
text: 'DownPanel1'
#on_press:
<DownPanel2>:
Button:
text: 'DownPanel2'
#on_press:
<SomeScreen>:
name: 'SomeScreen'
BoxLayout:
orientation: 'horizontal'
Menu:
BoxLayout:
orientation: 'vertical'
UpScreen:
DownPanel1:
<ToAvoid>:
name: 'ToAvoid'
BoxLayout:
orientation: 'horizontal'
Menu:
BoxLayout:
orientation: 'vertical'
UpScreen:
DownPanel2:
'''
class DownPanel1(BoxLayout):
pass
class DownPanel2(BoxLayout):
pass
class UpScreen(Screen):
pass
class SomeScreen(Screen):
pass
class ToAvoid(Screen):
pass
class ScreenManagement(ScreenManager):
pass
sm = Builder.load_string(kv)
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
How about some inception? Just put another ScreenManager inside of the other.
Try this example:
from kivy.app import App
from kivy.lang import Builder
KV = """
ScreenManager:
Screen:
name: "1st"
Button:
text: "next"
on_release:
root.current = "2nd"
Screen:
name: "2nd"
BoxLayout:
Button:
text: "3rd to avoid"
on_release:
root.current = "3rd"
ScreenManager:
id: sm2
Screen:
name: "inner1"
Button:
text: "go to inner 2"
on_release:
sm2.current = "inner2"
Screen:
name: "inner2"
Label:
text: "This is inner 2!"
Screen:
name: "3rd"
Label:
text: "To Avoid!"
"""
class MyApp(App):
def build(self):
return Builder.load_string(KV)
if __name__ == "__main__":
MyApp().run()

Mimic Tkinter file open in Kivy

I have worked mostly with Tkinter before and I used the following code to store path of file I selected. After exploring Kivy, it doesn't seem like Kivy have a simple function like this. So I tried using the filechoser instead
path = filedialog.askopenfilename(initialdir="/", title="Select file")
Main code is very simple
class checker_ui(GridLayout):
def findreport(self,path):
pass
class Checker(App):
def build(self):
return checker_ui()
if __name__ == '__main__':
Checker().run()
Then I created a .kv file just to see what filechooser looks like. The script would just open and freeze.
<checker_ui>:
BoxLayout:
FileChooserIconLayout:
id:filechooser
on_selection:root.select(*args)
Here is the output
I search all over the place and did not see anyone with a similar issue. Is there an alternative I can try to mimic the tkinter behaviour or am I stuck with this issue? I'm on a Windows machine and normal kivy widget works, ie: button,label etc.
so I wrote a lot more code than you (based heavily on the kivy example # https://kivy.org/docs/api-kivy.uix.filechooser.html#usage-example)
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
from kivy.lang import Builder
Builder.load_string("""
#:kivy 1.1.0
<Root>:
text_input: text_input
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: None
height: 30
Button:
text: 'Load'
on_release: root.show_load()
Button:
text: 'Save'
on_release: root.show_save()
BoxLayout:
TextInput:
id: text_input
text: ''
RstDocument:
text: text_input.text
show_errors: True
<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)
<SaveDialog>:
text_input: text_input
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
on_selection: text_input.text = self.selection and self.selection[0] or ''
TextInput:
id: text_input
size_hint_y: None
height: 30
multiline: False
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Save"
on_release: root.save(filechooser.path, text_input.text)""")
import os
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
class SaveDialog(FloatLayout):
save = ObjectProperty(None)
text_input = ObjectProperty(None)
cancel = ObjectProperty(None)
class Root(FloatLayout):
loadfile = ObjectProperty(None)
savefile = ObjectProperty(None)
text_input = ObjectProperty(None)
def dismiss_popup(self):
self._popup.dismiss()
def show_load(self):
content = LoadDialog(load=self.load, cancel=self.dismiss_popup)
self._popup = Popup(title="Load file", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def show_save(self):
content = SaveDialog(save=self.save, cancel=self.dismiss_popup)
self._popup = Popup(title="Save file", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def load(self, path, filename):
with open(os.path.join(path, filename[0])) as stream:
self.text_input.text = stream.read()
self.dismiss_popup()
def save(self, path, filename):
with open(os.path.join(path, filename), 'w') as stream:
stream.write(self.text_input.text)
self.dismiss_popup()
class Editor(App):
def build(self):
return Root()
if __name__ == '__main__':
Editor().run()
Solution
Replace FileChooserIconLayout with FileChooserIconView
Add a BoxLayout and make FileChooserIconView a children of the BoxLayout
Example
main.py
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
class Checker_ui(GridLayout):
def findreport(self, path):
print("path=", path)
class Checker(App):
def build(self):
return Checker_ui()
if __name__ == "__main__":
Checker().run()
checker.kv
#:kivy 1.10.0
<Checker_ui>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserIconView:
id: filechooser
on_selection: root.select(*args)
Output
Hey if anyone wants to open all types of file just use(mp4,jpg,pdf,txt,docs...etc)
import webbrowser
webbrowser.open(filename[0])

Not able to switch screen in kivy

I have below files i am trying to switch to new windows once the button on homescreen is pressed but it throws error 'No Screen with name "VerifyScreen"'
I debugged a bit and copy pasted the Screen: part from verifyscreen.kv to our homescreen.kv file and it started working.
But why its not able to get the screen even i get the two kv files in starting only??
homescreen.kv
<HomeScreen>:
orientation: 'vertical'
screen_manager: screen_manager
ScreenManager:
size_hint: 1, 1
id: screen_manager
Screen:
BoxLayout:
orientation: 'vertical'
name: 'Home_Screen'
id: 'home'
Label:
markup: True
text: 'Home-Panel'
Button:
text: 'submitt'
size_hint: 1,1
id: submitt
pos_hint: {'center_x': .5}
on_press:
root.verify()
verifyscreen.kv
<VerifyScreen>:
orientation: 'vertical'
verify_screen_manager: verify_screen_manager
ScreenManager:
size_hint: 1, 1
id: verify_screen_manager
Screen:
name: 'VerifyScreen'
id: verify_screen
main.py
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
from functools import partial
import os
import random
import kivy
kivy.require('1.8.0')
#all required modules are imported
from kivy.uix.screenmanager import Screen
from kivy.uix.screenmanager import ScreenManager
slides = [ "HomeScreen","VerifyScreen" ]
for slide in slides:
kv_file = "{}.kv".format(slide.lower())
Builder.load_file(os.path.join("slides", kv_file))
class HomeScreen(Screen):
screen_manager = ObjectProperty(None)
verify_screen_manager = ObjectProperty(None)
verify_screen = ObjectProperty(None)
def __init__(self, **kwargs):
super(HomeScreen, self).__init__(**kwargs)
self.orientation = 'vertical'
def verify(self):
print "manish"
#self.screen_manager.current = 'VerifyScreen'
self.screen_manager.switch_to(self.verify_screen)
class HomeScreenApp(App):
def build(self):
return HomeScreen()
if __name__ == '__main__':
HomeScreenApp().run()

Categories

Resources