Python 使用on_touch_down()替换Kivy中的小部件/布局

Python 使用on_touch_down()替换Kivy中的小部件/布局,python,kivy,Python,Kivy,好的,我有一个程序,在某些条件下,需要删除一些选项,并提供一些其他选项。我最初设计它是为了让某些按钮占据相同的空间。但是,当触发on touch down()时,我编写的预期开关不会交换布局 from kivy.uix.widget import Widget from kivy.config import Config from kivy import graphics from kivy.uix.button import Button from SpotChess import SCBoa

好的,我有一个程序,在某些条件下,需要删除一些选项,并提供一些其他选项。我最初设计它是为了让某些按钮占据相同的空间。但是,当触发on touch down()时,我编写的预期开关不会交换布局

from kivy.uix.widget import Widget
from kivy.config import Config
from kivy import graphics
from kivy.uix.button import Button
from SpotChess import SCBoardWidget
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.relativelayout import RelativeLayout

promote_now = False

class Chessboard(Widget):
    def __init__(self, **kwargs):
        super(Chessboard, self).__init__(**kwargs)
        self.bind(pos=self.drawBoardandPieces)
        self.bind(size=self.drawBoardandPieces)
        self.drawBoardandPieces()

    def drawBoardandPieces(self, *args):
        with self.canvas:
            # Reset the canvas in case of redraws.
            self.canvas.clear()
            # Define the lengths of the edges of the squares.
            edge_len = min(self.height, self.width) // 8
            Config.set("graphics", "resizable", True)
            for column in range(0, 8):
                for row in range(0, 8):
                    if ((row + column) % 2) == 0:
                        graphics.Color(0, 0, 1)
                        self.dark_rect = graphics.Rectangle(pos=(column*edge_len, row*edge_len),
                                                            size=(edge_len, edge_len))
                    else:
                        graphics.Color(1, 1, 1)
                        self.light_rect = graphics.Rectangle(pos=(column*edge_len, row*edge_len),
                                                             size=(edge_len, edge_len))

    # This provides all of the user's mouse interaction with the board.
    def on_touch_down(self, touch):
        global promote_now
        if promote_now == False:
            promote_now = True
            Options().swapMenus()
        else:
            promote_now = False
            Options().swapMenus()

game_board = Chessboard()

class PromotionOptions(GridLayout):
    def __init__(self, **kwargs):
        super(PromotionOptions, self).__init__(**kwargs)
        self.cols = 4

        self.queen_btn = Button(text="Q/q")
        self.rook_btn = Button(text="R/r")
        self.bishop_btn = Button(text="B/b")
        self.knight_btn = Button(text="N/n")

        self.add_widget(self.queen_btn)
        self.add_widget(self.rook_btn)
        self.add_widget(self.bishop_btn)
        self.add_widget(self.knight_btn)

class Options(GridLayout):
    def __init__(self, **kwargs):
        super(Options, self).__init__(**kwargs)
        self.cols = 1
        self.swapMenus()

    def swapMenus(self):
        global promote_now
        self.clear_widgets()
        if promote_now == False:
            # Present the menu layout for normal play.
            self.normal_play_menu = GridLayout(cols=3)
            # It contains the button to flip the board.
            self.flip_board_btn = Button(text="Flip")
            self.normal_play_menu.add_widget(self.flip_board_btn)
            self.add_widget(self.normal_play_menu)
        else:
            # Present the menu layout for pawn promotions.
            self.promotion_menu = GridLayout(cols=1)
            self.promotion_menu.add_widget(widget=PromotionOptions())
            self.add_widget(self.promotion_menu)

class SCApp(App):
    def build(self):
        top_portion = BoxLayout(orientation="vertical")
        chessboard_portion = RelativeLayout()
        chessboard_portion.add_widget(widget=game_board)
        top_portion.add_widget(widget=chessboard_portion)
        bottom_portion = BoxLayout(orientation="vertical")
        bottom_portion.add_widget(widget=Options())
        app_layout = BoxLayout(orientation="vertical")
        app_layout.add_widget(top_portion)
        app_layout.add_widget(bottom_portion)
        return app_layout

SCApp().run()

我显然是在调用对象来执行替换,但它既没有完成
self.clear\u widgets()
也没有完成
self.add\u widget()
,即使我调用了函数。我缺少什么?

在您的
on\u touch\u down()方法中

Options().swapMenus()
行正在创建
Options
类的新实例,并调用该新实例的
swapMenus()
方法。但是
Options
的新实例不在您的GUI中,因此它对您的应用程序没有影响。您需要获取对GUI中的
选项
实例的引用,并调用该实例的
swapMenus()
方法

您可以通过在
应用程序中保存对
选项
类的引用,并在
build()
方法中替换此行来完成此操作:

    bottom_portion.add_widget(widget=Options())
def on_touch_down(self, touch):
    global promote_now
    
    # get the instance of Options that is in the App
    options = App.get_running_app().options
    
    if promote_now == False:
        promote_now = True
        options.swapMenus()
    else:
        promote_now = False
        options.swapMenus()
与:

然后在
on\u触摸下()
方法中:

    bottom_portion.add_widget(widget=Options())
def on_touch_down(self, touch):
    global promote_now
    
    # get the instance of Options that is in the App
    options = App.get_running_app().options
    
    if promote_now == False:
        promote_now = True
        options.swapMenus()
    else:
        promote_now = False
        options.swapMenus()

这也是我最后发现的。我通过创建一个全局
options
变量解决了这个问题,该变量只是该类的一个副本。
App.get\u running\u App().widget\u name
是否偶然节省了计算时间?不,全局变量可能更快。