I am creating a simple, two-screen interface with Kivy for an image classification task. In the first screen, I am selecting an image using the file chooser and displaying it. In the second screen, I want to show the same image and the result of the classification task. The transition between screens is done via a button on the first screen.
My question is: When I press the button, how can I trigger an update of the image source property on the second screen, such that the chosen image will be displayed on the second screen? The classification part is just to understand the background of my question, I did not include it in the code.
Here is the main.py
file
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty
class WindowManager(ScreenManager):
image_source = StringProperty()
def selected(self,filename):
try:
self.image_source = filename[0]
except:
pass
# Screen where the image is selected
class ImageSelector(Screen):
pass
# Display image & classification results
class ClassificationResultWindow(Screen):
pass
class MainApp(App):
def build(self):
self.image_selector = ImageSelector()
self.scan_result_window = ClassificationResultWindow()
if __name__ == "__main__":
MainApp().run()
And here is the main.kv
file
#:kivy 2.0.0
WindowManager:
ImageSelector:
ClassificationResultWindow:
<ImageSelector>:
name: "image_selector"
id: image_selector
BoxLayout:
orientation: 'vertical'
id: image_box
FileChooserListView:
id: filechooser
on_selection:
root.manager.selected(filechooser.selection)
print(root.manager.image_source)
size_hint: 1, 10
Image:
id: image
source: root.manager.image_source
size_hint: 1, 4
Button:
id: diagnose
text: "Classify"
on_release:
print(root.manager.image_source)
app.root.current = "classification_result"
<ClassificationResultWindow>:
name: "classification_result"
BoxLayout:
orientation: 'vertical'
id: box
Image:
id: scan
source: root.manager.image_source
size_hint: 1, 10
Label:
text: "Here comes the classification result"
font_size: 30
size_hint: 1, 2
id: label
I tried without success binding the property in different ways, but since I'm new to kivy I didn't know if it makes sense so I didn't include them here.
The way I handle passing information from one screen onto the other is by having the ScreenManager
hold properties, and have the Screen
access them.
Your main.py
file should now be:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty
class WindowManager(ScreenManager):
image_source = StringProperty()
def selected(self,filename):
try:
self.image_source = filename[0]
except:
pass
# Screen where the image is selected
class ImageSelector(Screen):
pass
# Display image & classification results
class ClassificationResultWindow(Screen):
pass
class MainApp(App):
pass
if __name__ == "__main__":
MainApp().run()
#:kivy 2.0.0
WindowManager:
ImageSelector:
ClassificationResultWindow:
<ImageSelector>:
name: "image_selector"
id: image_selector
BoxLayout:
orientation: 'vertical'
id: image_box
FileChooserListView:
id: filechooser
on_selection:
root.manager.selected(filechooser.selection)
size_hint: 1, 10
Image:
id: image
screen: image_selector
source: self.screen.manager.image_source
size_hint: 1, 4
Button:
id: diagnose
text: "Classify"
on_release:
app.root.current = "classification_result"
<ClassificationResultWindow>:
name: "classification_result"
id: classification_results
BoxLayout:
orientation: 'vertical'
id: box
Image:
id: scan
screen: classification_results
source: self.screen.manager.image_source
size_hint: 1, 10
Label:
text: "Here comes the classification result"
font_size: 30
size_hint: 1, 2
id: label
What is going on? So first a StringProperty
is created in the ScreenManager
. Bindings to these properties are automatically created and thus things referencing this property will update as it is changed.
Then the Image
class in each Screen
references this StringProperty
through root.manager.image_source
.
root
is the root widget,manager
is a property that each screen has which points it towards its parent ScreenManager
image_source
is the property we created earlier.Hope this helps. I have not tested the above, so there may be an error or two, but I think the general concept of having the ScreenManager
hold objects that Screen
's need to pass on to one another is how I solve this issue.