Search code examples
pythonimagekivyfilechooser

How to set file selected by tkinter filechooser (image) as the source to a Kivy image widget?


I'm currently learning Kivy, I'm using tkinter filechooser to browse for images stored on my computer and want the selected image to be set as the source of the Images widget.

The code below launches the tkinter filechooser on button click, how should I go about to set the obtained file as source for my image widgets. Thank you for your time.

main.py

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.popup import Popup
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty

from tkinter.filedialog import askopenfilename
from tkinter import Tk

class SampBoxLayout(BoxLayout):
# Defines two FileChoosers.

    def get_image_one(self):
        # Select image file types, returned image should be used as source of Image widget.
        Tk().withdraw() # avoids window accompanying tkinter FileChooser
        img1 = askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
        return img1

    def get_image_two(self):
        Tk().withdraw()
        img2 = askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
        return img2

class SampleApp(App):
    def build(self):
        # Set the background color for the window
        Window.clearcolor = (1, 1, 1, 1)
        return SampBoxLayout()

sample_app = SampleApp()
sample_app.run()

sample.kv

#: import CheckBox kivy.uix.checkbox

<ColoredBackground@Image>:
    font_size: '48sp'
    color: (.9, .5, .4, 1)
    canvas.before:
        Color:
            rgb: (.9, .9, .9)
        Rectangle:
            pos: self.x + sp(2), self.y + sp(2)
            size: self.width - sp(5), self.height - sp(4)

<SampBoxLayout>:
    orientation: "vertical"
    padding: 10
    spacing: 10

    # ---------- Button FileChooser ----------
    BoxLayout:
        orientation: "horizontal"
        height: 30

        Button:
            text: "FileChooser-1"
            on_press: root.get_image_one()

        Button:
            text: "FileChooser-2"
            on_press: root.get_image_two()

    # ---------- Display Images----------
    BoxLayout:
        orientation: "horizontal"
        height: 30

        ColoredBackground:
            source: " " # <----------- should be the image file selected by FileChooser-1
            size: self.parent.width, self.parent.height
            allow_stretch: True
            keep_ratio: False

        ColoredBackground:
            source: " " # <----------- should be the image file selected by FileChooser-2
            size: self.parent.width, self.parent.height
            allow_stretch: True
            keep_ratio: False

Solution

  • The solution is that the ColoredBackground are accessible in get_image_one and get_image_two for it we do properties:

    *.kv

    ...
    <SampBoxLayout>:
        first_image: first_image     # <----
        second_image: second_image   # <----
        orientation: "vertical"
        padding: 10
        spacing: 10
    
        # ---------- Button FileChooser ----------
        BoxLayout:
            ...
    
        # ---------- Display Images----------
        BoxLayout:
            orientation: "horizontal"
            height: 30
    
            ColoredBackground:
                id: first_image  # <----
                size: self.parent.width, self.parent.height
                allow_stretch: True
                keep_ratio: False
    
            ColoredBackground:
                id: second_image  # <----
                size: self.parent.width, self.parent.height
                allow_stretch: True
                keep_ratio: False
    

    *.py

    def get_image_one(self):
        # Select image file types, returned image should be used as source of Image widget.
        Tk().withdraw() # avoids window accompanying tkinter FileChooser
        img = askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
        self.first_image.source = img
    
    def get_image_two(self):
        Tk().withdraw()
        img = askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
        self.first_image.source = img