1

I'm trying to create this functionality that when a physical button is pressed a function is called that if true opens a popup on the main Kivy screen. The idea was to have the display showing the menu but when an external function calls it opens the popup. To make both the waiting for the press of the button and the display work at the same time I went with threading but when I press the button Kivy gives:

TypeError: Cannot create graphics instruction outside the main Kivy thread.

I spent the last couple of nights trying to find a solution online but I did not come across any. Here's the python code:

from gpiozero import Button, DigitalOutputDevice
from time import sleep
from threading import Thread
#kivy imports
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.metrics import dp
from kivy.factory import Factory
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import Clock

hatch_btn = Button(20, bounce_time=0.2)

value = 6
x = 2
def function():
    if value >x:
        P.show_popup()

class P(FloatLayout):
    def show_popup():
        show = P()
        popupWindow = Popup(title='Popup Window', content=show, 
                size_hint=(None,None),auto_dismiss=False, size=(400,400))
        popupWindow.open()

class MainMenu(Screen):
    pass
    

class displayApp(App):
    def build(self):
        return MainMenu()
    

def btn_loop():
    while True:
        if hatch_btn.is_pressed:
            print('pressed')
            sleep(1)
            function()

        else:
            print('not pressed')
            sleep(0.2)


thread = Thread(target=btn_loop)
thread.start()


if __name__ == '__main__':
    displayApp().run()

And the kv file:

#kivy 2.0.0

#:import Factory kivy.factory.Factory
MainMenu:
<MainMenu>:
    BoxLayout:
        orientation:'vertical'
        BoxLayout:
            size_hint:1,0.2
            Label:
                size_hint: 0.3,1
                text:'Logo'
            Label:
                text:'Title'
        
        BoxLayout:
            padding: 50
            Button:
                text:'sup'
            Button:
                text:'sup'
            Button:
                text:'sup'
            Button:
                text:'sup'

<P>:
    Label:
        text:'popup from physical input'
        size_hint: 0.6, 0.2
        pos_hint: {'x':0.2, 'top':1}
    Button:
        text: 'wish I could see the popup open...'
        size_hint:0.8, 0.2
        pos_hint: {'x':0.1,'y':0.1} 

Is there any other way around this? I read something about using kivy.clock but I did not really understand it as I am a novice in both python and kivy. I also saw from the kivy docs that you can create a popup like this directly in the kv file; if there is a way with this method it would be even better because I'm trying to keep the graphical part separate.

#:import Factory kivy.factory.Factory
<MyPopup@Popup>:
    auto_dismiss: False
    Button:
        text: 'Plz help:(!'
        on_release: root.dismiss()

Button:
    text: 'Open popup'
    on_release: Factory.MyPopup().open()

1 Answer 1

1

there is a decorator available for that

from kivy.clock import mainthread

and then on the method

@mainthread
def show_popup(self, *args, **kwargs):
    # it is possible that changing to this structure will
    # negate the need for the mainthread decorator
    _popup=Popup()  # naturally, fill in the details inside ()
    _popup.open()

However, you may have other things to change.

I have never tried using Factory method inside the .kv file so I think you should try one of these two.

Button:
    text: 'Open popup'
    # create the popup within these methods
    on_release: root.show_popup()
    # or
    on_release: app.show_popup()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.