Genaro.exe
Genaro.exe

Reputation: 38

Popup can have only one widget as content

I work on a kivy interface. I try to implement a popup but when I press the button that should fire the popup I get the error kivy.uix.popup.PopupException: Popup can have only one widget as content (full console logs below).

The minimal reproducible example I prepared consists of 3 files; main.py, my.kv, and mygrid.py.

How can I achieve that pressing the button triggers the popup without altering the architecture of the modules?

my.kv

Contains the structure of <GridLayout> (green section) and <ScrollView> (blue section)

<ScrollView>:
    canvas:
        Color:
            rgb: 0, 0, 1
        Rectangle:
            pos: self.pos
            size: self.size

<GridLayout>:
    canvas:
        Color:
            rgb: 0, 1, 0
        Rectangle:
            pos: self.pos
            size: self.size

    cols:1
    size: root.width, root.height

    Button:
        width: root.width
        text: "Submit"
        on_press:root.SendButton()
        size_hint: 1, None

mygrid.py

Contains the logic regarding <GridLayout>. In the example case, it only decides when to fire a popup

from kivy.uix.gridlayout import GridLayout

class MyGrid(GridLayout):
    def SendButton(self):
        from main import myApp
        myApp().show_popup()

main.py

Run the application

Full console logs:

PS C:\Users\EXO\Desktop\mre>  & 'C:\Users\EXO\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\EXO\.vscode\extensions\ms-python.python-2022.10.1\pythonFiles\lib\python\debugpy\adapter/../..\debugpy\launcher' '51462' '--' 'c:\Users\EXO\Desktop\mre\main.py'
[INFO   ] [Logger      ] Record log in C:\Users\EXO\.kivy\logs\kivy_22-07-29_14.txt
[INFO   ] [deps        ] Successfully imported "kivy_deps.angle" 0.3.2
[INFO   ] [deps        ] Successfully imported "kivy_deps.glew" 0.3.1 
[INFO   ] [deps        ] Successfully imported "kivy_deps.sdl2" 0.4.5 
[INFO   ] [Kivy        ] v2.1.0
[INFO   ] [Kivy        ] Installed at "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\_
_init__.py"
[INFO   ] [Python      ] v3.10.5 (tags/v3.10.5:f377153, Jun  6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)]
[INFO   ] [Python      ] Interpreter at "C:\Users\EXO\AppData\Local\Programs\Python\Python310\python.exe"
[INFO   ] [Logger      ] Purge log fired. Processing...
[INFO   ] [Logger      ] Purge finished!
[INFO   ] [Factory     ] 189 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2 (img_pil, img_ffpyplayer ignored)
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [Window      ] Activate GLES2/ANGLE context
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] Backend used <angle_sdl2>
[INFO   ] [GL          ] OpenGL version <b'OpenGL ES 3.0.0 (ANGLE 2.1.17461 git hash: b790affce32e)'>
[INFO   ] [GL          ] OpenGL vendor <b'Google Inc. (Intel)'>
[INFO   ] [GL          ] OpenGL renderer <b'ANGLE (Intel, Intel(R) HD Graphics 3000 Direct3D11 vs_4_1 ps_4_1, D3D11-
9.17.10.4459)'>
[INFO   ] [GL          ] OpenGL parsed version: 3, 0
[INFO   ] [GL          ] Shading version <b'OpenGL ES GLSL ES 3.00 (ANGLE 2.1.17461 git hash: b790affce32e)'>       
[INFO   ] [GL          ] Texture max size <8192>
[INFO   ] [GL          ] Texture max units <16>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available
[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "c:\Users\EXO\Desktop\mre\main.py", line 36, in <module>
     myApp().run()
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\app.py", line 955, in run
     runTouchApp()
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\base.py", line 574, in runTouchApp        
     EventLoop.mainloop()
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\base.py", line 339, in mainloop
     self.idle()
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\base.py", line 383, in idle
     self.dispatch_input()
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\base.py", line 334, in dispatch_input     
     post_dispatch_input(*pop(0))
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\base.py", line 263, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\core\window\__init__.py", line 1664, in on_motion
     self.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\core\window\__init__.py", line 1701, in on_touch_up
     if w.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\scrollview.py", line 968, in on_touch_up
     if self.dispatch('on_scroll_stop', touch):
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\scrollview.py", line 1005, in on_scroll_stop
     self.simulate_touch_down(touch)
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\scrollview.py", line 668, in simulate_touch_down
     ret = super(ScrollView, self).on_touch_down(touch)
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\widget.py", line 589, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\widget.py", line 589, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1191, in kivy._event.EventObservers._dispatch
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\lang\builder.py", line 55, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "c:\Users\EXO\Desktop\mre\my.kv", line 23, in <module>
     on_press:root.SendButton()
   File "c:\Users\EXO\Desktop\mre\mygrid.py", line 6, in SendButton
     myApp().show_popup()
   File "c:\Users\EXO\Desktop\mre\main.py", line 32, in show_popup
     p = CustomPopup()
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\modalview.py", line 195, in __init__  
     super(ModalView, self).__init__(**kwargs)
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\anchorlayout.py", line 68, in __init__
     super(AnchorLayout, self).__init__(**kwargs)
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\layout.py", line 76, in __init__      
     super(Layout, self).__init__(**kwargs)
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\widget.py", line 366, in __init__     
     self.apply_class_lang_rules(
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\widget.py", line 470, in apply_class_lang_rules
     Builder.apply(
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\lang\builder.py", line 540, in apply      
     self._apply_rule(
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\lang\builder.py", line 659, in _apply_rule
     widget.add_widget(child)
   File "C:\Users\EXO\AppData\Local\Programs\Python\Python310\lib\site-packages\kivy\uix\popup.py", line 216, in add_widget    
     raise PopupException(
 kivy.uix.popup.PopupException: Popup can have only one widget as content
PS C:\Users\EXO\Desktop\mre> 

Upvotes: 0

Views: 215

Answers (1)

John Anderson
John Anderson

Reputation: 38962

The problem is your code:

def SendButton(self):
    from main import myApp
    myApp().show_popup()

The import here causes the Builder.load_string() in main.py to be executed a second time (the first was when you ran the App). And that second execution causes the <CustomPopup> rule to be loaded twice which results in the CustomPopup rule trying to put two Buttons in the Popup, and trigger the error message.

Also, this is creating another instance of myApp (myApp() always creates a new instance). And then calls the show_popup() method of that new instance. A better approach is to not do an import in the SendButton() method, and just call the show_popup() method of the running App. Like this:

from kivy.uix.gridlayout import GridLayout
from kivy.app import App

class MyGrid(GridLayout):
    def SendButton(self):
        App.get_running_app().show_popup()

This code gets the currently running App and calls its show_popup() method without importing anything from main.py.

Upvotes: 1

Related Questions