I have a Spinner and a ProgressBar in kivy. The Spinner is filled with values from 6 to 50. My goal is to pull the current value from the Spinner (string), parse it (to an int) and use the Spinner value on the value property of the ProgressBar. This has to happen everytime the user updates the spinner value. Here is my code:
main.py
from kivy.app import App
from kivy.config import Config
Config.set('graphics', 'resizable', False)
from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
class ApplicationLayout(FloatLayout):
def spinnerValues(self, min_value, max_value):
self.possible_values = []
for k in range(min_value, max_value + 1):
self.possible_values.append("" + str(k) + "")
return self.possible_values
def clearSelection(self):
self.ids.cb_word.active = False
self.ids.cb_letters.active = False
self.ids.cb_lowercase.active = False
self.ids.cb_uppercase.active = False
self.ids.cb_repeated_chars.active = False
self.ids.cb_numbers.active = False
self.ids.cb_special_chars.active = False
self.ids.lb_strength.text = ''
self.ids.pb_strength.value = 0
self.ids.it_word.text = ''
self.ids.it_passwords.text = ''
def currentValue(self, size):
print(type(int(size))) # just to ensure that this method can return an int
return int(size)
class PasswordGeneratorApp(App):
def build(self):
Window.clearcolor = (67 / 255, 67 / 255, 67 / 255, 1)
self.title = 'Password Generator'
return ApplicationLayout()
if __name__ == "__main__":
PasswordGeneratorApp().run()
passwordgenerator.kv
<Spinner#Spinner>
size_hint:[0.07,0.05]
<ButtonWidget#Button>
size_hint:[0.15,0.07]
font_size:'18sp'
background_normal: ''
background_color: (63/255, 191/255, 191/255, 0.6)
<OneWordLabel#Label>
font_size:'20sp'
size_hint:[0.1,0.05]
<MultiWordLabel#Label>
font_size:'20sp'
size_hint:[0.25,0.05]
<CheckBox#CheckBox>
size_hint:[0.05, 0.05]
<TextInput#TextInput>
size_hint:[0.3,0.06]
multiline: True
<ProgressBar#ProgressBar>
size_hint:[0.4,None]
<ApplicationLayout>:
padding: [30,30,0,0]
MultiWordLabel:
pos_hint:{'y':0.9}
text: 'Password length'
Spinner:
text_autoupdate: True
id: sp_passw_length
pos_hint: {'right':0.32, 'y':0.9}
values: root.spinnerValues(6, 50)
on_text: root.currentValue(self.text)
ProgressBar:
id:pb_strength
pos_hint: {'right': 0.77,'y':0.84}
value: root.currentValue(sp_passw_length.text)
OneWordLabel:
id: lb_strength
text: 'Strong'
pos_hint: {'right': 0.92,'y':0.9}
OneWordLabel:
text: 'Include:'
pos_hint: {'right':0.125, 'y': 0.8} #fix positioning when screen is maximized
CheckBox:
id:cb_word
pos_hint: {'right':0.19, 'y':0.8}
active: False
OneWordLabel:
text: 'Word'
pos_hint: {'right':0.275, 'y':0.8}
TextInput:
id: it_word
pos_hint: {'right':0.58, 'y':0.795}
disabled: not cb_word.active
CheckBox:
id: cb_letters
pos_hint: {'right':0.67, 'y':0.8}
OneWordLabel:
text: 'Letters:'
pos_hint: {'right':0.77, 'y':0.8}
CheckBox:
id: cb_lowercase
pos_hint: {'right':0.70, 'y':0.73}
OneWordLabel:
text: 'Lowercase'
pos_hint: {'right': 0.815, 'y':0.73}
CheckBox:
id: cb_uppercase
pos_hint: {'right':0.70, 'y':0.67}
OneWordLabel:
text: 'Uppercase'
pos_hint: {'right': 0.815, 'y':0.67}
CheckBox:
id: cb_numbers
pos_hint: {'right':0.19, 'y':0.58}
OneWordLabel:
text: 'Numbers'
pos_hint: {'right': 0.30, 'y':0.58}
CheckBox:
id: cb_repeated_chars
pos_hint: {'right':0.51, 'y':0.58}
MultiWordLabel:
text: 'Don\'t repeat characters'
pos_hint: {'right':0.775, 'y':0.58}
CheckBox:
id: cb_special_chars
pos_hint: {'right':0.19, 'y':0.51}
MultiWordLabel:
text: 'Special characters'
pos_hint: {'right':0.425, 'y':0.51}
OneWordLabel:
text: 'Quantity:'
pos_hint: {'right':0.58, 'y':0.51}
Spinner:
text_autoupdate: True
pos_hint: {'right': 0.69, 'y': 0.51}
values: root.spinnerValues(1, 20)
ButtonWidget:
text: 'Generate'
pos_hint: {'right':0.45, 'y':0.32}
ButtonWidget:
text: 'Clear'
pos_hint: {'right':0.65, 'y':0.32}
on_press: root.clearSelection()
MultiWordLabel:
text: 'Your password(s):'
pos_hint: {'right': 0.385, 'y':0.15}
TextInput:
id: it_passwords
pos_hint: {'right':0.69, 'y':0.145}
readonly: True
The Spinner and the ProgressBar of interest have the 'sp_passw_length' and 'pb_strength' ids, respectively.
It is only necessary that you convert the value to int if it is not an empty string:
ProgressBar:
id:pb_strength
pos_hint: {'right': 0.77,'y':0.84}
value: root.currentValue(int(sp_passw_length.text)) if sp_passw_length.text != "" else 6
Related
I'm just learning the Python , please don't judge too harshly. I'm working on a coffee shop position count program using Kivy. I've run into a few issues that I can't resolve.
There are 4 screens in the reduced copy of my program: MainWindow, CoffeeWindow, TeaWindow and SumMenu.
There are buttons on the CoffeeWindow and TeaWindow screens, the program count clicks on these buttons and should show the result in the SumMenu screen .
I can show in SumMenu the number of clicks on the buttons from CoffeeWindow or TeaWindow, but I can't show the result from both screens at the same time, I tried different ways, but I constantly encounter errors.
Please help me solve my problem, thanks in advance!
main.py:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class SumMenu(Screen):
def on_pre_enter(self, *args):
if self.manager.ids.coffee.coff: self.ids.label1.text = ""
if self.manager.ids.coffee.coff1 != 0: self.ids.label1.text += f"coffee 1 : {self.manager.ids.coffee.coff1}\n"
if self.manager.ids.coffee.coff2 != 0: self.ids.label1.text += f"coffee 2 : {self.manager.ids.coffee.coff2}\n"
if self.manager.ids.coffee.coff3 != 0: self.ids.label1.text += f"coffee 3 : {self.manager.ids.coffee.coff3}\n"
if self.manager.ids.coffee.coff4 != 0: self.ids.label1.text += f"coffee 4 : {self.manager.ids.coffee.coff4}\n"
#if self.manager.ids.tea.tea: self.ids.label1.text = ""
#if self.manager.ids.tea.tea1 != 0: self.ids.label2.text += f"tea 1 : {self.manager.ids.tea.tea1}\n"
#if self.manager.ids.tea.tea2 != 0: self.ids.label2.text += f"tea 2 : {self.manager.ids.tea.tea2}\n"
#if self.manager.ids.tea.tea3 != 0: self.ids.label2.text += f"tea 3 : {self.manager.ids.tea.tea3}\n"
#if self.manager.ids.tea.tea4 != 0: self.ids.label2.text += f"tea 4 : {self.manager.ids.tea.tea4}\n"
class CoffeeWindow(Screen):
coff = True
coff_tup = []
def count(self, num):
self.coff_tup.append(num)
self.coff1 = self.coff_tup.count(1)
self.coff2 = self.coff_tup.count(2)
self.coff3 = self.coff_tup.count(3)
self.coff4 = self.coff_tup.count(4)
class TeaWindow(Screen):
tea = True
tea_tup = []
def count(self, num):
self.tea_tup.append(num)
self.tea1 = self.tea_tup.count(1)
self.tea2 = self.tea_tup.count(2)
self.tea3 = self.tea_tup.count(3)
self.tea4 = self.tea_tup.count(4)
class MainWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('my.kv')
class MainApp(App):
def build(self):
return kv
if __name__ == '__main__':
MainApp().run()
my.kv:
<CoffeeButton#Button>:
font_size: "23sp"
size_hint: 0.5, 0.12
bold: True
<HorizBoxLayout#BoxLayout>:
padding: 30
spacing: 25
orientation: "horizontal"
<SumLabel#Label>:
bold: True
halign: "left"
valign: "middle"
WindowManager:
MainWindow:
id: main
CoffeeWindow:
id: coffee
TeaWindow:
id: tea
SumMenu:
id: summenu
<MainWindow>:
name: "main_window"
HorizBoxLayout:
CoffeeButton:
text: "Go to Coffee"
pos_hint: {'x' : 0, 'center_y' : 0.5}
on_release:
app.root.current = "coffee"
app.root.transition.direction = "left"
CoffeeButton:
text: "Go to Tea"
pos_hint: {'x' : 0, 'center_y' : 0.5}
on_release:
app.root.current = "tea"
app.root.transition.direction = "left"
<CoffeeWindow>:
name: "coffee"
GridLayout:
rows: 3
size_hint: 1, 0.8
pos_hint: {'center_x' : 0.5, 'top' : 0.95}
padding: 40
spacing: 40
CoffeeButton:
text: "coffee 1"
on_release:
root.count(1)
CoffeeButton:
text: "coffee 2"
on_release:
root.count(2)
CoffeeButton:
text: "coffee 3"
on_release:
root.count(3)
CoffeeButton:
text: "coffee 4"
on_release:
root.count(4)
Button:
bold: True
size_hint: 0.5, 0.1
font_size: "18sp"
pos_hint: {'right' : 0.5, 'y' : 0}
text: "Show Menu"
on_release:
app.root.current = "summenu"
app.root.transition.direction = "left"
Button:
bold: True
size_hint: 0.5, 0.1
font_size: "18sp"
pos_hint: {'right' : 0.5, 'y' : 0}
text: "Go to Main"
on_release:
app.root.current = "main_window"
app.root.transition.direction = "right"
<TeaWindow>:
name: "tea"
GridLayout:
rows: 3
size_hint: 1, 0.8
pos_hint: {'center_x' : 0.5, 'top' : 0.95}
padding: 40
spacing: 40
CoffeeButton:
text: "tea 1"
on_release:
root.count(1)
CoffeeButton:
text: "tea 2"
on_release:
root.count(2)
CoffeeButton:
text: "tea 3"
on_release:
root.count(3)
CoffeeButton:
text: "tea 4"
on_release:
root.count(4)
Button:
bold: True
size_hint: 0.5, 0.1
font_size: "18sp"
pos_hint: {'right' : 0.5, 'y' : 0}
text: "Show Menu"
on_release:
app.root.current = "summenu"
app.root.transition.direction = "left"
Button:
bold: True
size_hint: 0.5, 0.1
font_size: "18sp"
pos_hint: {'right' : 0.5, 'y' : 0}
text: "Go to Main"
on_release:
app.root.current = "main_window"
app.root.transition.direction = "right"
<SumMenu>:
name: "summenu"
BoxLayout:
orientation: "vertical"
padding: 30
spacing: 15
pos_hint: {'x' : 0, 'center_y' : 0.57}
size_hint: 1, 0.88
SumLabel:
id: label1
SumLabel:
id: label2
Button:
bold: True
size_hint: 0.5, 0.1
font_size: "18sp"
pos_hint: {'right' : 0.5, 'y' : 0}
text: "Go to Main"
on_release:
app.root.current = "main_window"
app.root.transition.direction = "right"
You can try storing all of the button click counts in a dictionary that get's updated whenever one of the buttons is pressed. Then in your summ screen you can simply build your label text based off of the keys and values in the dictionaries for the Tea and Coffee screens.
For example:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class SumMenu(Screen):
def on_pre_enter(self, *args):
coffee = self.manager.ids.coffee.clickCounter
tea = self.manager.ids.tea.clickCounter
self.set_label_text("Coffee", coffee, self.ids.label1)
self.set_label_text("Tea", tea, self.ids.label2)
def set_label_text(self, title, counts, label):
label.text = ""
for item_num, count in counts.items():
label.text += f"{title} {item_num} : {count}\n\n"
class CoffeeWindow(Screen):
clickCounter = {}
def count(self, num):
self.clickCounter.setdefault(num, 0)
self.clickCounter[num] += 1
class TeaWindow(Screen):
clickCounter = {}
def count(self, num):
self.clickCounter.setdefault(num, 0)
self.clickCounter[num] += 1
class MainWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('my.kv')
class MainApp(App):
def build(self):
return kv
if __name__ == '__main__':
MainApp().run()
I have made a popup to show up when an error occurs, with a button that closes the popup when clicked. All worked well until I tried getting an error for 2 times. In the second time the popup did not close and I am wondering if there is a way to work it out.
This is the python code:
class MyPopup(Popup):
filechooser= ObjectProperty(None)
class ErrorPopup(Popup):
filechooser= ObjectProperty(None)
class Main(FloatLayout):
audio_check= ObjectProperty(None)
video_check= ObjectProperty(None)
spinner_id= ObjectProperty(None)
yt_link=ObjectProperty(None)
name=ObjectProperty(None)
error_label=ObjectProperty(None)
def submit_text(self):
self.error_popup=MyApp()
if self.audio_check.active and self.video_check.active:
try:
YouTube(self.yt_link.text).streams.filter(res=self.spinner_id.text).first().download(path, filename=self.name.text+'.mp4')
except:
self.error_popup.error()
elif self.audio_check.active and not self.video_check.active:
try:
YouTube(self.yt_link.text).streams.filter(only_audio=True).first().download(path, filename=self.name.text+'.mp3')
except:
self.error_popup.error()
elif not self.audio_check.active and self.video_check.active:
try:
YouTube(self.yt_link.text).streams.filter(res=self.spinner_id.text, only_video =True).first().download(path, filename=self.name.text+'.mp4')
except:
self.error_popup.error()
elif not self.audio_check.active and not self.video_check.active:
self.error_popup.error()
def spinner_clicked(self, value):
self.ids.spinner_id.text= value
class MyApp(App):
def build(self):
return Main()
def open_popup(self):
self.popup = MyPopup()
self.popup.open()
def dismiss_popup(self):
self.popup.dismiss()
global path
path=self.popup.filechooser.path
def error(self):
self.error_popup= ErrorPopup()
self.error_popup.open()
def try_again(self):
self.error_popup.dismiss()
print("Andrew")
if __name__ == '__main__':
MyApp().run()
This is the kivy code:
<MyPopup>:
auto_dismiss: False
title: "Select a folder"
filechooser: filechooser
FloatLayout:
FileChooserIconView:
id: filechooser
Button:
id:my_button
text: 'Save'
size_hint: (0.1, 0.1)
pos_hint:{'x': 0, 'y': 0}
on_release: app.dismiss_popup()
<ErrorPopup>:
title: "Error"
Button:
text: "Try Again"
on_release: app.try_again()
<Main>:
audio_check: audio_check
video_check: video_check
spinner_id: spinner_id
yt_link: yt_link
name: name
folder_button: folder_button
BoxLayout:
orientation:'vertical'
cols: 4
Label:
text: "YouTube Downloader"
halign: 'center'
bold: True
font_size:'50sp'
TextInput:
id: yt_link
size_hint: (.5, .2)
multiline: False
hint_text: 'Enter the link of the Youtube video you want to download.'
pos_hint: {"x": 0.25}
TextInput:
id: name
size_hint: (.5, .2)
multiline: False
hint_text: 'Enter the name you want the file to have.'
pos_hint: {"x": 0.25}
BoxLayout:
cols:4
BoxLayout:
Label:
text: "Audio:"
halign: 'center'
font_size:'20sp'
CheckBox:
id: audio_check
BoxLayout:
Label:
text: "Video:"
halign: 'center'
font_size:'20sp'
CheckBox:
id: video_check
FloatLayout:
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}
FloatLayout:
Button:
id:folder_button
text: 'Folder'
on_release: app.open_popup()
size_hint: None, None
size: 130, 50
pos_hint: {'x':0.2,'y':.4}
Button:
text: "Submit"
size_hint: (.5, .2)
pos_hint: {"x": 0.25}
on_release: root.submit_text()
The problem is in your submit() method. The code:
self.error_popup=MyApp()
is creating a new instance of MyApp, then the code:
self.error_popup.error()
is calling the error() method from that new instance of MyApp. You need to be calling the methods of the App that you are running. To do that, just remove the line:
self.error_popup=MyApp()
And replace:
self.error_popup.error()
with:
App.get_running_app().error()
This makes sure that you are calling the error() method of the App that you are running.
Hello,
What I am actually trying to do is the following:
I want to create this login screen where if you have the correct mail (which in this case is only test#test.com) to trigger the inapp screen from the KV file and this is my actual problem.
I cannot trigger the "inapp" screen
The reason why I don't have my screenmanager and my screens classes in the PY file is because it gets bugged and when I switch screens it overlaps
Here is an example of the buggy UI
What am I doing wrong in my case?
This is my PY file:
class mytest(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.accent_palette = 'Blue'
self.theme_cls.accent_hue = '300'
self.theme_cls.primary_palette = "Green"
self.theme_cls.primary_hue = "400"
self.icon = 'testphoto.png'
self.title = "coolapp"
def login_checker(self, mail, psswrd):
hismail = mail
hispass = psswrd
print(themail)
print(thepass)
access_screen = self.root.ids.inapp
if themail == "test#test.com":
print("Corect")
access_screen
else:
toast("Invalid E-mail")
And this is the KV file:
BoxLayout:
ScreenManager:
id: scrin_meneger
Screen: #LOGIN
name: "login"
id: loginn
FloatLayout:
orientation: 'vertical'
Image: #Login Background Image
source: "./pictures/whitebg.jpg"
allow_stretch: True
keep_ratio: False
MDTextField: #mail-input
id: emadress
pos_hint: {'center_x': .5, 'center_y': .6}
size_hint: 0.60, 0.06
hint_text: "Email: "
current_hint_text_size: 0.5, 1
current_hint_text_color: 0, 0, 0, .60
helper_text: "No input provided"
helper_text_mode: "on_error"
color_mode: 'custom'
line_color_focus: 0, 0, 0, 1
required: True
max_text_lenght: 20
#min_text_lenght: 5
MDTextField: #pass-input
id: psswd
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: 0.60, 0.06
password: True
hint_text: "Password: "
current_hint_text_color: 0, 0, 0, .60
helper_text: "No input provided"
helper_text_mode: "on_error"
color_mode: 'custom'
line_color_focus: 0, 0, 0, 1
required: True
max_text_lenght: 20
#min_text_lenght: 5
MDFlatButton: #Login Button
text: "Login"
text_color: 0, 0, 0, .80
pos_hint: {'center_x': .3, 'y': .2}
size_hint: 0.4, 0.1
on_release:
app.login_checker(emadress.text, psswd.text)
Screen: #Application
name: 'inapp'
id: inapp
BoxLayout:
orientation: 'vertical'
MDBottomNavigation:
#Screen 1
MDBottomNavigationItem:
id: main_screen
name: "main_menu"
text: "Main Menu"
icon: "air-humidifier"
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: toolbar
title: "This is my MDToooolbar"
You just need to access the ScreenManager to set the current Screen, like this:
if themail == "test#test.com":
print("Corect")
self.root.ids.scrin_meneger.current = 'inapp'
else:
toast("Invalid E-mail")
What I'm trying to achieve here is to change the color button in the SurveyHeader widget after clicking either checkboxes. Example: after checking any checkboxes in question 3, I would like only button number "3" to turn red. Also, after clicking next, I would like the button number "3" to remain red. This is where I'm having a hard time., after switching screens, my button color changes to the original color. Is it because I'm creating a new instance of QuestionsScreen1 everytime? If so, is there any workaround for my case?
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition, WipeTransition, NoTransition, SlideTransition
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivymd.theming import ThemeManager
import re
class NavTray1(BoxLayout):
pass
class SurveyHeader(GridLayout):
pass
class SubjectsLayout(GridLayout):
pass
class MainScreen(Screen):
pass
class BeginScreen(Screen):
pass
class QuestionsScreen1(Screen):
def insert_data_A(self, *args):
if args[1] == True:
pass
def insert_data_B(self, *args):
self.question_text1 = MDApp.get_running_app().root.current
if args[1] == True:
pass
class MyScreenManager(ScreenManager):
# Create new page from 1 to 5.
def new_page(self):
if self.current == 'begin':
s = QuestionsScreen1(name='Question 1')
if "Question 1" in self.screen_names:
self.current = 'Question 1'
else:
self.add_widget(s)
self.current = 'Question 1'
elif self.current =='Question 5':
pass
else:
current_page_number = int(re.search(r'\d+', self.current).group(0))
s = QuestionsScreen1(name='Question {}'.format(str(int(current_page_number +1))))
if "Question {}".format(str(int(current_page_number +1))) in self.screen_names:
self.current = 'Question {}'.format(str(int(current_page_number +1)))
else:
self.add_widget(s)
self.current = 'Question {}'.format(str(int(current_page_number + 1)))
# Switch screens according to number.
def switch_pages(self, instance):
question_button = StringProperty()
self.question_button = instance.text
s = QuestionsScreen1(name='Question {}'.format(self.question_button))
if 'Question {}'.format(self.question_button) in self.screen_names:
self.current = 'Question {}'.format(self.question_button)
else:
self.add_widget(s)
self.current = 'Question {}'.format(self.question_button)
# Switch screens between 1 to 5.
def back_page(self):
current_page = StringProperty()
if self.current == 'Question 1':
pass
else:
current_page_number = int(re.search(r'\d+', self.current).group(0))
s = QuestionsScreen1(name='Question {}'.format(str(int(current_page_number -1))))
if "Question {}".format(str(int(current_page_number -1))) in self.screen_names:
self.current = 'Question {}'.format(str(int(current_page_number - 1)))
else:
self.add_widget(s)
self.current = 'Question {}'.format(str(int(current_page_number - 1)))
main_widget_kv = ('''
#: import ScrollEffect kivy.effects.scroll.ScrollEffect
MyScreenManager:
BeginScreen:
<BeginScreen>:
begin_button:begin_button
name: "begin"
canvas.before:
Color:
rgb: .1, .1, .1
FloatLayout:
id: begin_layout
Button:
id: begin_button
text: 'Begin'
font_size: 24
on_press: app.root.new_page()
size_hint: (.4,.25)
pos_hint: {"center_x":.5, "center_y":.2}
color: [0,0,0,1]
<NavTray1>:
cols: 3
padding: '5dp'
spacing: '5dp'
canvas.before:
Color:
rgb: .1, .1, .1
Rectangle:
size: self.size
pos: self.pos
MDRaisedButton:
size_hint_x: None
color: [0.4, 0.4, 0.4, 1]
font_style: 'Body1'
height: dp(80)
text: 'Back'
on_release : app.root.back_page()
BoxLayout:
size_hint_x: 0.4
orientation: 'vertical'
Label:
font_style: 'Body1'
MDRaisedButton:
size_hint_x: None
color: [6/255, 114/255, 0, 1]
height: dp(80)
text: "Next"
font_style: 'Body1'
background_color: [28/138, 1, 35/138, 0.5]
on_release : app.root.new_page()
<QuestionsScreen1>:
BoxLayout:
orientation: 'vertical'
size: root.size
pos: root.pos
SurveyHeader:
size_hint: (1.0, None)
height: '90dp'
id: header
rows: 2
Button:
text: "1"
background_color: [0,255,255,1]
on_release: app.root.switch_pages(self)
Button:
text: "2"
background_color: [0,255,255,1]
on_release: app.root.switch_pages(self)
Button:
text: "3"
background_color: [0,255,255,1]
on_release: app.root.switch_pages(self)
Button:
text: "4"
background_color: [0,255,255,1]
on_release: app.root.switch_pages(self)
Button:
text: "5"
background_color: [0,255,255,1]
on_release: app.root.switch_pages(self)
ScrollView:
size_hint: (1.0, None)
height: root.height - header.height - navtray.height
SubjectsLayout:
cols: 1
Label:
size_hint_y : 0.25
text: app.root.current
text_size: self.size
valign: 'middle'
halign: 'center'
GridLayout:
cols: 2
rows: 2
size_hint_y : 0.75
Label:
text: 'a'
font_size: "20dp"
size_hint_x : 0.8
CheckBox:
group: 'answer_group'
size_hint_x : 0.2
on_active: root.insert_data_A(*args)
Label:
text: 'b'
font_size: "20dp"
size_hint_x : 0.8
CheckBox:
group: 'answer_group'
size_hint_x : 0.2
on_active: root.insert_data_B(*args)
NavTray1:
id: navtray
size_hint: (1.0, None)
height: '90dp'
''')
class TestApp(MDApp):
def __init__(self,**kwargs):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Red"
super().__init__(**kwargs)
def build(self):
main_widget = Builder.load_string(main_widget_kv)
return main_widget
if __name__ == '__main__':
TestApp().run()
I got a popup filechooser from the below link:
Kivy popup Filechooser pass variable (selection)
I cannot get the file path string value to pass between my main Tab() class instance of the app and the class FileChoosePopup popup instance. I know this question has been asked before, but I cannot seem to figure it out. When I run the app and click on the file I want to pass to a TextInput on my main class I get the following error:
AttributeError: 'super' object has no attribute '__getattr__'
I have tried passing a reference to the popup class instance in the main class by using the super init method, but then the app does not even initialize.
Here is my popup in python:
class FileChoosePopup(Popup):
file_path = StringProperty("No file chosen")
def __init__(self, **kwargs):
super(FileChoosePopup, self).__init__(**kwargs)
self.Tab = Tab()
def load(self, selection):
self.file_path = str(selection[0])
path_file = self.file_path
the_file = self.ids.get_file #is the textinput id
if path_file != "No file chosen":
the_file.text = path_file
self.dismiss()
else:
self.dismiss()
class Tab(StackLayout):
def open_popup(self):
the_popup = FileChoosePopup()
the_popup.open()
Here the kivy code:
<FileChoosePopup>:
title: "Choose a .CSV File"
size_hint: .9, .9
auto_dismiss: False
BoxLayout:
orientation: "vertical"
FileChooser:
id: filechooser
FileChooserIconLayout
BoxLayout:
size_hint: (1, 0.1)
pos_hint: {'center_x': .5, 'center_y': .5}
spacing: 20
RoundedCancelButton:
text: "Cancel"
on_release: root.dismiss()
RoundedAcceptButton:
text: "Load"
on_release: root.load(filechooser.selection)
id: ldbtn
disabled: True if filechooser.selection==[] else False
<Tab>:
TabbedPanel:
do_defualt_tab: False
background_color: (.87, .87, .87, 1)
border: [0, 0, 0, 0]
background_image: 'path/to/background/image'
TabbedPanelItem:
text: 'Import'
background_color: (1, .5, 0, 1)
background_normal: ''
StackLayout:
orientation: 'lr-tb'
size_hint_y: None
height: 30
spacing: 5
Label:
text: ''
size_hint_x: 1
Label:
text: ''
size_hint_x: 0.2
RoundedButton:
text: 'Choose File'
size_hint_x: 0.2
on_press: root.open_popup()
TextInput:
id: get_file
readonly: True
size_hint_x: 0.4
Label:
text: ''
size_hint_x: 0.2
Can someone please give me some pointers on how to get the value to pass from the popup to the textinput?
Reference TextInput
Populate TextInput by using the following:
self.ids.get_file.text = self.file_path
Example
main.py
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty, StringProperty
from kivy.lang import Builder
class FileChoosePopup(Popup):
load = ObjectProperty()
class Tab(TabbedPanel):
file_path = StringProperty("No file chosen")
the_popup = ObjectProperty(None)
def open_popup(self):
self.the_popup = FileChoosePopup(load=self.load)
self.the_popup.open()
def load(self, selection):
self.file_path = str(selection[0])
self.the_popup.dismiss()
print(self.file_path)
# check for non-empty list i.e. file selected
if self.file_path:
self.ids.get_file.text = self.file_path
Builder.load_file('main.kv')
class TestApp(App):
def build(self):
return Tab()
if __name__ == "__main__":
TestApp().run()
main.kv
<FileChoosePopup>:
title: "Choose a .CSV File"
size_hint: .9, .9
auto_dismiss: False
BoxLayout:
orientation: "vertical"
FileChooser:
id: filechooser
FileChooserIconLayout
BoxLayout:
size_hint: (1, 0.1)
pos_hint: {'center_x': .5, 'center_y': .5}
spacing: 20
Button:
text: "Cancel"
on_release: root.dismiss()
Button:
text: "Load"
on_release: root.load(filechooser.selection)
id: ldbtn
disabled: True if filechooser.selection==[] else False
<Tab>:
do_default_tab: False
TabbedPanelItem:
text: 'Import'
background_color: (1, .5, 0, 1)
background_normal: ''
StackLayout:
orientation: 'lr-tb'
size_hint_y: None
height: 30
spacing: 5
Label:
text: ''
size_hint_x: 1
Label:
text: ''
size_hint_x: 0.2
Button:
text: 'Choose File'
size_hint_x: 0.2
on_press: root.open_popup()
TextInput:
id: get_file
readonly: True
size_hint_x: 0.4
Label:
text: ''
size_hint_x: 0.2
Output