簡體   English   中英

Python Kivy - 跨不同調用方法 class

[英]Python Kivy - Call methods across different class

我是編碼新手,與 Python 一起工作了幾個月,並試圖全神貫注於 Kivy。我認為對此有一個簡單的解決方案,但在從另一個 class 中調用方法時,我很掙扎。 甚至不確定這是否可能,我的 OOP 不會很強!!

如果有人能向我解釋這一點,我將不勝感激。 我在網上看過,但仍在努力了解我需要做什么。

我有一個簡單的代碼,它有一個 label 和 3 個切換按鈕,label 文本更改以顯示按下了多少個切換按鈕。 下面是原始代碼。

我想要做的是使用循環創建切換按鈕,以便可以輕松更改切換按鈕的數量。 我已經實現了這一點,但是當我嘗試將該方法綁定到切換按鈕時,代碼失敗了。 我還嘗試在“Tbtn”class 中定義一個方法來調用 Main.Counter(),但這也不起作用。

線路

    self.bind(on_state = Main.counter())

我認為在切換按鈕的初始部分是我出錯的地方。

任何幫助甚至解釋都會很棒。 這不是我第一次被困在這上面了!! 謝謝

原始代碼:

from kivy.app import App
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty

class Tbtn(ToggleButton):
    pass

class Header_Box(BoxLayout):
    pass

class Counter(BoxLayout):
    pass

class Main(BoxLayout):
    count = NumericProperty()

    def counter(self,widget):
        toggles = []
        for child in self.ids.Seat_Box.children:
            if isinstance(child, ToggleButton):
                if child.state == 'down':
                    toggles.append(child.text)
        self.count = len(toggles)
        print(self.count)


class TestApp(App):
    def build(self):
        return Main()

TestApp().run()

KV文件:

<Main>:
    name: "main"
    BoxLayout:

        orientation: "vertical"
        Header_Box:
            Label:
                text: str(root.count)

        Counter:
            id: Seat_Box            
            Tbtn:
                id: btn1
                on_state: root.counter(self)
            Tbtn:
                id: btn2
                on_state: root.counter(self)
            Tbtn:
                id: btn2
                on_state: root.counter(self)

使用 for 循環的代碼:

from kivy.app import App
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty

class Tbtn(ToggleButton):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.bind(on_state = Main().counter())

class Header_Box(BoxLayout):
    pass

class Counter(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        for x in range(3):
            btn = Tbtn()
            self.add_widget(btn)

class Main(BoxLayout):
    count = NumericProperty()

    def counter(self,widget):
        toggles = []
        for child in self.ids.Seat_Box.children:
            if isinstance(child, ToggleButton):
                if child.state == 'down':
                    toggles.append(child.text)
        self.count = len(toggles)
        print(self.count)


class TestApp(App):
    def build(self):
        return Main()

TestApp().run()

KV文件:

<Main>:
    name: "main"
    BoxLayout:

        orientation: "vertical"
        Header_Box:
            Label:
                text: str(root.count)

        Counter:
            id: Seat_Box      

首先,刪除self.bind(on_state = Main().counter())

我建議你解決這個 in.kv 方面。

方式 1-.kv 端:在您的 .kv 文件下方添加:

<Tbtn>:
    on_state: app.get_running_app().root.counter(self)

Way 2-.py side:在Tbtn class中添加這個。

def on_release(self):
    App.get_running_app().root.counter(self)

雖然其他答案已經解決了您的問題,但以下內容讓我發布了這個問題。

任何幫助甚至解釋都會很棒......

從技術上講,以下行,

self.bind(on_state = Main().counter())

由於各種原因是錯誤的。 讓我們試着弄清楚這一點。

on_state方法是一種通用方法,不是默認事件(如on_press等)。 這就是為什么bind(on_state = some_callback)不起作用的原因。

您再次執行Main().counter() ,它實際上創建了Main的一個新實例(它可能與root相關,也可能不相關,這里當然不是)並分配給它的方法。

您似乎只想訪問Main小部件(恰好是此處的root小部件)方法之一。

由於您使用kvlang ,因此可以按如下方式更有效地完成此操作,

<Tbtn>:
    on_state: app.root.counter()

您可以在kvlang文檔中找到更多相關信息。

現在在.py中,您只需定義 class 以及其他一些更改,

class Tbtn(ToggleButton):
    pass
.
.
.
class Main(BoxLayout):
    count = NumericProperty()

    def counter(self): # Pass no extra args as you haven't done in 'on_state' method.
        toggles = []
        .
        .
        .

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM