This questions has been asked and answered quite often, but I still can't get it to work. I want to access a widget that is a children of another widget. For this I used an ObjectProperty. When I try to access the ObjectProperty (by opening any file via the FileChooser popup) to change the label's text I get this error:
self.pdfpages.text = "change to this" AttributeError: 'kivy.properties.ObjectProperty' object has no attribute 'text'
Do I need to initialize the ObjectProperty? Or is there a problem with my .kv structure?
main.py
import kivy
kivy.require('1.10.0') # replace with your current kivy version !
# Kivy Imports
from kivy.app import App
#UI Eleemnts
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from kivy.uix.scatter import Scatter
from kivy.uix.image import Image
#Core Elements
from kivy.core.image import Image as CoreImage
from kivy.properties import ObjectProperty
# Python Imports
import os
class Window(BoxLayout):
#add child widgets (in kv file)
pass
class PDFView(ScrollView):
pdfpages = ObjectProperty()
def newPage(self, filepath):
#here the error occurs
self.pdfpages.text = "change to this"
class SideBar(BoxLayout):
def openfile(self):
print("Button pressed")
OpenDialog().open()
class OpenDialog(Popup):
def cancelfile(self):
#close popup
self.dismiss()
print("No file opened")
def openfile(self, path, selection):
#selection can contain multiple files, [0] is first or only
self.dismiss()
print("Opened File: " + os.path.join(path, selection[0]))
#open PDFView class
PDFView.newPage(PDFView, os.path.join(path, selection[0]))
class PDFEditor(App):
title = "PDFEditor"
#gets called on startup
#load program
def build(self):
#return root node
return Window()
if __name__ == '__main__':
PDFEditor().run()
PDFEditor.kv
<Window>:
#this is the main (root) "window"
orientation: "horizontal"
SideBar:
size_hint: (.1, 1)
PDFView:
size_hint: (.9, 1)
<PDFView>:
#handler for ObjectProperty
pdfpages: pdfpages
Scatter:
#only zoom
BoxLayout:
#add Images in here somehow
orientation: "vertical"
Label:
id: pdfpages
text: "hi"
<SideBar>:
orientation: "vertical"
Button:
id: btn_openfile
on_release: root.openfile()
text: "Open File"
Label:
text: "Hello!"
<OpenDialog>:
title: "Choose File"
BoxLayout:
#Fullscreen
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: chsr_open
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancelfile()
Button:
text: "Open"
on_release: root.openfile(chsr_open.path, chsr_open.selection)
The problem here is that you set the text of a new instance, wich is not even on the window, rather than the one you allready have.
To fix this, you need to access the one you have.
First, make your Window
as an App
attribute, so you can reference it later.
class PDFEditor(App):
title = "PDFEditor"
def build(self):
self.root = Window()
return self.root
Then give the PDFView
an id
in kv
<Window>:
orientation: "horizontal"
SideBar:
size_hint: (.1, 1)
PDFView:
id: pdfview
size_hint: (.9, 1)
Then in your openfile
method, you can get the running apps root
attribute you created earlier, like this.
def openfile(self, path, selection):
self.dismiss()
print("Opened File: " + os.path.join(path, selection[0]))
app = App.get_running_app()
pdf = app.root.ids.pdfview
pdf.newPage(os.path.join(path, selection[0]))
That way you can access the ids
of your Window
class