Good evening. I'm learning kivy and trying to make something like "microsoft to do". But I have a problem. Now I'm doing an adding task function. The main idea of it:
When I click "add task"(button with plus icon) button, my screen changes on "AddingNewTaskScreen".
In AddingNewTaskScreen class I created a function ""addTask that takes text from TextInput and add it in text file. Then it changes this screen on "MainMenuScreen"
In MainMenuScreen class(it is first screen), in constructor i call a "taskRead" function that takes text from text file and write it in array. Then it adds elements of arrays in MDList and after it, it adds this MDList to ScrollView.
And it works, but it takes shows me tasks after new programm launch. For example: I add the task and the "MainMenuScreen" doesn't show me anything. But when I restart my programm, everything are in ScrollView. If you have any ideas how it can be fixed, please tell me, I wold really apreciate it. Thank you for advance.
main.py
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivymd.app import MDApp
from kivymd.uix.list import OneLineListItem, MDList
from kivy.properties import ObjectProperty
from kivy.uix.scrollview import ScrollView
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class MainMenuScreen(Screen):
listBox = ObjectProperty()
theme_changer = ObjectProperty()
search_task = ObjectProperty()
all_tasks = ObjectProperty()
important_tasks = ObjectProperty()
create_list = ObjectProperty()
completed_tasks = ObjectProperty()
list_name = ObjectProperty()
sort = ObjectProperty()
rename = ObjectProperty()
add_button = ObjectProperty()
scroll = ScrollView()
list_view = MDList()
def __init__(self, **kw):
super().__init__(**kw)
self.taskRead()
def taskRead(self):
sv = open('tasks.txt', 'r', encoding='utf-8')
arr = sv.read().split('\n')
sv.close()
for i in range(len(arr)):
self.list_view.add_widget(OneLineListItem(text=arr[i], on_press=self.scr))
self.add_widget(MDList())
self.scroll.add_widget(self.list_view)
self.listBox.add_widget(self.scroll)
def scr(self, value):
self.manager.transition = FadeTransition()
self.manager.current = 'goodbye_screen'
class ToDoListApp(MDApp):
def __init__(self, **kw):
super().__init__(**kw)
def build(self):
self.theme_cls.theme_style = "Dark"
Window.size = (1300, 700)
sm = ScreenManager()
sm.add_widget(MainMenuScreen(name='main_menu_screen'))
sm.add_widget(ImportantOrCompletedTaskCheckScreen(name='goodbye_screen'))
sm.add_widget(AddingNewTaskScreen(name='adding_newTask_screen'))
return sm
class AddingNewTaskScreen(Screen):
taskToTxt = ObjectProperty()
addTaskButton = ObjectProperty()
def __init__(self, **kw):
super().__init__(**kw)
def addTask(self):
task_text = str(self.taskToTxt.text)
sv = open('tasks.txt', 'a', encoding='utf-8')
sv.writelines(str(task_text) + '\n')
sv.close()
ToDoListApp.get_running_app().root.current = "main_menu_screen"
# Class for another problem
class ImportantOrCompletedTaskCheckScreen(Screen):
pass
if __name__ == '__main__':
ToDoListApp().run()
todolist.kv
<MainMenuScreen#Screen>:
listBox:listBox
rename:rename
search_task:search_task
theme_changer:theme_changer
all_tasks:all_tasks
important_tasks:important_tasks
create_list:create_list
completed_tasks:completed_tasks
list_name:list_name
sort:sort
#add_button:add_button
orientation: 'vertical'
# right lateral panel
BoxLayout:
BoxLayout:
size_hint: '0.3', '0.8'
pos_hint: {'y': 0.17}
orientation: 'vertical'
GridLayout:
cols: 1
rows: 9
MDRoundFlatButton:
id: theme_changer
size_hint: 0.5, 0.3
text: 'Light theme'
line_color: 1,1,1,1
elevation_normal: 0
on_press: root.change_theme()
BoxLayout:
size_hint: 1, 0.5
MDRoundFlatButton:
size_hint: 1, 0.7
text: 'All tasks'
line_color: 1,1,1,1
id: all_tasks
BoxLayout:
size_hint: 1, 0.08
MDRoundFlatButton:
size_hint: 1, 0.7
text: 'Important'
line_color: 1,1,1,1
id: important_tasks
BoxLayout:
size_hint: 1, 0.08
MDRoundFlatButton:
size_hint: 1, 0.7
text: '+ Create \nlist'
line_color: 1,1,1,1
id: create_list
BoxLayout:
size_hint: 1, 0.08
MDRoundFlatButton:
size_hint: 1, 0.7
text: 'Completed \ntasks'
line_color: 1,1,1,1
id: completed_tasks
# top panel
BoxLayout:
orientation: 'vertical'
AnchorLayout:
anchor_y: 'top'
size_hint: 1, 0.05
GridLayout:
size_hint: 1, 0.05
cols: 4
rows: 1
Label:
text: 'Name'
size_hint: 0.5, 0.05
id: list_name
MDTextField:
id:search_task
halign: 'center'
valign: 'center'
hint_text: 'Search'
size_hint: 1, None
line_color_normal: 0.15,0.15,0.15
MDRectangleFlatButton:
id: rename
text: 'Rename'
line_color: 1,1,1,1
MDRectangleFlatButton:
text: 'Sort'
line_color: 1,1,1,1
id: sort
# Center
BoxLayout:
orientation: 'vertical'
size_hint: 0.1, 0.1
MDFloatingActionButton:
icon: "plus"
md_bg_color: 'black'
on_press: root.manager.current = 'adding_newTask_screen'
BoxLayout:
orientation: 'vertical'
size_hint: 1,1
BoxLayout:
ScrollView:
line_color_normal: 1,1,0,1
id: listBox
# Screen for another problem
<ImportantOrCompletedTaskCheckScreen#Screen>:
name: 'goodbye_screen'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
orientation: 'vertical'
size_hint: 0.5, 0.25
GridLayout:
cols: 2
rows: 1
size_hint: 0.3, 0.25
pos_hint: {'x': 0.35}
MDSwitch:
size_hint: 0.3, 0.3
theme_text_color: "Custom"
text_color: 1, 1, 1, 1
line_color: 1, 1, 1, 1
Label:
text: 'Important'
BoxLayout:
size_hint: 0, 0.5
GridLayout:
cols: 2
rows: 1
size_hint: 0.3, 0.25
pos_hint: {'x': 0.35}
MDSwitch:
text: 'Important'
size_hint: 0.3, 0.3
theme_text_color: "Custom"
text_color: 1, 1, 1, 1
line_color: 1, 1, 1, 1
Label:
text: 'Completed'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
MDRoundFlatButton:
text: 'Continue'
size_hint: 1, 0.5
theme_text_color: "Custom"
text_color: 1, 1, 1, 1
line_color: 1, 1, 1, 1
on_press: root.manager.current='main_menu_screen'
<AddingNewTaskScreen#Screen>:
taskToTxt:taskToTxt
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
orientation: 'vertical'
size_hint: 0.5, 0.25
MDTextField:
id: taskToTxt
hint_text: 'Name of new task'
color: 'white'
halign: 'center'
valign: 'center'
size_hint: 1, None
multiline: False
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
MDRoundFlatButton:
text: 'Add task'
id: addTaskButton
on_press: root.addTask()
size_hint: 1, 0.5
theme_text_color: "Custom"
text_color: 1, 1, 1, 1
line_color: 1, 1, 1, 1
In addTask you should get access to main screen
main_screen = ToDoListApp.get_running_app().root.get_screen('main_menu_screen')
and then you can add task to list
main_screen.list_view.add_widget(OneLineListItem(text=task_text, on_press=main_screen.scr))
def addTask(self):
task_text = str(self.taskToTxt.text)
sv = open('tasks.txt', 'a', encoding='utf-8')
sv.writelines(str(task_text) + '\n')
sv.close()
main_screen = ToDoListApp.get_running_app().root.get_screen('main_menu_screen')
main_screen.list_view.add_widget(OneLineListItem(text=task_text, on_press=main_screen.scr))
ToDoListApp.get_running_app().root.current = "main_menu_screen"
BTW:
ScreenManager is a parent for every Screen so you could write shorter with self.parent.
Or you could use self.manager
main_screen = self.parent.get_screen('main_menu_screen')
#main_screen = self.manager.get_screen('main_menu_screen')
# ... code ...
self.parent.current = "main_menu_screen"
#self.manager.current = "main_menu_screen"
In MainMenuScreen you could also create function to add single task
class MainMenuScreen(Screen):
def add_task(self, text):
self.list_view.add_widget(OneLineListItem(text=text, on_press=self.scr))
and then you could write it simpler in addTask
main_screen = self.parent.get_screen('main_menu_screen')
main_screen.add_task(task_text)
and in taskRead you could reduce for-loop
for text in arr:
self.add_task(text)
Related
I have an App with 3 screens managed by a ScreenManager: MainScreen, ScanScreen, PinScreen. From MainScreen I have 2 buttons, 1 to go to ScanScreen, 1 to go to PinScreen. In ScanScreen I have a button to go into PinScreen and in PinScreen I have a button to go in ScanScreen. I want to go to MainScreen after some interval of time. I managed to make it works only if I go to secondary screens from MainScreen. If I go from MainScreen to ScanScreen and from ScanScreen to PinScreen then it wont work. I get this error:
line 16, in timeout
self.parent.current = 'mainScreen'
AttributeError: 'NoneType' object has no attribute 'current'
This is what I got so far:
kv file
ScreenManagement:
id:'screenManager'
MainScreen:
ScanScreen:
PinScreen:
FinalScreen:
<MainScreen>:
name: "mainScreen"
MDCard:
radius: [36, ]
size_hint: .8, .9
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
padding: [20, 50, 20, 150]
spacing: 50
orientation: 'vertical'
MDIcon:
icon: "face-recognition"
font_size: 120
halign: 'center'
size_hint: 1, .5
MDFillRoundFlatButton:
text: "Scan Face"
font_size: 32
pos_hint: {"center_x": 0.5}
#size_hint: 1, .25
on_release:
root.manager.current = 'scanScreen'
root.manager.transition.direction = 'left'
MDFillRoundFlatButton:
text: "Access with PIN"
font_size: 32
pos_hint: {"center_x": 0.5}
#size_hint: 1, .25
on_release:
root.manager.current = 'pinScreen'
root.manager.transition.direction = 'left'
<ScanScreen>:
on_pre_enter: app.title = 'Scan Screen'
name: "scanScreen"
#on_enter: TODO timer function
MDCard:
radius: [36, ]
size_hint: .9, .95
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
padding: [20, 50, 20, 150]
spacing: 50
orientation: 'vertical'
Image:
id: "frame_feed"
size_hint: 1, .8
MDFillRoundFlatButton:
text: "Access with PIN"
font_size: 32
pos_hint: {"center_x": 0.5}
on_release:
root.manager.current = 'pinScreen'
root.manager.transition.direction = 'left'
<PinScreen>:
on_pre_enter: app.title = 'PIN Screen'
name: "pinScreen"
MDBoxLayout:
orientation: 'vertical'
MDBoxLayout:
orientation: 'vertical'
size_hint: (1, .5)
MDIconButton:
icon: "arrow-left-drop-circle"
#icon_size: '32sp' this should be the right way but its not working
user_font_size: '32sp' #this should be deprecated but it's working
on_release:
root.manager.current = 'scanScreen'
root.manager.transition.direction = 'right'
MDIcon:
icon: "account-lock"
font_size: 60
halign: 'center'
MDLabel:
text: "Enter your passcode"
halign: "center"
font_style: "Body1"
MDGridLayout:
size_hint: (.5, 1)
pos_hint: {"center_x": .5}
cols: 6
#padding: [80,0,80,0]
#halign: "center"
MDIcon:
icon:"checkbox-blank-circle-outline"
MDIcon:
icon:"checkbox-blank-circle-outline"
MDIcon:
icon:"checkbox-blank-circle-outline"
MDIcon:
icon:"checkbox-blank-circle-outline"
MDIcon:
icon:"checkbox-blank-circle-outline"
MDIcon:
icon:"checkbox-blank-circle-outline"
Widget:
size_hint_y: None
height: 100
MDBoxLayout:
orientation: 'vertical'
size_hint: (1, .5)
MDGridLayout:
size_hint: (.5, 1)
pos_hint: {"center_x": .385}
cols:3
spacing: 20
MDFillRoundFlatButton:
text: "1"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "2"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "3"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "4"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "5"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "6"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "7"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "8"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: "9"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatButton:
text: ""
md_bg_color: 1,0,0,0
MDFillRoundFlatButton:
text: "0"
text_color: .95,.953,.956,1
font_size: 20
font_style: 'H4'
md_bg_color: .4, .4, .4, 1
MDFillRoundFlatIconButton:
icon: "backspace"
padding: [40,0,0,0]
font_style: 'H4'
icon_color: .827,.827,.827,1
md_bg_color: 1,0,0,0
<FinalScreen>:
on_pre_enter: app.title = 'Final Screen'
name: "finalScreen"
python file
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.clock import Clock
Window.size = (414, 736) #This is the viewport of iPhone 6 Plus/6S Plus/7 Plus/8 Plus
import cv2
class MainScreen(Screen):
pass
class ScanScreen(Screen):
def timeout(self, *args):
self.parent.current = 'mainScreen'
def on_enter(self, *args):
Clock.schedule_once(self.timeout, 2)
class PinScreen(Screen):
def timeout(self, *args):
self.parent.current = 'mainScreen'
def on_enter(self, *args):
Clock.schedule_once(self.timeout, 2)
class FinalScreen(Screen):
def timeout(self, *args):
self.parent.current = 'mainScreen'
def on_enter(self, *args):
Clock.schedule_once(self.timeout, 2)
class ScreenManagement(ScreenManager):
pass
class MainApp(MDApp):
def __init__(self, **kwargs):
self.title = "Main Screen"
super().__init__(**kwargs)
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Green"
self.theme_cls.accent_palette = "Teal"
return Builder.load_file('main.kv')
def return_to_main_screen(self):
pass
if __name__ == "__main__":
MainApp().run()
I also tried this:
class ScanScreen(Screen):
def timeout(self, *args):
MDApp.get_running_app().root.manager.current = 'mainScreen'
#self.parent.current = 'mainScreen'
def on_enter(self, *args):
Clock.schedule_once(self.timeout, 2)
but I get this error:
MDApp.get_running_app().root.manager.current = 'mainScreen'
AttributeError: 'ScreenManagement' object has no attribute 'manager'
So to clarify, I managed to do what I wanted by using get_running_app() method and accessing the root, which in my case is the ScreenManager. I made some changes to my code so it would reset the countdown after activity. This is what I have in each of the screen that I want to return to MainScreen after 30s of inactivity:
class ScanScreen(Screen):
def timeout(self, *args):
MDApp.get_running_app().root.current = 'mainScreen'
MDApp.get_running_app().root.transition.direction = 'right'
def reset_timeout(self, *args):
Clock.unschedule(self.timeout)
Clock.schedule_once(self.timeout, 30)
def on_enter(self, *args):
Clock.schedule_once(self.timeout, 30)
def on_leave(self, *args):
Clock.unschedule(self.timeout)
def on_touch_down(self, touch):
self.reset_timeout()
return super().on_touch_down(touch)
def on_touch_move(self, touch):
self.reset_timeout()
return super().on_touch_move(touch)
from kivy.app import App
from kivy.graphics import Line
from kivy.metrics import dp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivymd.app import MDApp
class ScrollViewExample(ScrollView):
pass
class FirstWindow(Screen):
def set_text(self):
my_title_input = self.ids.note_title
my_details = self.ids.note_details
fo = open("notes.txt", "a")
fo.write('\n'+'\n'+my_title_input.text)
fo.write('\n'+my_details.text)
fo.close()
class SecondWindow(Screen):
pass
class ThirdWindow(Screen):
def on_toggle_button_state(self):
dark_mode = self.ids.dark_mode
dark_mode.text = 'Feature not available'
pass
class FourthWindow(Screen):
#This class displays notes from a file in buttons
#works but only the notes showup
def build(self):
root = FourthWindow()
root.add_widget(FourthWindow(name='StackLayout'))
class StackLayoutExample(StackLayout):
class ScrollView(ScrollView):
pass
def __init__(self, **kwargs):
super().__init__(**kwargs)
layout = StackLayout(orientation='lr-tb')
with open('notes.txt', 'r') as fp:
data = fp.read()
splat = data.split("\n\n")
notes = []
for i, note in enumerate(splat, 0):
notes.append(note)
for i in range(0, len(notes)):
b = Button(text=notes[i], size_hint=(.25, .4))
self.add_widget(b)
class WindowManager(ScreenManager):
pass
class RelativeLayoutExample(RelativeLayout):
pass
class ScreeManager(ScreenManager):
pass
class LineMaker(Widget):
pass
class Noteit(App):
pass
Noteit().run()
Noteit.kv <---The kv file begins here
WindowManager:
FirstWindow:
SecondWindow:
ThirdWindow:
FourthWindow:
<FirstWindow>:
id: first_window
name: "Notes"
RelativeLayout:
Label:
text: "Notes"
size_hint: None,None
pos_hint: {'top':1,'center_x':.5}
font_size: 35
Button:
text: 'Account'
size_hint: None,None
pos_hint: {'top':1,'right':1}
on_release:
app.root.current = "Account"
root.manager.transition.direction= "left"
Button:
text: 'Preferences'
size_hint: None,None
pos_hint: {'top':1,'left':1}
on_release:
app.root.current = "Preferences"
root.manager.transition.direction= "right"
Label:
text: "Title:"
size_hint: None,None
pos_hint: {'top':.85,'center_x':.5}
font_size: 20
TextInput:
id: note_title
size_hint: .45,.08
pos_hint: {'top':.75,'center_x':.5}
multiline: False
Label:
text: "Details:"
size_hint: None,None
pos_hint: {'top':.65,'center_x':.5}
font_size: 20
TextInput:
id: note_details
size_hint: .45,.3
pos_hint: {'top':.55,'center_x':.5}
multiline: True
Button:
text: "Submit"
size_hint: .25,.1
length: "100dp"
pos_hint: {'top':.25,'center_x':.5}
on_release:
root.set_text()
LineMaker:
canvas:
Color:
rgba: 1, 1, 1, 1
Line:
width: 2.
points: (self.width,self.height*.83,0,self.height*.83)
Button:
text: 'View All Notes'
size_hint:.25,.15
pos_hint: {'bottom':1,'center_x':.5}
on_release:
app.root.current = "View"
root.manager.transition.direction= "up"
<SecondWindow>:
name: "Account"
RelativeLayout:
Label:
text: "Account"
size_hint: None,None
pos_hint: {'top':1,'center_x':.5}
font_size: 35
Button:
text: 'Notes'
size_hint: None,None
pos_hint: {'top':1,'left':1}
on_release:
app.root.current = "Notes"
root.manager.transition.direction= "right"
Button:
text: 'Preferences'
size_hint: None,None
pos_hint: {'top':1,'right':1}
on_release:
app.root.current = "Preferences"
root.manager.transition.direction= "left"
Label:
text: "Username:"
size_hint: None,None
pos_hint: {'top':.85}
font_size: 20
TextInput:
size_hint: .5,.1
pos_hint: {'top':.55,'left':.3}
multiline: False
Label:
text: "Password:"
size_hint: None,None
pos_hint: {'top':.65}
font_size: 20
TextInput:
size_hint: .5,.1
pos_hint: {'top':.75,'left':.3}
multiline: False
Button:
text: "Log In"
size_hint: .25,.1
length: "100dp"
pos_hint: {'top':.45}
Button:
text: "Sign Up"
size_hint: .25,.1
length: "100dp"
pos_hint: {'top':.45,'center_x':.375}
LineMaker:
canvas:
Color:
rgba: 1, 1, 1, 1
Line:
width: 2.
points: (self.width,self.height*.83,0,self.height*.83)
<ThirdWindow>:
name: "Preferences"
RelativeLayout:
Label:
text: "Preferences"
size_hint: None,None
pos_hint: {'top':1,'center_x':.5}
font_size: 35
Button:
text: 'Notes'
size_hint: None,None
pos_hint: {'top':1,'right':1}
on_release:
app.root.current = "Notes"
root.manager.transition.direction= "left"
Button:
text: 'Account'
size_hint: None,None
pos_hint: {'top':1,'left':1}
on_release:
app.root.current = "Account"
root.manager.transition.direction= "right"
ToggleButton:
text: 'Dark Mode'
size_hint: .25,.1
pos_hint: {'top':.75,'center_x':.25}
on_state: root.on_toggle_button_state()
Label:
id: dark_mode
text: ''
LineMaker:
canvas:
Color:
rgba: 1, 1, 1, 1
Line:
width: 2.
points: (self.width,self.height*.83,0,self.height*.83)
<FourthWindow>:
name: "View"
RelativeLayout:
Button:
text: 'Note Submission'
size_hint:.25,.15
pos_hint: {'top':1,'center_x':.5}
on_release:
app.root.current = "Notes"
root.manager.transition.direction= "down"
Label:
text: 'All Notes'
size_hint: None,None
pos_hint: {'top':1,'right':.9}
font_size: 35
How do I make the stacklayout code showup with the kv file code? Or at least make the stacklayout part of the screen.
Right now the only option I have is either take the screen as output or the stack layout as output.
Replacing the def build(self) inside the class FourthWindow(Screen) will show the whole application. The code inside the def build(self) also works but they do not work together.
I am new to kivy and object oriented programming so I do not know much about this topic so I could be missing something really basic.
I have used KivyMD to develop a Screen which displays the Parameter values (In a DialogBox) of specific Item (which I listed them as OnelinelistItem). I also want to make provision for the user to change the parameter values from the DialogBox. But apparently I cant update the parameter settings from the DialogBox. The DialogBox contains the Textfield. Can anyone help me to figure out the issue, by going through the code, and let me know, where I am doing it wrong?
TIA! :)
testingsetpointpage.py
'''
from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'systemanddock')
from kivy.uix.boxlayout import BoxLayout
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen
from kivymd.uix.dialog import MDDialog
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivymd.uix.button import MDFlatButton
from kivy.properties import StringProperty
Window.size = (1024, 600)
The Builder is shown here:
KV = """
#:kivy 1.11.0
#:import MDDropdownMenu kivymd.uix.menu.MDDropdownMenu
#:import MDRaisedButton kivymd.uix.button.MDRaisedButton
ScreenManager:
MainScreen:
<MainScreen>:
name: 'mainscreen'
NavigationLayout:
ScreenManager:
Screen:
name: 'homemain'
BoxLayout:
orientation:"vertical"
halign:"center"
#DOWN TAB
MDBottomNavigation:
MDBottomNavigationItem:
name: 'setpoint'
text: 'Setpoints'
icon: 'network'
BoxLayout:
orientation: "vertical"
MDToolbar:
title: 'Setpoints'
pos_hint: {'center_x':0.5,'center_y':0.95}
right_action_items: [["wifi", lambda x: app.navigation_draw()]]
left_action_items: [["menu", lambda x: nav_drawer.toggle_nav_drawer()]]
elevation: 10
BoxLayout:
orientation:"vertical"
padding: 5
spacing: 5
MDLabel:
text: " Functions: "
halign:"left"
theme_text_color: "Custom"
text_color: 0, 0, 1, 1
size_hint_y: 0.15
canvas.before:
Color:
rgba: (211/255.0,211/255.0,211/255.0,1)
Rectangle:
size: self.size
pos: self.pos
SetpointContent:
#MAKE THE PARAMETER LIST
<SetpointContent>:
BoxLayout:
orientation: "vertical"
padding: 5
spacing: 5
ScrollView:
MDList:
OneLineListItem:
text: "51P: Phase Time Overcurrent"
on_press: root.show_51Pdata()
<Content51P>
alarmpick51p: alp51p
alarmdelay51p: ald51p
trippick51p: trp51p
invcurve51p: inp51p
orientation: "vertical"
size_hint_y: None
height: "200dp"
GridLayout:
rows: 4
cols: 2
spacing: 10
MDLabel:
text: "Alarm Pickup: "
halign: "center"
theme_text_color: "Custom"
text_color: 0, 0, 1, 1
size_hint_y: 0.15
size_hint_x: 0.4
width:100
MDTextFieldRect:
id: alp51p
text: root.text1
multiline: False
MDLabel:
text: "Alarm Delay: "
halign: "center"
theme_text_color: "Custom"
text_color: 0, 0, 1, 1
size_hint_y: 0.15
size_hint_x: 0.4
width:100
MDTextFieldRect:
id: ald51p
text: str(app.Aldelay51P)
multiline: False
MDLabel:
text: "Trip Pickup: "
halign: "center"
theme_text_color: "Custom"
text_color: 0, 0, 1, 1
size_hint_y: 0.15
size_hint_x: 0.4
width:100
MDTextFieldRect:
id: trp51p
text: str(app.Trpick51P)
multiline: False
MDLabel:
text: "Inverse Curve: "
halign: "center"
theme_text_color: "Custom"
text_color: 0, 0, 1, 1
size_hint_y: 0.15
size_hint_x: 0.4
width:100
MDTextFieldRect:
id: inp51p
text: str(app.InverseCurve)
multiline: False
#####
"""
and the Classes are defined here:
class Content51P(BoxLayout):
app=MDApp.get_running_app()
text1 = StringProperty("1")
alarmpick51p = ObjectProperty()
alarmdelay51p = ObjectProperty()
trippick51p = ObjectProperty()
invcurve51p = ObjectProperty()
class MainScreen(Screen):
class SetpointContent(Screen):
def show_51Pdata(self):
self.dialog = MDDialog(title="51P Parameters:",
type="custom",
content_cls=Content51P(),
buttons=[MDFlatButton(text='Close', on_release=self.close_dialog),
MDFlatButton(text='Update', on_release=self.update51P)]
)
self.dialog.auto_dismiss = False
self.dialog.open()
def update51P(self, obj):
duc = Content51P()
app = MDApp.get_running_app()
duc.text1 = duc.ids.alp51p.text
print(duc.text1)
app.Alpick51P = float(duc.text1)
print(app.Alpick51P)
def close_dialog(self, obj):
self.dialog.auto_dismiss = True
self.dialog.dismiss()
class MainApp(MDApp):
Alpick51P = ObjectProperty("5")
Aldelay51P = ObjectProperty("5")
Trpick51P = ObjectProperty("5")
InverseCurve = ObjectProperty("Very Inverse")
def build(self):
self.theme_cls.primary_palette = "Blue"
screen = Builder.load_string(KV)
return screen
def navigation_draw(self):
print("Navigation")
def on_start(self):
pass
if __name__ == '__main__':
MainApp().run()
'''
The outlook looks something like this. I want to update the four parameters as the user clicks on the Update button and be able to view the value, the next time I open the DialogBx.
In the kv rule, under <Content51P> for MDTextFieldRect textinputs add:
on_text: app.Alpick51P = self.text
on_text: app.Aldelay51P = self.text
on_text: app.Trpick51P = self.text
on_text: app.InverseCurve = self.text
The on_text method should go to respective MDTextFieldRect.
Update the update51P() function should be like below now:
def update51P(self, obj):
app = MDApp.get_running_app()
print(app.Alpick51P)
print(app.Aldelay51P)
print(app.Trpick51P)
print(app.InverseCurve)
This would now print the updated inputs from textinput fields.
I want the last button in the pop up to add a label to the previous screen with the text of whatever in entered into the text input in the pop up but I cant find a way to do so, is it possible?
I want the button with id add to add a label to screen the List every time it is clicked, and the text of said label should be whatever value put into text inputs with the ids lab, club, and blub
And if it is possible, how can I do it, any help would be greatly appreciated.
Python :
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.uix.popup import Popup
import time
from kivy.properties import StringProperty
class Enter_Name(Screen):
input_1 = StringProperty()
def line(self):
App.get_running_app().root.get_screen('list').lab_text = self.airline.text
pass
class Pop(Screen):
air_craft = StringProperty()
def lad(self):
plane = App.get_running_app().root.get_screen('pop').lab_text = self.airplane.text
self.plane = plane
class List(Screen):
Enter_Name.line
def add(self):
show_popup()
def show_popup():
show = Pop()
pop_up_window = Popup(title="Add Route", content=show, size_hint=(None, None), size=(400, 400))
pop_up_window.open()
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("pot.kv")
class am4(App):
def build(self):
return kv
if __name__ == "__main__":
am4().run()
Kivy :
#:kivy 1.0
WindowManager:
Enter_Name
List
Pop
#_______________________________________________________________________________________________________
#LOGIN
#_______________________________________________________________________________________________________
<Enter_Name>
airline: input_1
name: 'enter_name'
id: enter_nom
FloatLayout:
cols: 3
size: root.size
Label:
text: "Name of Airline?"
size_hint: 1, 0.3
pos_hint: {"x": 0, "top":1}
TextInput:
multiline: False
name: 'input_one'
id: input_1
size_hint: 0.6, 0.06
pos_hint: {"x": 0.20, "top":0.6}
Button:
size_hint: 0.2, 0.1
pos_hint: {"x": 0.4, "top":0.4}
text: "Enter"
on_release:
app.root.current = 'list'
root.line()
#_______________________________________________________________________________________________________
#MAIN
#_______________________________________________________________________________________________________
<List>
lab_text: ''
name: 'list'
FloatLayout:
Label:
text: root.lab_text
size_hint: 1, 0.3
pos_hint: {"x": -0.38, "top":1.1}
font_size: 50
Label:
text: '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'
size_hint: 1, 0.3
pos_hint: {"x": -0.38, "top":1}
font_size: 50
Button:
text: "Add Route"
size_hint: 0.2, 0.1
pos_hint: {"x":0.79, "top":0.99}
on_release: root.add()
<Pop>
name: "pop"
airplane: air_craft
FloatLayout:
Label:
id: lab
text: "Aircraft"
pos_hint: {"x": -0.38, "top":1.45}
Label:
id: club
text: "Departure"
pos_hint: {"x": 0, "top":1.45}
Label:
id: blub
text: "Arrival"
pos_hint: {"x": 0.38, "top":1.45}
TextInput:
multiline: False
name: 'aircraft'
id: air_craft
size_hint: 0.23, 0.06
pos_hint: {"x": 0, "top":0.9}
TextInput:
multiline: False
name: 'departure'
id: leaving
size_hint: 0.23, 0.06
pos_hint: {"x": 0.38, "top":0.9}
TextInput:
multiline: False
name: 'arrival'
id: arriving
size_hint: 0.23, 0.06
pos_hint: {"x": 0.76, "top":0.9}
Button:
size_hint: 0.2, 0.1
pos_hint: {"x": 0.4, "top":0.5}
id: add
text: "Add"
on_release:
root.lad()
Here is a modified version of your code that does what I think you want:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import StringProperty
class Enter_Name(Screen):
input_1 = StringProperty()
def line(self):
App.get_running_app().root.get_screen('list').lab_text = self.airline.text
class ListRow(BoxLayout):
ac = StringProperty('')
arr = StringProperty('')
lv = StringProperty('')
class Pop(RelativeLayout):
def lad(self, ac, arr, lv):
list_scr = App.get_running_app().root.get_screen('list')
if ac != '' or arr != '' or lv != '':
box_layout = list_scr.ids.box_layout
box_layout.add_widget(ListRow(ac=ac, arr=arr, lv=lv))
list_scr.pop.dismiss()
class List(Screen):
Enter_Name.line
pop = ObjectProperty(None)
def add(self):
self.pop = show_popup()
def show_popup():
show = Pop()
pop_up_window = Popup(title="Add Route", content=show, size_hint=(None, None), size=(400, 400))
pop_up_window.open()
return pop_up_window
class WindowManager(ScreenManager):
pass
# kv = Builder.load_file("pot.kv")
kv = Builder.load_string('''
#:kivy 1.0
WindowManager:
Enter_Name
List
#_______________________________________________________________________________________________________
#LOGIN
#_______________________________________________________________________________________________________
<Enter_Name>
airline: input_1
name: 'enter_name'
id: enter_nom
FloatLayout:
cols: 3
size: root.size
Label:
text: "Name of Airline?"
size_hint: 1, 0.3
pos_hint: {"x": 0, "top":1}
TextInput:
multiline: False
name: 'input_one'
id: input_1
size_hint: 0.6, 0.06
pos_hint: {"x": 0.20, "top":0.6}
Button:
size_hint: 0.2, 0.1
pos_hint: {"x": 0.4, "top":0.4}
text: "Enter"
on_release:
app.root.current = 'list'
root.line()
#_______________________________________________________________________________________________________
#MAIN
#_______________________________________________________________________________________________________
<List>
lab_text: ''
name: 'list'
BoxLayout:
id: box_layout
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
pos_hint: {'top':1}
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: 50
BoxLayout:
orientation: 'horizontal'
Label:
id: lab1
text: root.lab_text
size_hint_x: 1
#pos_hint: {"x": -0.38, "top":1}
font_size: 50
Button:
text: "Add Route"
size_hint_x: 0.5
#pos_hint: {"x":0.79, "top":1}
on_release: root.add()
Label:
text: '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'
size_hint: 1, 0.3
#pos_hint: {"x": -0.38, "top":0.99}
font_size: 50
<ListRow>:
orientation: 'horizontal'
size_hint: (1, None)
height: self.minimum_height
Label:
text: 'Aircraft: ' + root.ac
halign: 'left'
size_hint: 1, None
height: self.texture_size[1]
Label:
text: 'Leave: ' + root.lv
halign: 'left'
size_hint: 1, None
height: self.texture_size[1]
Label:
text: 'Arrive: ' + root.arr
halign: 'left'
size_hint: 1, None
height: self.texture_size[1]
<Pop>
airplane: air_craft
FloatLayout:
Label:
id: lab
text: "Aircraft"
pos_hint: {"x": -0.38, "top":1.45}
Label:
id: club
text: "Departure"
pos_hint: {"x": 0, "top":1.45}
Label:
id: blub
text: "Arrival"
pos_hint: {"x": 0.38, "top":1.45}
TextInput:
multiline: False
name: 'aircraft'
id: air_craft
size_hint: 0.23, 0.06
pos_hint: {"x": 0, "top":0.9}
TextInput:
multiline: False
name: 'departure'
id: leaving
size_hint: 0.23, 0.06
pos_hint: {"x": 0.38, "top":0.9}
TextInput:
multiline: False
name: 'arrival'
id: arriving
size_hint: 0.23, 0.06
pos_hint: {"x": 0.76, "top":0.9}
Button:
size_hint: 0.2, 0.1
pos_hint: {"x": 0.4, "top":0.5}
id: add
text: "Add"
on_release:
root.lad(air_craft.text, arriving.text, leaving.text)
''')
class am4(App):
def build(self):
return kv
if __name__ == "__main__":
am4().run()
Some of the significant changes that I made:
Redefined the Pop class as extending RelativeLayout instead of Screen and removed Pop from the children of WindowManager.
Defined a ListRow class that is added to the List Screen when the lad() method is called.
Added arguments to the lad() method for information to be added, and added a dismiss() call to close the Popup.
The show_pop() method now returns the created Popup instance which is saved in the List Screen for use of dismiss().
Redesigned the List Screen using a vertical BoxLayout to make adding ListRows simpler.
The kv is loaded using Builder.load_string() in the above code, but that is only for my own convenience.
I've some problems with multiple MDLabels in BoxLayout (that is contains by AnchorLayout), so all the MDLabel objects are stacked in one place on the screen!
I dont know how to make them centered and grouped like a list (with spacing and e.g.)
Please, help me with solving that problem!
Thanks a lot and sorry for bad english.
There is my main.py
from kivy.app import App
from kivymd.theming import ThemeManager
from kivymd.label import MDLabel
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.metrics import dp, sp, pt
def toast(text):
from kivymd.toast.kivytoast import toast
toast(text)
class MyScreen(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.menu_items = [
{
"viewclass": "MDMenuItem",
"text": "text%d" % i,
"callback": self.callback,
}
for i in range(1, 3)
]
self.menu_button = None
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
def callback(self, *args):
toast(args[0])
class MainApp(App):
title = "KivyMD MDDropdownMenu Demo"
theme_cls = ThemeManager()
def build(self):
return MyScreen()
if __name__ == "__main__":
MainApp().run()
And there is my main.kv file contains:
#:import MDDropdownMenu kivymd.menus.MDDropdownMenu
#:import MDRaisedButton kivymd.button.MDRaisedButton
#:import MDLabel kivymd.label.MDLabel
<MDMenuItem>:
on_release:
app.root.change_variable(self.text)
app.root.menu_button.text = self.text
<MyScreen>:
name: 'myscrn'
AnchorLayout:
anchor_y: 'center'
BoxLayout:
orientation: 'vertical'
size_hint: 0.1, 0.5
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
spacing: dp(10)
MDRaisedButton:
id: mainbutton
size_hint: None, None
size: 3 * dp(48), dp(48)
text: 'MDButton1'
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
opposite_colors: True
on_release:
root.menu_button = mainbutton
MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
MDRaisedButton:
id: secondbutton
size_hint: None, None
size: 3 * dp(48), dp(48)
text: 'MDButton2'
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
opposite_colors: True
on_release:
root.menu_button = secondbutton
MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
AnchorLayout:
anchor_y: 'top'
BoxLayout:
orientation: 'vertical'
size_hint: 0.95, 0.5
padding: [0, 0, 0, 0]
spacing: dp(5)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MDLabel:
font_size: dp(12)
text: '123'
MDLabel:
font_size: dp(22)
text: '456'
Woops, looks like a simple mistake. Your indentation on KV Lang is incorrect. You didn't nest your labels into BoxLayout correctly.
AnchorLayout:
anchor_y: 'top'
BoxLayout:
orientation: 'vertical'
size_hint: 0.95, 0.5
padding: [0, 0, 0, 0]
spacing: dp(5)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MDLabel:
font_size: dp(12)
text: '123'
MDLabel:
font_size: dp(22)
text: '456'"""