python - Kivy: 'NoneType' 对象不可调用,按钮删除时

标签 python kivy

我正在尝试使用 Kivy 用 Python 编写一个简单的界面,有 4 个元素:顶部的标题栏、底部的文本输入以及旁边的小按钮“添加”。在顶部和底部之间我想要一个 ScrollView ,当我们单击文本输入旁边的按钮时,它会在 ScrollView 中创建一个新按钮,并在它旁边有一个小按钮来删除该行(line = the按钮+其删除按钮) 要理解: what i want

当我点击“X”按钮删除时,出现错误:

 Traceback (most recent call last):
   File "nouv_test.py", line 39, in <module>
     RunApp().run()
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\app.py", line 828, in run
     runTouchApp()
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\base.py", line 504, in runTouchApp
     EventLoop.window.mainloop()
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\core\window\window_sdl2.py", line 663, in mainloop
     self._mainloop()
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\core\window\window_sdl2.py", line 405, in _mainloop
     EventLoop.idle()
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\base.py", line 342, in idle
     self.dispatch_input()
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\base.py", line 327, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\base.py", line 233, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\core\window\__init__.py", line 1192, in on_motion
     self.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\core\window\__init__.py", line 1228, in on_touch_up
     if w.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\screenmanager.py", line 1199, in on_touch_up
     return super(ScreenManager, self).on_touch_up(touch)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\widget.py", line 479, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\relativelayout.py", line 304, in on_touch_up
     ret = super(RelativeLayout, self).on_touch_up(touch)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\widget.py", line 479, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\widget.py", line 479, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\scrollview.py", line 833, in on_touch_up
     if self.dispatch('on_scroll_stop', touch):
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\scrollview.py", line 872, in on_scroll_stop
     self.simulate_touch_down(touch)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\scrollview.py", line 596, in simulate_touch_down
     ret = super(ScrollView, self).on_touch_down(touch)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\widget.py", line 457, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\widget.py", line 457, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
   File "C:\Users\dvfrg\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 718, in kivy._event.EventDispatcher.dispatch (kivy\_event.c:8191)
 TypeError: 'NoneType' object is not callable

这是我的代码(.py/.kv):

# coding: utf-8

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder


from kivy.uix.button import Button


class GUI(ScreenManager):
    def __init__(self, **kwargs):
        super(GUI, self).__init__(**kwargs)

class Home(Screen):

    def __init__(self, **kwargs):
        super(Home, self).__init__(**kwargs)

    def add_btn(self, grid):
        left = Button(text="added", size = (32, 32), size_hint = (1, None)) # the green button
        right = Button(background_color = (1,0,0,1), text="X", size = (32, 32), size_hint = (None, None)) # the red DELETE button

        right.on_press = self.del_btn(grid, left, right)

        grid.add_widget(left)
        grid.add_widget(right)

    def del_btn(self, grid, L, R): # function called when I click on delete a line
        grid.remove_widget(L)
        grid.remove_widget(R)

Builder.load_file("nouv_test.kv")

class RunApp(App):
    def build(self):
        return GUI()

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

.KV:

 #: kivy 1.10.0

    <GUI>:
        Home:
            name: "home_screen"
            id: home

    <Home>:

        GridLayout:
            rows: 3

            Button:
                text: u"Mes ann\u00e9es"
                size: (50, 50)
                size_hint: (1, None)
                background_color: (0,1,0,1)

            ScrollView:


                size_hint:(1, .8)
                pos_hint: {'center_x': 0.5, 'center_y': 0.5}
                do_scroll_x: False

                GridLayout:
                    id: home_scroll_grid
                    cols: 2
                    padding: 5
                    spacing: 5
                    height: self.minimum_height
                    size_hint: (1, None)


            BoxLayout:

                padding: 5
                spacing: 5
                size: (42, 42)
                size_hint: (1, None)

                TextInput:
                    size: (32, 32)
                    size_hint: (1, None)

                Button:
                    text: "+"
                    background_color: (0,1,0,1)
                    size: (32, 32)
                    size_hint: (None, None)
                    on_press: root.add_btn(home_scroll_grid)

最佳答案

您收到 NoneType 错误,因为在此语句中:right.on_press = self.del_btn(grid, left, right),您实际上调用了 del_btn ,它什么也不返回。
on_press 采用可调用函数,而不是被调用函数。所以它应该看起来像这样:right.on_press = self.del_btn

但是由于您需要将参数传递给回调,因此可以使用 partial
然后使用 .bind 而不是分配给 on_press。
像这样:

from functools import partial

然后:

right.bind(on_press=partial(self.del_btn, grid, left, right))

关于python - Kivy: 'NoneType' 对象不可调用,按钮删除时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47680463/

相关文章:

python - 具有绝对 URL 路径的 Django 压缩器和 clevercss

android - Kivy:AsyncImage 和 Urllib 不会在 Android 上打开任何 url

android - 在 Kivy 中引用另一个类的函数

android - 如何将 BoxLayout 定位到屏幕顶部

python - 使用 Builder.load_string 在 Kivy 应用程序上显示变量

python - 有没有办法同时评估两个案例,在 python 中大于和小于?

python - 在 google colab 中使用本地 jupyter 时出现问题

python - 如何使基维线一致地绘制

python - 如何在 contourf 的色标中设置最大值和最小值?

python - 使用 cherrypy (python 2) 禁用弱密码