网格布局内的按钮问题 网格布局内的按钮问题

Problem with buttons inside grid layout inside grid layout

提问人:DR4NKR1D3R 提问时间:8/14/2022 更新时间:8/15/2022 访问量:121

问:

你能帮我解决按钮问题吗? 我的布局如下所示(图 1): BoxLayout->GridLayout->GridLayout->Button(x9)

我的问题是我无法更改其他子网格中按钮的文本。看看我这样做的想法:

类:

class SmallGrid(GridLayout):
    buttons = []
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        for i in range(0, 9):
            obj = SudokuButton()
            self.buttons.append(obj)
            self.add_widget(obj)


class BigGrid(GridLayout): 
    small_grids = []
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        for i in range(0, 9):
            obj = SmallGrid()
            self.grids.append(obj)
            self.add_widget(obj)   

我的主类/伪代码的一小部分:

big_grid = BigGrid()

for i in range(0, 9):
            for j in range(0, 9):
                self.big_grid.small_grids[i].buttons[j].text = ...

我可以访问其他 SmallGrid() layous 和他们的按钮,但看起来 SmallGrids() 在同一个地方,但它们的按钮在它们预定的位置。

完整的代码在这里(如果你想尝试你的想法):

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.graphics import Rectangle
from kivy.graphics import Color
from kivy.graphics.vertex_instructions import Line
from kivy.properties import NumericProperty, ObjectProperty, StringProperty
from kivy.metrics import dp
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.config import Config

import random


class KivySudokuApp(App):
    def build(self):
        return Sudoku()


class SmallGrid(GridLayout):
    buttons = []
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        for i in range(0, 9):
            obj = SudokuButton()
            self.buttons.append(obj)
            self.add_widget(obj)


class BigGrid(GridLayout): 
    grids = []
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        for i in range(0, 9):
            obj = SmallGrid()
            self.grids.append(obj)
            self.add_widget(obj)       

class MenuWidget(RelativeLayout):
    pass   
    
        
class Sudoku(BoxLayout):
    original_board = [[0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0]]
    
    player_board = [[0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0]]
    
    
    useable_values = numberList=[1, 2, 3, 4, 5, 6, 7, 8, 9]  
    
    seconds_passed = 0
    minutes_passed = 0
    
    last_key = ""
    
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
        self.orientation = 'vertical'
        
        self.title = Label(text = "KivySudoku",
                           font_size = self.height * 0.5,
                           font_name = "label_font.ttf",
                           color = (0, 0.25, 0.3, 1),
                           bold = True,
                           size_hint = (1, 0.1))
        
        self.timer = Label(font_size = self.height * 0.2,
                           font_name = "label_font.ttf",
                           color = (0, 0.25, 0.3, 1),
                           bold = True,
                           size_hint = (1, 0.05))
        
        self.number = Label(font_size = self.height * 0.2,
                           font_name = "label_font.ttf",
                           color = (0, 0.25, 0.3, 1),
                           bold = True,
                           size_hint = (1, 0.05))
        
        self.menu = MenuWidget()
        self.add_widget(self.menu)
        
        self._keyboard = Window.request_keyboard(self.keyboard_closed, self)
        self._keyboard.bind(on_key_down=self.on_key_down)
        
        Clock.schedule_interval(self.update, 1/60)


    def on_key_down(self, keyboard, keycode, text, modifiers):
        for i in range(1, 10):
            if keycode[1] == str(i):
                self.last_key = str(i)
        return True
    
    
    def keyboard_closed(self):
        self._keyboard.unbind(on_key_down = self.on_key_down)
        self._keyboard = None
    
    
    def original_board_init(self):
        for i in range(0, 81):
            row = int(i/9)
            col = i%9
            if self.original_board[row][col] == 0:
                random.shuffle(self.useable_values)      
                for value in self.useable_values:
                    if self.value_check(row, col, value):
                        self.original_board[row][col] = value
                        if self.is_full(self.original_board):
                            return True
                        else:
                            if self.original_board_init():
                                return True
                break
        self.original_board[row][col] = 0  
        
    
    def player_board_init(self, to_del):
        self.player_board = self.original_board
        
        to_remove = random.sample(range(0, 81), to_del)
        
        for i in to_remove:
            row = int(i/9)
            col = i%9  
            self.player_board[row][col] = ""
        
        for i in range(0, 9):
            for j in range(0, 9):
                self.grid.grids[i].buttons[j].text = str(self.player_board[i][j])
#                if self.grid.grid1.buttons[j].text == "":
#                    self.grid.grid1.buttons[j].disabled = True


    def solve_board(self):
        for i in range(0, 81):
            row = int(i/9)
            col = i%9
            if self.original_board[row][col] == 0:
                for value in range(1,10):
                    if self.value_check(row, col, value):
                        self.original_board[row][col] == value
                        self.solve_board()
                        self.original_board[row][col] = 0
                return False     
            

    def is_full(self, board):
        for row in range(0, 9):
            for col in range(0, 9):
                if board[row][col] == 0:
                    return False
        return True
                    
                    
    def value_check(self, row, col, value):
        R = int(row/3) * 3
        C = int(col/3) * 3
        
        for i in range(0, 9):
            if self.original_board[i][col] == value:
                return False
            for j in range(0, 9):
                if self.original_board[row][j] == value:
                    return False
        for i in range(R, R + 3):
            for j in range(C, C + 3):
                if value == self.original_board[i][j]:
                    return False
        return True

                
    def update(self, dt):
        self.seconds_passed += dt
        self.number.text = "Enter number: " + str(self.last_key)
        
