Kivy button does not dismiss a popup when it should - python

I have made a button that when released opens a popup in kivy, which contains a Float Layout. I want the layout to contain a filechooser, so the user can select a folder to save something, and a button that saves this choice and closes the popup at the same time.
I am currently trying to figure out how to make the button close the popup at first. I came up with this code and I really have no idea why it doesn't close the popup, but it doesn't. I don't get any error at all, just nothing happens. The code is this in kvlang:
#:import Factory kivy.factory.Factory
<BoxLayout3>:
Label:
text: "Audio:"
halign: 'center'
font_size:'20sp'
CheckBox:
<BoxLayout4>:
Label:
text: "Video:"
halign: 'center'
font_size:'20sp'
CheckBox:
<FileWidget>:
FileChooserIconView:
id: filechooser
Button:
id:my_button
text: 'Save'
size_hint: (0.1, 0.1)
pos_hint:{'x': 0, 'y': 0}
on_release:Factory.MyPopup().dismiss()
<MyPopup>:
id:pop
auto_dismiss: False
title: "Select a folder"
FileWidget:
<FloatLayout1>:
Button:
text: 'Folder'
on_release: Factory.MyPopup().open()
size_hint: None, None
size: 130, 50
pos_hint: {'x':0.2,'y':.4}
<FloatLayout2>:
Spinner:
id: spinner_id
text: "Quality"
values: ['144p', '240p', '360p', '480p', '720p', '1080p', '1440p', '2160p']
on_text: root.spinner_clicked(spinner_id.text)
size_hint: None, None
size: 130, 50
pos_hint: {'x': .2, 'y':.4}
<BoxLayout2>:
cols:4
BoxLayout3:
BoxLayout4:
FloatLayout2:
FloatLayout1:
BoxLayout1:
<BoxLayout1>:
orientation:'vertical'
cols: 3
Label:
text: "YouTube Downloader"
halign: 'center'
bold: True
font_size:'50sp'
TextInput:
size_hint: (.5, .2)
multiline: False
hint_text: 'Enter the link of the Youtube video you want to download.'
pos_hint: {"x": 0.25}
BoxLayout2:
Button:
text: "Submit"
size_hint: (.5, .2)
pos_hint: {"x": 0.25}
My python code is(it isn't finished yet):
class MyPopup(Popup):
pass
class FloatLayout1(FloatLayout):
pass
class FileWidget(FloatLayout):
pass
class FloatLayout2(FloatLayout):
def spinner_clicked(self, value):
pass
class StackLayout(StackLayout):
pass
class BoxLayout1(BoxLayout):
pass
class BoxLayout2(BoxLayout):
pass
class BoxLayout3(BoxLayout):
pass
class BoxLayout4(BoxLayout):
pass
class MyApp(App):
pass

Related

Either the class "FourthWindow" doesn't show stacklayout or its the only thing on the screen

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.

How to get, use and change values from a .kv file

So, I've been working on a very simple kivy app and am having trouble with the backend. How would you go about getting the values from text_input and changing label values? I've watched a few tutorials but their methods vary and I get error messages.
Here is my python code:
import kivy
from kivy.app import App
kivy.require('1.9.1')
class MyWindowApp(App):
pass
window = MyWindowApp()
window.run()
And here is the .kv file:
Screen:
side: side
FloatLayout:
Label:
text: "Side:"
pos_hint: {"x": 0.1, "y": 0.7}
text_size: self.size
Label:
text: "Volume:"
pos_hint: {"x": 0.1, "y": 0.65}
text_size: self.size
Label:
text: "Surface Area:"
pos_hint: {"x": 0.1, "y": 0.6}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x": 0.24, "y": 0.7}
id: side
Label:
text: "0cm"
id: volume
pos_hint: {"x": 0.27, "y": 0.65}
text_size: self.size
Label:
text: "0cm"
id: surface_area
pos_hint: {"x": 0.355, "y": 0.6}
text_size: self.size
As mentioned in the other answer, place Builder.load_file or Builder.load_string in your build method.
To handle changes e.g. if the user hits enter in the side input use on_text_validate: app.on_side_change(self) or place a button to trigger the calculation and use on_press method.
The on_side_change method in your class MyApp will handle the change. It will be called once the user hits enter. See the example code below, for a basic calculation.
For getting/setting values from the labels/inputs you can use ObjectProperty or StringProperty from kivy.properties. In the below code I'm using StringProperty.
Important you need the StringProperty in your app class and use it in the kv file.
For the mode of your calculation I've added a property, so you can use it in your calculation method.
The mode is also used in the kv file so it's displaying the current mode.
The switcher dictionary is the Python way to do a switch/case statement.
Example code
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
kv = """
Screen:
side: side
GridLayout:
rows: 1
cols:2
spacing:0
GridLayout:
rows: 5
cols:1
Button:
text: "Cube"
# on_press: app.mode = self.text
on_press: app.setMode(self)
Button:
text: "Cuboid"
on_press: app.setMode(self)
Button:
text: "Cylinder"
on_press: app.setMode(self)
Button:
text: "Cone"
on_press: app.setMode(self)
Button:
text: "Sphere"
on_press: app.setMode(self)
FloatLayout:
Label:
text: "The Volume and surface area of a {}:".format(app.mode)
pos_hint: {"x":0.1, "y":0.8}
text_size: self.size
Label:
text:"Side:"
pos_hint: {"x":0.1, "y":0.7}
text_size: self.size
Label:
text:"Volume:"
pos_hint: {"x":0.1, "y":0.65}
text_size: self.size
Label:
text:"Surface Area:"
pos_hint: {"x":0.1, "y":0.6}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":0.24, "y":0.7}
id: side
text: app.sideText
on_text_validate: app.on_side_change(self)
Label:
text: app.volume
pos_hint: {"x":0.27, "y":0.65}
text_size: self.size
Label:
text: app.area
pos_hint: {"x":0.355, "y":0.6}
text_size: self.size
"""
class MyApp(App):
sideText = StringProperty("")
area = StringProperty("0 cm²")
volume = StringProperty("0 cm³")
mode = StringProperty("Cube")
def build(self):
return Builder.load_string(kv)
def setMode(self, btn):
self.mode = btn.text
def on_side_change(self, instance):
print(instance.text)
result = 0
try:
value = float(instance.text)
except:
# failed to convert
return
def cubeCalc(val):
return {
"volume": val * val * val,
"area": val * val
}
switcher = {
"Cube": cubeCalc
}
method = switcher.get(self.mode, "Unknown mode")
if method is not "Unknown mode":
result = method(value) # result is a dictionary with volume & area
#print(result)
print(self.volume)
self.volume = "{:.2f} cm³".format(result["volume"])
self.area = "{:.2f} cm²".format(result["area"])
if __name__ == "__main__":
MyApp().run()
why you don't have a build method in your App class?
try this:
import kivy
from kivy.app import App
from kivy.lang.builder import Builder
kivy.require('1.9.1')
class MyWindowApp(App):
def build(self):
self.root = Builder.load_file("YOUR_KV_FILE.kv")
return self.root
window = MyWindowApp()
window.run()
Don't forget to change YOUR_KV_FILE.kv to your own kv filename
since you are not using Builder.load_file method to load your kv file you your kv file name must be something like mywindow.kv but im recommended to use Builder.load_file because you can save the whole window in a variable and access it later easy and it also make you free to change your kv design filename

How to change screens from python code in Kivy

So I'm working on making a fully functional login screen for my first serious kivy app and I want to be able to change windows/screens when the user presses on a button. I know normally in the KV file i'd just use on release but I want the on release to call to a method to verify the users credentials, and if those credentials are correct then change screens. So how in python itself would I be able to call to screen manager to change the screen?
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
class LoginLayout(Screen):
def login(self, **kwargs):
print("Login function working")
userEmail = self.ids.username.text
userPassword = self.ids.password.text
print(userEmail)
print(userPassword)
ScreenManager.current('emailWindow')
class EmailWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('loginScreen.kv')
class LoginScreen(App):
def build(self):
return kv
app = LoginScreen()
app.run()
KV
ScreenManager:
LoginLayout:
EmailWindow:
<LoginLayout>:
name: 'loginWindow'
canvas.before:
Color:
rgba: (28/255, 102/255, 137/255, 1)
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size: root.width, root.height
Label:
text: 'Username'
font_name: 'Framd.ttf'
font_size: 20
TextInput:
id: username
multiline: False
size_hint: (.5, .3)
pos_hint: {'center_x' : .5}
Label:
text: 'Password'
font_name: 'Framd.ttf'
font_size: 20
TextInput:
id: password
multiline: False
size_hint: (.5, .3)
pos_hint: {'center_x' : .5}
Button:
text: 'Login'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
on_release: root.login()
Button:
text: 'Create Account'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
Button:
text: 'Forgot login Info'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
<EmailWindow>:
name: 'emailWindow'
canvas.before:
Color:
rgba: (28/255, 102/255, 137/255, 1)
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size: root.width, root.height
Label:
text: 'To:'
font_name: 'Framd.ttf'
TextInput:
multiline: False
pos_hint: {'center_x': 0.5}
size_hint: (.5, .3)
font_name: 'Framd.ttf'
Label:
text: 'Subject'
TextInput:
multiline: False
pos_hint: {'center_x': 0.5}
size_hint: (.5, .3)
font_name: 'Framd.ttf'
Label:
text: 'Body'
font_name: 'Framd.ttf'
TextInput:
size_hint: (.5, .7)
pos_hint: {'center_x': 0.5}
multiline: True
Button:
text: 'send'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
When a Screen gets added to a ScreenManager, it gets a manager attribute set to the ScreenManager. So in your login() method you can do:
self.manager.current = 'emailWindow'
instead of:
ScreenManager.current('emailWindow')
Note that using ScreenManager, as you do above, references the ScreenManager class, not the ScreenManager instance that is in your App.

Using KIVY Popup I have NameError

Last time I solved the error thanks to you.
However, due to my lack of skills,
I looked up a lot of data but couldn't solve the error.
If I click information Button happen this error message.
File "", line 27, in
NameError: name 'Factory' is not defined
I want to make Project. This Picture. But The Button location always not good.
This is My Python KIVY code
#project.kv file
kv = '''
BoxLayout:
orientation: 'vertical'
Upper_bar:
size_hint: (1, 0.1)
Label:
text: 'Select Mode'
BoxLayout:
padding: [90, 40]
size_hint: (1, 0.5)
orientation: 'horizontal'
Button:
size_hint: (0.5, 1)
text: 'Object'
BoxLayout:
Button:
size_hint: (0.5, 1)
text: 'Street'
<Upper_bar>:
BoxLayout:
Button:
size_hint: (0.3, 1)
text: 'Information'
on_press: Factory.InformationPop().open()
<InformationPop#Popup>:
size_hint: 0.5, 0.5
tittle: 'Information'
auto_dismiss: True
BoxLayout:
orientation: 'vertical'
Label:
text:
"""Name:
Student Number:
E-mail: """
Button:
text:
'Close'
on_press:
root.dismiss()
size_hint_y: None
height: '40dp'
'''
class Upper_bar(BoxLayout):
pass
class AIObjectCameraApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
AIObjectCameraApp().run()
You just forgot to add the import of Factory at the top of your kv string:
#:import Factory kivy.factory.Factory

Accessing widget in child layout kivy

This is my code. I have a screen manager with two screens.
Screen 1: Login
Screen 2: Tabbed options
In screen 2 I have a dropdown widget in which I want to load some default values. But I am not able to access the id of the same.
Builder.load_string("""
<TACLogin>
FloatLayout:
MDToolbar:
title: "TEST"
pos_hint: {"x":0.001, "y":0.9}
MDRectangleFlatIconButton:
id: tac_screen1_next_id
icon: "page-next-outline"
font_size: '20sp'
font_name: 'fonts/prox_nova.ttf'
md_bg_color: 0, 0.502, 0.502, 1
text_color: 1,1,1,1
text: 'Login'
on_press: root.manager.current = 'tacconfig'
size_hint: None, None
size: dp(100), dp(30)
pos_hint: {"x":0.7, "y":0.2}
<TACConfig>
BoxLayout:
orientation:"vertical"
MDToolbar:
title: "Taxonomy Administration Console"
specific_text_color: app.theme_cls.accent_color
MDTabs:
id: android_tabs
text_color_normal: 1,1,1,1
Tab:
text:"Home"
text_color_normal: 1,1,1,1
MDLabel:
color: 0,0,0,1
font_size: '20sp'
font_name: 'fonts/prox_nova.ttf'
pos_hint: {"x":0.4, "y":0.1}
text:'WELCOME ADMIN'
Tab:
text_color_normal: 1,1,1,1
text:"Configure User"
TACUserConfig:
Tab:
text_color_normal: 1,1,1,1
text:"Configure DataSource"
TACScreen1:
Tab:
text_color_normal: 1,1,1,1
text:"Exit"
<TACUserConfig>
FloatLayout:
id: ucScreen_id
MDLabel:
color: 0,0,0,1
font_size: '15sp'
font_name: 'fonts/prox_nova.ttf'
text:'Select User Type'
pos_hint:{'center':(0.7,0.7)}
size_hint:0.8,1.4
MDDropDownItem:
id: user_type
pos_hint:{"x":0.5, "y":0.68}
dropdown_bg: [1, 1, 1, 1]
""")
This is my python code
class TACLogin(Screen, MDApp):
def __init__(self, **kwargs):
super(TACLogin, self).__init__(**kwargs)
class TACUserConfig(Screen, MDApp):
def __init__(self, **kwargs):
super(TACUserConfig, self).__init__(**kwargs)
print(self.ids)
def on_start(self):
self.ids.ucScreen_id.ids.user_type.items = ["Business User", "Admin User"]
sm = ScreenManager()
sm.add_widget(TACLogin(name='taclogin'))
sm.add_widget(TACConfig(name='tacconfig'))
sm.add_widget(TACUserConfig(name='tacuserconfig'))
class TestApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Teal"
return sm
if __name__ == '__main__':
TestApp().run()
I am trying to add values to the dropdown,the on_start function is not fired at all and I am not able to access the id of the dropdown user_type. Can someone please help me out?

Categories