在吉维继续运行在启动

2024-09-30 04:33:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我遇到了一个问题,即应用程序在其他任何事情发生之前立即运行按钮的on-unu-press命令。如果我用一个.kv的布局,它工作得很好,但我想能够管理按钮使用一个简单的列表。在

class AppBase(Widget):

    def Launcher(self, launchapp):
        os.system(launchapp)

    def BuildLayout(self):
        layout = GridLayout( rows=4, row_force_default = True, row_default_height = 100, col_force_default = True, col_default_width = 300 )
        with open('config.txt', 'rb') as f:
            reader = csv.reader(f, delimiter="|")
            for row in reader:
                launchbutton = Button( text = row[0], background_normal = 'tile.png', on_press = self.Launcher(row[1]) )
                layout.add_widget(launchbutton)
        return layout


class MyApp(App):

    def build(self):
        Config.set('graphics', 'width', 1920)
        Config.set('graphics', 'height', 400)
        return AppBase().BuildLayout()

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

Tags: selfdefaultondef按钮classreaderrow
1条回答
网友
1楼 · 发布于 2024-09-30 04:33:04

您没有将回调传递到Button,而是在此时实际执行该函数。更改此项:

^{1}$

为此:

^{pr2}$

现在传递一个未命名的函数,该函数将在on_press事件时调用self.Launcher,而不是在创建Button时将其设置为self.Launcher的返回结果。在

更新:由于某些原因,on_press和{}事件实际上并没有分配给Button.__init__中的回调,事件本身只是注册而没有结果。(这在我看来是一个bug,但我对Kivy还不太熟悉,不能肯定地说。)您需要显式地bind回调才能正常工作:

launchbutton = Button( text = row[0], background_normal = 'tile.png' )
launchbutton.bind( on_press = lambda widget: self.Launcher( row[1] ) )

注意,回调实际上接收一个参数,我在lambda中以widget的形式包含了该参数。在

更新2:我应该早点发现这个,抱歉,但是我已经将我的本地测试用例减少到一个按钮。在循环中执行此操作时:

funcs = []
for x in xrange(10):
    funcs.append( lambda: x)

每次调用funcs[n](),其中n in [0..9]都将返回9,而不是预期的{}的值。lambda已经创建了一个闭包,它包含来自周围范围的x。但是,x的值在循环过程中会发生变化,到最后它是9。现在,funcs中的所有lambda都持有对9的引用。可以通过向lambda的局部作用域添加所需的来避免这种情况:

    funcs.append( lambda x=x: x)

这会将lambda局部变量x指向外部作用域中循环变量x所引用的同一对象。如果我们使用不同的变量名,情况会更明显:

    funcs.append( lambda inner_x=x: inner_x)

但是x=x形式在这种情况下非常常见。因此,为了确保每个按钮使用正确的值,您应该能够执行以下操作:

launchbutton.bind( on_press = lambda widget, appname=row[1]: self.Launcher( appname ) )

在这里,您将当前值row[1]绑定到lambda局部作用域中的appname,因此当调用它时,它将传递给Launcher。在

相关问题 更多 >

    热门问题