#        for i in range(0, 9):
#            for j in range(0, 9):
#                self.grid.big_grid.small_grids[i].buttons[j].last_key = self.last_key
         
        self.update_time()
        
        
    def update_time(self):
        if self.seconds_passed > 60:
            self.seconds_passed -= 60
            self.minutes_passed += 1
            
        seconds = str(format(int(self.seconds_passed), '02'))
        minutes = str(format(self.minutes_passed, '02'))
        
        self.timer.text = "Time: " + minutes + ":" + seconds
        
        
    def easy_button(self):
        self.switch_menu() 
        self.player_board_init(31)    
        
        
    def medium_button(self):
        self.switch_menu()
        self.player_board_init(51) 
        
        
    def hard_button(self):
        self.switch_menu()
        self.player_board_init(61) 
        
    
    def switch_menu(self):
        self.seconds_passed = 0
        self.minutes_passed = 0
        
        self.original_board_init()
        
        self.remove_widget(self.menu)
        
        self.grid = BigGrid()
        self.grid.pos_hint = {"center_x": 0.5, "center_y:": 0.5}
        
        self.add_widget(self.title)
        self.add_widget(self.timer)
        self.add_widget(self.number)
        self.add_widget(self.grid)
        
              
class SudokuButton(Button):
    last_key = ""
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
        self.background_normal = ""
        self.background_color = (0.2, 0.2, 0.2)
    
        
    def on_press(self):
        if self.last_key != "":
            self.text = self.last_key
        return super().on_press()


KivySudokuApp().run()

kivysudoku.kv 文件:

#:kivy 2.1.0

Sudoku:
<Sudoku>:
    canvas.before:
        Color:
            rgba: [0.1, 0.1, 0.1, 1]
        Rectangle:
            pos: self.pos
            size: self.size    

<BigGrid>:
    cols: 3
    size_hint: (None, 0.8)  
    width: self.height  
    spacing: 4  
    padding: 8  
    canvas.before:
        Color:
            rgba: [0, 0.25, 0.3, 1]
        Rectangle:
            pos: self.pos
            size: self.size    

<SmallGrid>:
    cols: 3
    spacing: 1
    canvas.before:
        Color:
            rgba: [0, 0.25, 0.3, 1]  
        Rectangle:
            pos: self.pos
            size: self.size    

<MenuWidget>:
    canvas.before:
        Color:
            rgba: 0.1, 0.1, 0.1
        Rectangle:
            size: self.size
    Label:
        text: "difficuty"
        color: 0, 0.35, 0.4, 1
        font_size: self.height * 0.8
        font_name: "label_font.ttf"
        pos_hint: { "center_x": .5, "center_y": 0.8}
        size_hint: 0.4, 0.15
    Button:
        color: 0, 0.25, 0.3, 1
        background_color: 0.95 ,0.95, 0.95, 0.8
        font_size: self.height * 0.8
        font_name: "label_font.ttf"
        text: "easy"
        pos_hint: { "center_x": .5, "center_y": 0.6}
        size_hint: 0.4, 0.15
        on_press: root.parent.easy_button()
        background_normal: ""
    Button:
        color: 0, 0.25, 0.3, 1
        background_color: 0.95 ,0.95, 0.95, 0.8
        font_size: self.height * 0.8
        font_name: "label_font.ttf"
        text: "medium"
        pos_hint: { "center_x": .5, "center_y": 0.4}
        size_hint: 0.4, 0.15
        on_press: root.parent.medium_button()
        background_normal: ""
    Button:
        color: 0, 0.25, 0.3, 1
        background_color: 0.95 ,0.95, 0.95, 0.8
        font_size: self.height * 0.8
        font_name: "label_font.ttf"
        text: "hard"
        pos_hint: { "center_x": .5, "center_y": 0.2}
        size_hint: 0.4, 0.15
        on_press: root.parent.hard_button()
        background_normal: ""
python-3.x kivy

评论


答:

0赞 John Anderson 8/15/2022 #1

问题在于您对 和 使用了类变量。你真的需要它们成为实例变量。只需将您的定义稍微更改为:gridsbuttons

class BigGrid(GridLayout):
    # grids = []

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.grids = []

        for i in range(0, 9):
            obj = SmallGrid()
            self.grids.append(obj)
            self.add_widget(obj)

class SmallGrid(GridLayout):
    # buttons = []

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.buttons = []

        for i in range(0, 9):
            obj = SudokuButton()
            self.buttons.append(obj)
            self.add_widget(obj)

评论

0赞 DR4NKR1D3R 8/15/2022
哇,非常感谢。我在这个问题上浪费了一整天。你花了多长时间才看到这一点?