I made a chat app but it was command line so I wanted to add some gui to it and after I started making app use ScreenManager the error start occurring.
Here is python code:
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(("192.168.41.20", 5002))
except Exception as e:
print(e)
class LoginScreen(Screen):
pass
class MainScreen(Screen):
pass
class SettingScreen(Screen):
pass
class WindowManager(ScreenManager):
pass
class MainApp(MDApp):
def build(self):
return Builder.load_file('kivy.kv')
def logger(self):
self.root.ids.welcome_label.text = ('Hello ' + self.root.ids.user.text + '!')
s.send(bytes('#u'+self.root.ids.user.text, 'utf-8'))
s.send(bytes('#p'+self.root.ids.password.text, 'utf-8'))
def clear(self):
self.root.ids.user.text = ""
self.root.ids.welcome_label.text = "WELCOME"
self.root.ids.password.text = ""
MainApp().run()
And here is my kivymd .kv code:
WindowManager:
LoginScreen:
MainScreen:
SettingScreen:
<LoginScreen>:
name: "login"
Widget:
MDCard:
size_hint: None, None
size: 300, 400
pos_hint: {"center_x": 0.5, "center_y":0.5 }
elevation: 10
padding: 25
spacing: 25
orientation: "vertical"
MDLabel:
id: welcome_label
text: "BALCOME!"
halign: 'center'
font_size: 40
size_hint_y: None
height: self.texture_size[1]
padding_y: 15
MDTextFieldRound:
id: user
hint_text: "username"
icon_right: "account"
width: 200
size_hint_x: None
font_size: 18
pos_hint: {"center_x": 0.5}
MDTextFieldRound:
id: password
hint_text: "password"
icon_right: "eye-off"
width: 200
size_hint_x: None
font_size: 18
pos_hint: {"center_x": 0.5}
password: True
MDRoundFlatButton:
text: "LOGIN"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: app.logger()
on_release: app.root.current = "main"
MDRoundFlatButton:
text: "CLEAR"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: app.clear()
Widget:
size_hint_y: None
height: 10
<MainScreen>:
name: "main"
MDRoundFlatButton:
text: "Get LOst"
pos_hint: {"center_y: 0.5"}
<SettingScreen>:
name: "satt"
MDRoundFlatButton:
text: "Get Lost"
pos_hint: {"center_y: 0.5"}
And when I run it this error comes:
AttributeError: 'set' object has no attribute 'items' error occurring when I trying to run my code.
Any help is highly appreciated.
Related
I want to know the method of loading the second screen when authentication is passed.
I can call the second screen from the .kv file vi on_press or other methods. But I need to call from python code to check the authentication.
Can anyone help with my code?
Here is my code:
app.py
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.properties import ObjectProperty
class my_layout(FloatLayout):
screen_mngr = ObjectProperty(None)
class myapp(MDApp):
def build(self):
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_palette = "BlueGray"
return Builder.load_file("app.kv")
def logger(self):
if self.root.ids.user.text == 'admin' and self.root.ids.password.text=='admin':
self.root.ids.welcome_label.text = f'Sup {self.root.ids.user.text}!'
screen = Screen(name='screen2')
else:
self.root.ids.welcome_label.text = 'Wrong credentials'
if __name__ == "__main__":
myapp().run()
And here is my design kv file.
app.kv file:
my_layout:
screen_mngr: screen_mngr
ScreenManager:
id: screen_mngr
home: home
Screen:
id: home
name: 'home'
MDCard:
size_hint: None, None
size: 450, 600
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
padding: 25
spacing: 25
orientation: 'vertical'
MDLabel:
id: welcome_label
text: "WELCOME"
font_size: 40
halign: 'center'
size_hint_y: None
height: self.texture_size[1]
padding_y: 15
MDTextField:
id: user
hint_text: "username"
icon_right: "account"
size_hint_x: None
width: 200
font_size: 18
pos_hint: {"center_x": 0.5}
MDTextField:
id: password
hint_text: "password"
icon_right: "eye-off"
size_hint_x: None
width: 200
font_size: 18
pos_hint: {"center_x": 0.5}
MDRoundFlatButton:
text: "LOG IN"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: screen2
Screen:
id: screen2
name: 'screen2'
MDRoundFlatButton:
text: "This is Second Screen\nGo to Screen1"
size_hint: 0.2,0.1
pos_hint: {"center_x":0.5,"y":0.5}
on_press: screen_mngr.current = "home"
A couple small problems:
First, in your kv you need to have your LOG IN Button call the code to handle the log in, like this:
MDRoundFlatButton:
text: "LOG IN"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: app.logger() # call the method that handles login
Then, in that method, you can change to the screen2 by using the current property of the ScreenManager, like this:
def logger(self):
if self.root.ids.user.text == 'admin' and self.root.ids.password.text=='admin':
self.root.ids.welcome_label.text = f'Sup {self.root.ids.user.text}!'
self.root.ids.screen_mngr.current = 'screen2' # go to screen2
# screen = Screen(name='screen2')
else:
self.root.ids.welcome_label.text = 'Wrong credentials'
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.
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
On display screen of my code i have used accordions, I have done every thing as instructed and the code for TextInput in that page is right but accordions are not working as intended and the textInput is not taking any inputs. I am new to kivy and as far as I know every thing seems right to me.
Heres my code:
import kivy
kivy.require('1.10.0')
from kivy.uix.stacklayout import StackLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.textinput import TextInput
from kivy.properties import StringProperty
import json
Builder.load_file('VocabularyJournal.kv')
class MenuPage(Screen):
pass
class DisplayPage(Screen): # here is the display page[![enter image description here][1]][1]
search_box= ObjectProperty()
label_maening=StringProperty()
label_synonym=StringProperty()
label_ant=StringProperty()
label_sentence=StringProperty()
def search_function(self):
with open('vocab_words.json') as rfile:
data=json.load(rfile)
word=self.search_box.text
for value in data:
if value['word']==word:
self.label_maening=value['meaning']
self.label_synonym=value['synonym']
self.label_ant=value['antonyms']
self.label_sentence=value['sentence']
class WordInsertPage(Screen):
pass
class NewWordPage(Screen):
word_box = ObjectProperty()
meaning_box = ObjectProperty()
synonym_box = ObjectProperty()
ant_box = ObjectProperty()
sentence_box = ObjectProperty()
def saving_data(self):
with open('vocab_words.json') as rfile:
data=json.load(rfile)
entry={'word': self.word_box.text, 'meaning': self.meaning_box.text, 'synonym': self.synonym_box.text, 'antonyms': self.ant_box.text, 'sentence': self.sentence_box.text}
data.append(entry)
with open('vocab_words.json','w') as wfile:
json.dump(data,wfile,indent=4)
class FlashCard(Screen):
pass
class WordGroups(Screen):
pass
class Manager(ScreenManager):
pass
class VocabularyJournalApp(App):
def build(self):
return Manager()
object = VocabularyJournalApp()
object.run()
heres the kivy code-
<Manager>:
MenuPage:
name: 'menu'
WordInsertPage:
name: 'insertword'
NewWordPage:
name: 'newword'
FlashCard:
name: 'flashcard'
WordGroups:
name: 'wordgroup'
DisplayPage:
name: 'display'
<MenuPage>:
Label:
text: "Vocabulary Journal"
size_hint: .90,.10
StackLayout:
orientation: 'tb-rl'
spacing: 10
padding: 10
Button:
text: 'Search'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='insertword'
Button:
text: 'New Word'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='insertword'
Button:
text: 'Flash Cards'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='flashcard'
Button:
text: 'Word Groups'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='wordgroup'
<WordInsertPage>:
FloatLayout:
Button:
text: "New Word"
on_press: root.manager.current='newword'
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.3}
background_down: 'darkgrey.png'
Button:
text: "search word"
on_press: root.manager.current='display'
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.5}
background_down: 'darkgrey.png'
Button:
text: 'Flash Cards'
on_press: root.manager.current="flashcard"
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.7}
background_down: 'darkgrey.png'
<NewWordPage>:
id: refer_to_it
word_box: word_input
meaning_box: meaning_input
synonym_box: Synonym_input
ant_box: ant_input
sentence_box: sentence_input
StackLayout:
orientation: 'tb-rl'
spacing: 10
padding: 90
TextInput:
text: "write your word here"
color: 1,1,1,1
id: word_input
width: 300
size_hint: None, .10
TextInput:
text: "write meaning of your word here"
color: 1,1,1,1
id: meaning_input
width: 600
size_hint: None, .20
TextInput:
text: "write Synonyms of your word here"
color: 1,1,1,1
id: Synonym_input
width: 600
size_hint: None, .20
TextInput:
text: "write antonyms of your text here"
color: 1,1,1,1
id: ant_input
width: 600
size_hint: None, .20
TextInput:
text: "write a sentence based on your word here"
color: 1,1,1,1
id: sentence_input
width: 600
size_hint: None, .20
Button:
text: 'Save'
size_hint: None,.10
width: 130
background_down:'darkgrey.png'
on_press: refer_to_it.saving_data()
<DisplayPage>: # here is the display page
search_box: search_text
BoxLayout:
size_hint_y: None
height: '48dp'
TextInput:
text:'enter the word you wanna search here'
id: search_text
on_text_validate: root.search_function()
Accordion:
orientation: 'vertical'
AccordionItem:
title:'meaning'
Label:
text: root.label_maening
text_size: self.width, None
AccordionItem:
title:'Synonym'
Label:
text: root.label_synonym
text_size: self.width, None
AccordionItem:
title:'Antonym'
Label:
text: root.label_ant
text_size: self.width, None
AccordionItem:
title:'Sentence'
Label:
text: root.label_sentence
text_size: self.width, None
In principle I see three problems:
on_text_validate isn't fired in multiline inputs. You should set multiline property to False.
Use hint_text property to set the suggestion text.
The weird behavior of your accordion is probably caused because you are loading your kv file twice (Your "Multiple screens named ..." warnings are indicative of that.). I recommend renaming your kv to vocabularyjournal.kv and not using Builder.load_file (). You can look at this related answer.
main.py:
import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
import json
class MenuPage(Screen):
pass
class DisplayPage(Screen):
search_box= ObjectProperty()
label_maening=StringProperty()
label_synonym=StringProperty()
label_ant=StringProperty()
label_sentence=StringProperty()
def search_function(self):
with open('vocab_words.json') as rfile:
data=json.load(rfile)
word=self.search_box.text
for value in data:
if value['word']==word:
self.label_maening=value['meaning']
self.label_synonym=value['synonym']
self.label_ant=value['antonyms']
self.label_sentence=value['sentence']
class WordInsertPage(Screen):
pass
class NewWordPage(Screen):
word_box = ObjectProperty()
meaning_box = ObjectProperty()
synonym_box = ObjectProperty()
ant_box = ObjectProperty()
sentence_box = ObjectProperty()
def saving_data(self):
with open('vocab_words.json') as rfile:
data=json.load(rfile)
entry={'word': self.word_box.text, 'meaning': self.meaning_box.text, 'synonym': self.synonym_box.text, 'antonyms': self.ant_box.text, 'sentence': self.sentence_box.text}
data.append(entry)
with open('vocab_words.json','w') as wfile:
json.dump(data,wfile,indent=4)
class FlashCard(Screen):
pass
class WordGroups(Screen):
pass
class Manager(ScreenManager):
pass
class VocabularyJournalApp(App):
def build(self):
return Manager()
obj = VocabularyJournalApp()
obj.run()
vocabularyjournal.kv:
<Manager>:
MenuPage:
name: 'menu'
WordInsertPage:
name: 'insertword'
NewWordPage:
name: 'newword'
FlashCard:
name: 'flashcard'
WordGroups:
name: 'wordgroup'
DisplayPage:
name: 'display'
<MenuPage>:
Label:
text: "Vocabulary Journal"
size_hint: .90,.10
StackLayout:
orientation: 'tb-rl'
spacing: 10
padding: 10
Button:
text: 'Search'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='insertword'
Button:
text: 'New Word'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='insertword'
Button:
text: 'Flash Cards'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='flashcard'
Button:
text: 'Word Groups'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='wordgroup'
<WordInsertPage>:
FloatLayout:
Button:
text: "New Word"
on_press: root.manager.current='newword'
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.3}
background_down: 'darkgrey.png'
Button:
text: "search word"
on_press: root.manager.current='display'
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.5}
background_down: 'darkgrey.png'
Button:
text: 'Flash Cards'
on_press: root.manager.current="flashcard"
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.7}
background_down: 'darkgrey.png'
<NewWordPage>:
id: refer_to_it
word_box: word_input
meaning_box: meaning_input
synonym_box: Synonym_input
ant_box: ant_input
sentence_box: sentence_input
StackLayout:
orientation: 'tb-rl'
spacing: 10
padding: 90
TextInput:
hint_text: "write your word here"
color: 1,1,1,1
id: word_input
width: 300
size_hint: None, .10
TextInput:
hint_text: "write meaning of your word here"
color: 1,1,1,1
id: meaning_input
width: 600
size_hint: None, .20
TextInput:
hint_text: "write Synonyms of your word here"
color: 1,1,1,1
id: Synonym_input
width: 600
size_hint: None, .20
TextInput:
hint_text: "write antonyms of your text here"
color: 1,1,1,1
id: ant_input
width: 600
size_hint: None, .20
TextInput:
hint_text: "write a sentence based on your word here"
color: 1,1,1,1
id: sentence_input
width: 600
size_hint: None, .20
Button:
hint_text: 'Save'
size_hint: None,.10
width: 130
background_down:'darkgrey.png'
on_press: refer_to_it.saving_data()
<DisplayPage>: # here is the display page
search_box: search_text
BoxLayout:
size_hint_y: None
height: '48dp'
TextInput:
hint_text:'enter the word you wanna search here'
id: search_text
multiline: False
on_text_validate: root.search_function()
Accordion:
orientation: 'vertical'
AccordionItem:
title:'meaning'
Label:
text: root.label_maening
text_size: self.width, None
AccordionItem:
title:'Synonym'
Label:
text: root.label_synonym
text_size: self.width, None
AccordionItem:
title:'Antonym'
Label:
text: root.label_ant
text_size: self.width, None
AccordionItem:
title:'Sentence'
Label:
text: root.label_sentence
text_size: self.width, None
Note: You shouldn't use object as variable name. It is a built-in function.
I am making an application.as far as I know I am doing thingd correctly but still getting this error
word=self.search_box.text
AttributeError: 'NoneType' object has no attribute 'text'
I have checked for typos and other common mistakes still its not working.
heres the code-
import kivy
kivy.require('1.10.0')
from kivy.uix.stacklayout import StackLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.textinput import TextInput
from kivy.properties import StringProperty
import json
Builder.load_file('VocabularyJournal.kv')
class MenuPage(Screen):
pass
class DisplayPage(Screen):
search_box= ObjectProperty()
label_maening=StringProperty()
label_synonym=StringProperty()
label_ant=StringProperty()
label_sentence=StringProperty()
def __init__(self, **kwargs):
super(DisplayPage,self).__init__(**kwargs)
with open('vocab_words.json') as rfile:
data=json.load(rfile)
word=self.search_box.text #the error occurred here
for value in data:
if value['word']==word:
self.label_maening=value['meaning']
self.label_synonym=value['synonym']
self.label_ant=value['antonyms']
self.label_sentence=value['sentence']
class WordInsertPage(Screen):
pass
class NewWordPage(Screen):
word_box = ObjectProperty()
meaning_box = ObjectProperty()
synonym_box = ObjectProperty()
ant_box = ObjectProperty()
sentence_box = ObjectProperty()
def saving_data(self):
with open('vocab_words.json') as rfile:
data=json.load(rfile)
entry={'word': self.word_box.text, 'meaning': self.meaning_box.text, 'synonym': self.synonym_box.text, 'antonyms': self.ant_box.text, 'sentence': self.sentence_box.text}
data.append(entry)
with open('vocab_words.json','w') as wfile:
json.dump(data,wfile,indent=4)
class FlashCard(Screen):
pass
class WordGroups(Screen):
pass
class Manager(ScreenManager):
pass
class VocabularyJournalApp(App):
def build(self):
return Manager()
object = VocabularyJournalApp()
object.run()
heres the kv code-
<Manager>:
MenuPage:
name: 'menu'
WordInsertPage:
name: 'insertword'
NewWordPage:
name: 'newword'
FlashCard:
name: 'flashcard'
WordGroups:
name: 'wordgroup'
DisplayPage:
name: 'display'
<MenuPage>:
Label:
text: "Vocabulary Journal"
size_hint: .90,.10
StackLayout:
orientation: 'tb-rl'
spacing: 10
padding: 10
Button:
text: 'Search'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='insertword'
Button:
text: 'New Word'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='insertword'
Button:
text: 'Flash Cards'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='flashcard'
Button:
text: 'Word Groups'
size_hint: None,.20
width: 130
background_down:'darkgrey.png'
on_press: root.manager.current='wordgroup'
<WordInsertPage>:
FloatLayout:
Button:
text: "New Word"
on_press: root.manager.current='newword'
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.3}
background_down: 'darkgrey.png'
Button:
text: "search word"
on_press: root.manager.current='display'
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.5}
background_down: 'darkgrey.png'
Button:
text: 'Flash Cards'
on_press: root.manager.current="flashcard"
font_size: 30
color: 0,0,0,1
size_hint: .2, .1
pos_hint: {"center_x": .5, "center_y": 0.7}
background_down: 'darkgrey.png'
<NewWordPage>:
id: refer_to_it
word_box: word_input
meaning_box: meaning_input
synonym_box: Synonym_input
ant_box: ant_input
sentence_box: sentence_input
StackLayout:
orientation: 'tb-rl'
spacing: 10
padding: 90
TextInput:
text: "write your word here"
color: 1,1,1,1
id: word_input
width: 300
size_hint: None, .10
TextInput:
text: "write meaning of your word here"
color: 1,1,1,1
id: meaning_input
width: 600
size_hint: None, .20
TextInput:
text: "write Synonyms of your word here"
color: 1,1,1,1
id: Synonym_input
width: 600
size_hint: None, .20
TextInput:
text: "write antonyms of your text here"
color: 1,1,1,1
id: ant_input
width: 600
size_hint: None, .20
TextInput:
text: "write a sentence based on your word here"
color: 1,1,1,1
id: sentence_input
width: 600
size_hint: None, .20
Button:
text: 'Save'
size_hint: None,.10
width: 130
background_down:'darkgrey.png'
on_press: refer_to_it.saving_data()
<DisplayPage>:
search_box: search_text # search_box is the reference to the textinput in py file
BoxLayout:
size_hint_y: None
height: '48dp'
TextInput:
text:'enter the word you wanna search here'
id: search_text
ToggleButton:
id: tog
text: 'Horizontal'
group: 'accordion'
state: 'down'
ToggleButton:
text: 'Vertical'
group: 'accordion'
Accordion:
orientation: 'horizontal' if tog.state == 'down' else 'vertical'
AccordionItem:
title:'meaning'
Label:
text: root.label_maening
text_size: self.width, None
AccordionItem:
title:'Synonym'
Label:
text: root.label_synonym
text_size: self.width, None
AccordionItem:
title:'Antonym'
Label:
text: root.label_ant
text_size: self.width, None
AccordionItem:
title:'Sentence'
Label:
text: root.label_sentence
text_size: self.width, None
the problem is caused because the children are not stuck in the constructor of the parent, it does it an instant later so search_box will be None in the constructor, the solution is to execute it an instant after finishing the constructor with the help of Clock:
from kivy.clock import Clock
class DisplayPage(Screen):
search_box= ObjectProperty()
label_maening=StringProperty()
label_synonym=StringProperty()
label_ant=StringProperty()
label_sentence=StringProperty()
def __init__(self, **kwargs):
super(DisplayPage,self).__init__(**kwargs)
Clock.schedule_once(self.callback)
def callback(self, dt):
with open('vocab_words.json') as rfile:
data=json.load(rfile)
word=self.search_box.text #the error occurred here
for value in data:
if value['word']==word:
self.label_maening=value['meaning']
self.label_synonym=value['synonym']
self.label_ant=value['antonyms']
self.label_sentence=value['sentence']