sockets with kivy-recv line don't work - kivy

I made an app working with kivy that sends "name" to the server(with socket), the server inserts the "name" to the data base and sends back the "name" to the client(the app) and the client prints it.
I don't get any error but the app doesn't work. it is not open.
My client(the app):
# kivy.require("1.8.0")
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.graphics import Line
from kivy.uix.button import Button
import socket
Builder.load_string("""
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
<MenuScreen>:
BoxLayout:
Button:
text: 'Sign Up'
on_press:
root.manager.transition.direction = 'left'
root.manager.current = 'settings'
Button:
text: 'Login'
on_press:
root.manager.transition.direction = 'left'
root.manager.current = 'settings'
<Searchi>:
BoxLayout:
Button:
text: 'send massage'
font_size: '20sp'
size_hint: (0.4,0.111)
pos_hint: {'y': 0,'x':0.6}
on_press:
root.manager.transition.direction = 'right'
root.manager.current = 'settings'
<SettingsScreen>:
BoxLayout:
FloatLayout:
LoginScreen
Button:
font_size: '20sp'
size_hint: (0.4,0.111)
pos_hint: {'y': 0,'x':0.6}
text: 'Back to menu'
on_press:
root.manager.transition.direction = 'right'
root.manager.current = 'menu'
""")
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.my_socket = socket.socket()
#host = socket.gethostname()
#port = 8585
self.my_socket.connect(('127.0.0.1', 8081))
self.add_widget(Label(text='username'))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text='Password'))
self.password = TextInput(multiline=False, password=True)
self.add_widget(self.password)
self.submit_button = Button(text='sumbit',size_hint=(.5,
.25),font_size=20)
self.submit_button.bind(on_press=self.submit_username)
self.add_widget(self.submit_button)
def submit_username(self, *args):
# Make sure to validate the input before submitting to the server
self.my_socket.send(self.username.text.encode('utf-8'))
sm.current = 'searchi'
sm.transition.direction = 'left'
# Declare both screens
class MenuScreen(Screen):
pass
class SettingsScreen(Screen):
pass
class Searchi(Screen):
def __init__(self, **kwargs):
super(Searchi, self).__init__(**kwargs)
self.my_socket = socket.socket()
self.my_socket.connect(('127.0.0.1', 8081))
self.msg=self.my_socket.recv(1024)
self.name=self.msg.decode('utf-8')
self.add_widget(Label(text="hello"+self.name,size_hint=(1,
1.7),font_size=20))
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(Searchi(name='searchi'))
sm.add_widget(SettingsScreen(name='settings'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
My server:
import socket
import db # import my db
import time
server_socket = socket.socket()
server_socket.bind(('127.0.0.1',8081))
server_socket.listen(5)
(client_socket, client_address) = server_socket.accept()
while(True):
client_username = client_socket.recv(1024)
msg=client_username.decode('utf-8')
db.data_entry_login(msg,"dsfsds","dsfsfsdd","2") #insert to my db
msg=msg+"\r\n"
client_socket.send(msg.text.encode('utf-8'))
Can you help me?

The problem is as you mentioned the recv method.
That method put the whole main thread on hold, so the app wont run.
Whenever something is waiting or looping in the mainthread, the app will stop updating. And recv is waiting for a message.
So you need to put the recv in a thread.
You could do like this:
import threading
from kivy.clock import mainthread
class Searchi(Screen):
def __init__(self, **kwargs):
super(Searchi, self).__init__(**kwargs)
self.hello_label = Label(text="Connecting...",size_hint=(1,1.7),font_size=20)
threading.Thread(target=self.recv_msg).start()
# make sure you execute UI updates in mainthread
#mainthread
def recv_msg(self):
self.my_socket = socket.socket()
self.my_socket.connect(('127.0.0.1', 8081))
self.msg=self.my_socket.recv(1024)
self.name=self.msg.decode('utf-8')
self.hello_label.text = "hello"+self.name

Related

Add KivyMD Expansion Panel inside RecyleView kivy

anyone can help me about how to add KivyMD Expansion Panel in RecycleView kivy? Because I have issue with slow perfomance while add MDExpansionPanel with "add_widget" on kivy (run in old android).
Then i have idea to put Expansion into RecycleView, but the expansionpanel can't open with true index.
fyi, i have make custom expansion.py file
expansion.py
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.properties import StringProperty, ObjectProperty, NumericProperty
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.button import MDIconButton
from kivymd.uix.list import (IRightBody, ILeftBody, TwoLineAvatarIconListItem)
from kivymd.uix.selectioncontrol import MDCheckbox
Builder.load_string(
"""
#:import images_path kivymd.images_path
#:import md_icons kivymd.icon_definitions.md_icons
<CustomExpansionPanel>
text: root.title
secondary_text: root.desc
_no_ripple_effect: True
IconRightSampleWidget:
id: check
disabled_color: [.2, .3, .6, .9]
disabled: True
ChevronRight:
id: chevron
icon: 'chevron-right'
disabled: True
canvas.before:
PushMatrix
Rotate:
angle: self.angle
axis: (0, 0, 1)
origin: self.center
canvas.after:
PopMatrix
<CustomMDExpansionPanel>
size_hint_y: None
height: dp(68)
padding:dp(0)
BoxLayout:
id: box_item
size_hint_y: None
height: root.height
orientation: 'vertical'
CustomExpansionPanel:
id: item_anim
title: root.title
desc: root.desc
on_press: root.check_open_box(self)
"""
)
class IconRightSampleWidget(ILeftBody, MDCheckbox):
pass
class ChevronRight(IRightBody, MDIconButton):
angle = NumericProperty(0)
class CustomExpansionPanel(TwoLineAvatarIconListItem):
title = StringProperty()
desc = StringProperty()
class CustomMDExpansionPanel(BoxLayout):
content = ObjectProperty()
title = StringProperty()
desc = StringProperty()
def __init__(self, **kwargs):
super(CustomMDExpansionPanel, self).__init__(**kwargs)
self.register_event_type("on_open")
self.register_event_type("on_close")
def on_open(self, *args):
pass
def on_close(self, *args):
pass
def check_open_box(self, instance,CloseAll=False):
press_current_item = False
for box in self.parent.children:
if isinstance(box, CustomMDExpansionPanel):
if len(box.ids.box_item.children) == 2:
if instance is box.ids.item_anim:
press_current_item = True
box.ids.box_item.remove_widget(box.ids.box_item.children[0])
chevron = box.ids.box_item.children[0].ids.chevron
self.anim_chevron_up(chevron)
self.anim_resize_close(box)
self.dispatch("on_close")
break
if not press_current_item and not CloseAll:
self.anim_chevron_down()
def anim_chevron_down(self):
chevron = self.ids.item_anim.ids.chevron
angle = -90
Animation(angle=angle, d=0.2).start(chevron)
self.anim_resize_open_item()
self.dispatch("on_open")
def anim_chevron_up(self, instance):
angle = 0
Animation(angle=angle, d=0.2).start(instance)
def anim_resize_close(self, box):
Animation(height=dp(68), d=0.1, t="in_cubic").start(box)
def anim_resize_open_item(self, *args):
self.content.name_item = self.title
anim = Animation(
height=self.content.height + dp(70), d=0.2, t="in_cubic"
)
anim.bind(on_complete=self.add_content)
anim.start(self)
def add_content(self, *args):
if self.content and len(self.ids.box_item.children) == 1:
self.ids.box_item.add_widget(self.content)
main.py
from kivymd.app import MDApp as App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from expansion import CustomMDExpansionPanel
from time import time
from kivy.uix.boxlayout import BoxLayout
Builder.load_string(
"""
<ListScreen>:
recycle_view: recycle_view
RecycleView:
id: recycle_view
size_hint: 1, 0.9
viewclass: "CustomMDExpansionPanel"
RecycleGridLayout:
id: items_box
cols:1
default_size_hint: 1, None
size_hint: 1, None
height:self.minimum_height
"""
)
class Container(BoxLayout):
def __init__(self,**kwargs):
super(Container,self).__init__()
class ListScreen(Screen):
recycle_view = ObjectProperty(None)
items_box = ObjectProperty(None)
def on_enter(self):
start = time()
container = []
for i in range(0,50):
container.append(Container(item='strrr'+str(i), index=i))
self.recycle_view.data.append(
{
'content':container[i],
'title':'title'+str(i),
'desc':'desc'+str(i)
}
)
def on_leave(self):
self.recycle_view.data = []
class ListApp(App):
sm = ScreenManager()
screens = {}
def build(self):
self.__create_screens()
ListApp.sm.add_widget(ListApp.screens['list1'])
return ListApp.sm
def __create_screens(self):
ListApp.screens['list1'] = ListScreen(name='list1')
if __name__ == '__main__':
ListApp().run()
Thank You
From my understanding , if you are trying to add your expansion panel inside the RecycleView.
Here is an example code of how to do that
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelThreeLine
from kivymd import images_path
KV = """
<Content>
adaptive_height: True
TwoLineIconListItem:
text: "(050)-123-45-67"
secondary_text: "Mobile"
RecycleView:
MDGridLayout:
id: box
cols: 1
adaptive_height: True
"""
class Content(MDBoxLayout):
"""Custom content."""
class Test(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
for i in range(10):
self.root.ids.box.add_widget(
MDExpansionPanel(
icon=f"{images_path}kivymd.png",
content=Content(),
panel_cls=MDExpansionPanelThreeLine(
text="Text",
secondary_text="Secondary text",
tertiary_text="Tertiary text",
),
)
)
Test().run()
Please Refer Documentations Before Asking Questions :) As It Solves 90 % Of Your Problems <3
Also Edit Your Question And Specify Your Problem Clearly :)

Recycleview AttributeError: 'super' object has no attribute '__getattr__'

please check why the below program is giving an
AttributeError: 'super' object has no attribute '__getattr__'
.py:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ListProperty, NumericProperty, ObjectProperty
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.textinput import TextInput
# from kivy.effects.scroll.ScrollEffect import ScrollEffect
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.gridlayout import GridLayout
from kivy.uix.recycleboxlayout import RecycleBoxLayout
Builder.load_file('so_extractTIC.kv')
class RecycleItem(ScreenManager,RecycleDataViewBehavior, TextInput):
index = NumericProperty(0)
def refresh_view_attrs(self, rv, index, data):
self.index = index
return super(RecycleItem, self).refresh_view_attrs(rv, index, data)
class DataView(Screen):
DataList = ListProperty()
TextInputNum = NumericProperty(10)
def __init__(self,*args,**kwargs):
super(DataView, self).__init__(*args,**kwargs)
# for key, val in self.ids.items():
# print("key={0}, val={1}".format(key, val))
data12= []
for x in range(self.TextInputNum):
data12.append({'text': '', 'height': 50})
self.ids.rv.data = data12
def extract_data(self,rv):
print(self.parent.parent.parent)
self.DataList.clear()
for x in range(self.TextInputNum):
self.DataList.append(self.ids.rv.data[x]['text'])
print(self.DataList)
class RootWidget(ScreenManager):
pass
class MainApp(App):
def build(self):
# self.root = Builder.load_string(APP_KV)
return RootWidget()
if __name__ == '__main__':
MainApp().run()
.kv:
<DataView>:
BoxLayout:
orientation: 'vertical'
RecycleView:
size_hint_y: 0.9
viewclass: 'RecycleItem'
id: rv
key_size: 'size'
# effect_cls: ScrollEffect
cols: 1
RecycleBoxLayout:
id: rvbox
cols: rv.cols
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
default_size_hint: 1, None
Button:
text: 'Submit'
size_hint_y: 0.1
on_release: root.extract_data()
<RecycleItem>:
on_text: self.parent.parent.data[self.index]['text'] = self.text
<RootWidget>:
DataView:
name:"DataView_screen"
I have been searching for extract data from recycleview using textInput boxes. Please find the link for the query:
Retrieve Data from Kivy Recycleview
I am trying to inherit from ScreenManager, but it is giving the 'super' attribute error. Tried passing id as argument in the .kv and tried to find real parent but nothing works.
Also, please suggest how to use the above code for recycle GridLaout, with 2d rows and columns, i tried using for loops, but getting key related errors.
like:
for z in range(12):
for y in range(8):
self.table_data12.append(self.ids.idname.data[y][z]['text'])
thanks!
In your DataView class, the __init__() method references self.ids, but the ids are not yet available at that point. You can delay that referencing by using Clock.schedule_once() like this:
def __init__(self, *args, **kwargs):
super(DataView, self).__init__(*args, **kwargs)
# for key, val in self.ids.items():
# print("key={0}, val={1}".format(key, val))
Clock.schedule_once(self.setup_data)
def setup_data(self, dt):
data12 = []
for x in range(self.TextInputNum):
data12.append({'text': '', 'height': 50})
self.ids.rv.data = data12
I see no reason for making the RecycleItem a subclass of ScreenManager.
In your 'kv, the on_textline forRecycleItem` can be:
<RecycleItem>:
on_text: app.root.get_screen('DataView_screen').ids.rv.data[self.index]['text'] = self.text
And the submit Button can be:
Button:
text: 'Submit'
size_hint_y: 0.1
on_release: root.extract_data(rv)

Close kivy popup from another class

I am writing a simple Vocabulary App and when the user submits an answer, a popup should display if he has answered correct or not. This works so far, but when the popup should be dismissed/closed the app crashes telling that AttributeError: 'MyScreenManager' object has no attribute 'close_pop'
which does makes sense, because the close_pop method is defined in the PopupWindow class (I'd like to separate the different concerns if possible)
I though of two possible solutions, but don't know how to realize them:
1: Call the close_pop method from within the MyScreenManager class, but I don't know how to reference the popup object that should be closed
2: Adjust the kv part:
<PopupWindow>:
pLabel: pLabel
Label:
id: pLabel
size_hint: .6, .2
pos_hint:{'x': .2, 'top': 1}
font_name: 'static/NotoSansSC-Regular.otf'
Button:
text: 'Close'
size_hint: .8, .2
pos_hint:{'x': .1, 'y': .1}
on_release: app.root.close_pop()
to not call the root class (MyScreenManager), but instead do something like app.PopupWindow.close_pop(), but this doesn't work either.
I was able to get it working without screenmanager (and putting all methods into one class 'Mainwindow' which also was the root class then) but for further enhancements I'd like to use screen manager :)
Any other fine solution will also work - thanks a lot!
Here is my Python Code:
import random
import pandas as pd
import unidecode
from kivy.app import App
#from kivy.uix.gridlayout import GridLayout
#from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
#from kivy.uix.actionbar import ActionBar
#from kivy.uix.label import Label
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
userInput = ObjectProperty(None)
vocab = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
self.df = pd.read_excel(r"static/HSK1-Vocabulary-List.xlsx")
self.en = self.df['English']
self.zh = self.df['Chinese']
self.pinyin = self.df['Pinyin']
self.rd = None
def btn_submit(self):
if self.rd is None:
pLabel = "Please start before submitting!"
elif not self.userInput.text:
pLabel = "Please enter something!"
else:
pLabel = self.validate(self.userInput.text)
self.btn_next()
PopupWindow(pLabel).open_popup()
def btn_next(self):
self.userInput.text = ""
self.rd = random.randint(0, self.df.shape[0]-1)
self.vocab.text = "What is '{}' in Chinese?".format(self.en[self.rd])
def validate(self, answer):
def replace_tones(orig_voc):
unaccented_voc = unidecode.unidecode(orig_voc)
return(unaccented_voc)
if answer == self.zh[self.rd]:
#correct+=1
return("Well done, even in chinese characters!")
elif answer == self.pinyin[self.rd]:
#correct+=1
return("Well done, you also got the correct tones!")
elif answer == replace_tones(self.pinyin[self.rd]):
#correct+=1
return("Well done! Keep in mind the tones '{}'".format(self.pinyin[self.rd]))
else:
return("Sorry, that was not correct!\nThe correct vocab is {}".format(self.pinyin[self.rd]))
#cnt+=1
class PopupWindow(FloatLayout):
def __init__(self, userInput):
super().__init__()
self.pLabel.text = userInput
def open_popup(self):
content = PopupWindow(self.pLabel.text)
self.pop = Popup(title="Result", content=content, size_hint=(None, None), size=(400, 400))
self.pop.open()
def close_pop(self):
self.pop.dismiss()
class DashboardWindow(Screen):
pass
class MyScreenManager(ScreenManager):
pass
#def close_pop(self):
# print("This should close the popup...")
KV = Builder.load_file("main.kv")
class VocabularyTrainer(App):
def build(self):
return KV
if __name__ == "__main__":
app = VocabularyTrainer()
app.run()
and here my .kv file:
MyScreenManager:
MainWindow:
DashboardWindow:
<MainWindow>:
name: 'main'
vocab: vocab
userInput: userInput
GridLayout:
size: root.width, root.height
rows: 4
ActionBar:
id: actBar
background_image: ''
background_color: (0.53, 0.808, 0.98, 1)
ActionView:
ActionPrevious:
ActionButton:
text: 'Quiz'
ActionButton:
text: 'Training'
ActionButton:
text: 'Settings'
Label:
id: vocab
text: 'Welcome to the Chinese Learning App!'
TextInput:
id: userInput
hint_text: 'Enter answer'
width: 300
multiline: False
on_text_validate: root.btn_submit()
font_name: 'static/NotoSansSC-Regular.otf'
GridLayout:
cols: 3
Button:
text: 'Submit'
on_press: root.btn_submit()
Button:
text: 'Start/Skip'
on_press: root.btn_next()
Button:
text: 'Dashboard'
on_press: app.root.current = 'dashboard'
<PopupWindow>:
pLabel: pLabel
Label:
id: pLabel
size_hint: .6, .2
pos_hint:{'x': .2, 'top': 1}
font_name: 'static/NotoSansSC-Regular.otf'
Button:
text: 'Close'
size_hint: .8, .2
pos_hint:{'x': .1, 'y': .1}
on_release: app.root.close_pop()
<DashboardWindow>:
name: 'dashboard'
GridLayout:
rows: 2
Label:
text: '<e.g. PieChart Results>'
Button:
text: 'Go back'
on_press: app.root.current = 'main'
The problem is that your PopupWindow is creating two PopupWindows each time you use it. A better approach would be to just create one, like this:
class PopupWindow(FloatLayout):
def __init__(self, userInput):
super().__init__()
self.pLabel.text = userInput
self.pop = Popup(title="Result", content=self, size_hint=(None, None), size=(400, 400))
def open_popup(self):
self.pop.open()
def close_pop(self):
self.pop.dismiss()
Then in your kv you can use:
<PopupWindow>:
pLabel: pLabel
Label:
id: pLabel
size_hint: .6, .2
pos_hint:{'x': .2, 'top': 1}
font_name: 'static/NotoSansSC-Regular.otf'
Button:
text: 'Close'
size_hint: .8, .2
pos_hint:{'x': .1, 'y': .1}
on_release: root.close_pop()
You should break it down to a simple example of your problem. From what I have seen so far you should try to change your btn_submit method to something like this to make the popup accessible easily:
def btn_submit(self):
if self.rd is None:
pLabel = "Please start before submitting!"
elif not self.userInput.text:
pLabel = "Please enter something!"
else:
pLabel = self.validate(self.userInput.text)
self.btn_next()
self.mypopup = PopupWindow(pLabel)
self.mypopup.open_popup()
and then you should be able to access it with your screenmanager like this:
class MyScreenManager(ScreenManager):
def close_pop(self):
print("This should close the popup...")
self.get_screen('main').mypopup.close_pop()

Kivy Text Input. Setting text with Clock.schedule_once()

I though that it will be fairly simple to show set some text to TextInput and show it on the screen but it seems I was wrong. In the below code I need to set text Lorem ipsum... to the text input and switch the tabs. I can see the text only when I uncomment Clock.schedule_interval(self.set_text, 1). I would use Clock.schedule_once or any other way than just constantly calling set_text() method.
'''
Test of the widget TabbedPanel.
'''
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader
from kivy.factory import Factory
theRoot = """
#:import Factory kivy.factory.Factory
<EditButton>
orientation: 'vertical'
Button:
text: 'Switch to Edit Screen'
on_press: root.change_tab()
<EditInput>
orientation: 'vertical'
TextInput:
id: text_input
<UnCloseableHeader>
color: 0,0,0,1
disabled_color: self.color
# variable tab_width
text: 'tabx'
size_hint_x: None
width: self.texture_size[0] + 40
BoxLayout:
pos: root.pos
size_hint: None, None
size_y: 20
padding: 3
Label:
id: lbl
text: root.text
<MainTabbedPanel>:
size_hint: (1, 1)
do_default_tab: False
#default_tab: edit_button_tab
tab_width: 130
FloatLayout:
EditButton:
id: edit_button
EditInput:
id: edit_input
UnCloseableHeader:
id: edit_button_tab
text: 'Edit'
content: edit_button.__self__
UnCloseableHeader:
id: edit_input_tab
text: 'Edit Tab'
content: edit_input.__self__
MainTabbedPanel:
"""
class EditInput(BoxLayout):
notes = ''
def __init__(self, **kwargs):
super(EditInput, self).__init__(**kwargs)
print('NOTES', self.notes)
#Clock.schedule_interval(self.set_text, 1)
Clock.schedule_once(self.set_text, -1)
def set_text(self, dt):
print('SET TEXT', self.notes)
self.ids.text_input.text = self.notes
class EditButton(BoxLayout):
def __init__(self, **kwargs):
super(EditButton, self).__init__(**kwargs)
def change_tab(self):
EditInput.notes = 'Lorem ipsum...'
EditInput()
mtp = App.get_running_app().root
mtp.switch_to(mtp.ids.edit_input_tab)
class MainTabbedPanel(TabbedPanel):
tab = ''
def __init__(self, **kwargs):
super(MainTabbedPanel, self).__init__(**kwargs)
self.tabs_showing = True
class UnCloseableHeader(TabbedPanelHeader):
pass
Factory.register('UnCloseableHeader', cls=UnCloseableHeader)
sm = Builder.load_string(theRoot)
class TabbedPanelApp(App):
def build(self):
return sm
if __name__ == '__main__':
TabbedPanelApp().run()
EDIT
I've tried with:
SNIPPET
def change_tab(self):
EditInput.notes = 'Lorem ipsum...'
EditInput()
and:
Clock.schedule_once(self.set_text, 1)
It works in about 50% of cases witch is pretty hard to understand
You can take advantage of Property binding that kv sets up for you. Change your EditInput class to simply:
class EditInput(BoxLayout):
notes = StringProperty('')
no need for any of the methods. Then, in your kv, change the EditInput rule to:
<EditInput>
orientation: 'vertical'
TextInput:
id: text_input
text: root.notes
and change the change_tab method of EditButton to:
def change_tab(self):
mtp = App.get_running_app().root
mtp.ids.edit_input.notes = 'Lorem ipsum...'
mtp.switch_to(mtp.ids.edit_input_tab)
Note that changing the notes property of the EditInput instance will automatically change the TextInput (due to the property binding set up by kv).
Also, the line in change_tab():
EditInput()
is creating a new instance of the EditInput class that is unused and will be garbage collected.

kivy select folder with FileChooser

i want to add kivy filechooser into gridlayout https://kivy.org/docs/api-kivy.uix.filechooser.html
i apply documentation and use root widget for have list file, but it's not work, my all folders not appear to my window
i have my main class :
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
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):
pass
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class MyApp(App):
def build(self):
layout = BoxLayout(orientation='vertical')
root=Root()
root.show_load()
layout.add_widget(root)
return layout
if __name__ == '__main__':
MyApp().run()
i have only filechooser title, i have not folder or file in window why ?
the result :
You need to create a kv file, my.kv and some minor changes to the Python code. Please refer to the example for details.
Example
Python Script - main.py
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
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 MyApp(App):
def build(self):
return Root()
if __name__ == '__main__':
MyApp().run()
kv file - my.kv
#:kivy 1.11.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)
Output

Resources