Python 扫雷游戏gtk3 点击后获取按钮值

Python minesweeper game gtk3 get button value after click

我使用 Gtk3 在 Python 2.7 中编写简单的扫雷游戏。使用 set_sensitive(False).

单击后,标签的显示值出现问题

第一种情况,我在点击后使用 button.hide(),效果很好,标签值显示出来了。

M - 船上有地雷

但我不想使用 hide()。单击 set_sensitive() 属性 后,我想阻止按钮。我尝试在 discover 函数 return self.button.set_sensitive(False) 中执行此操作,但之后我没有获得任何按钮值。我点击了所有板,所有按钮都被禁用。为什么我没有得到标签的任何价值?

使用后的板子set_sensitive(False)

我的代码:

import gi
from random import randrange

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk


class SaperButton(Gtk.Button):
    def __init__(self):
        Gtk.Button.__init__(self)
        self.set_size_request(50, 50)


class Cell:
    def __init__(self):
        self.mine = False
        self.neighbormines = 0
        self.button = SaperButton()

    def place_mine(self):
        self.mine = True

    def is_mine(self):
        return self.mine

    def discover(self):
        print 'discover'
        # with hide showing values of label
        # with return self.button.set_sensitive(False) don't show
        return self.button.hide()

    def is_discovered(self):
        return not self.button.get_visible()

    def set_nighbromines(self, number):
        self.neighbormines = number

    def get_nighbromines(self):
        return self.neighbormines

    def get_button(self):
        return self.button


class SaperGrid(Gtk.Grid):
    def __init__(self, rows, cols, ratio):
        self.rows = rows
        self.cols = cols
        self.cells = []
        self.ratio = ratio
        Gtk.Grid.__init__(self)

        for row in range(rows):
            for col in range(cols):
                cell = Cell()
                self.cells.append(cell)
                self.attach(cell.get_button(), row, col, 1, 1)

        self.place_mines()

    def get_cells(self):
        return self.cells

    def get_row_col_button(self, index):

        return (index / self.cols, index % self.cols)

    def place_mines(self):
        mines = 0
        while mines < (self.rows * self.cols * self.ratio):

            row = randrange(0, self.rows)
            col = randrange(0, self.cols)

            i = self.get_index(row, col)

            if not self.cells[i].is_mine():

                mines += 1
                self.cells[i].place_mine()

                button = Gtk.Button()
                label = Gtk.Label("M")
                button.add(label)

                self.attach(button, row, col, 1, 1)

        for i, val in enumerate(self.cells):
            print self.cells[i]

    def get_index(self, row, col):
        return (row * self.cols) + col

    def discover_cell(self, row, col):
        index = self.get_index(row, col)
        print 'index', index
        self.cells[index].discover()

    def discover_all_cells(self):
        for cell in self.cells:
            cell.discover()


class Saper:
    def __init__(self, rows, cols):
        self.window = Gtk.Window()
        self.rows = rows
        self.cols = cols
        self.vbox = Gtk.VBox()
        self.window.add(self.vbox)
        self.create_grid(rows, cols)

    def create_grid(self, rows, cols):

        self.grid = SaperGrid(rows, cols, 0.10)

        for i, cell in enumerate(self.grid.get_cells()):
            (row, col) = self.grid.get_row_col_button(i)
            print 'Button connect in col {} row {}'.format(col, row)
            cell.get_button().connect('clicked', self.clicked_handler, row, col)

        self.grid.set_column_homogeneous(True)
        self.grid.set_row_homogeneous(True)
        self.vbox.pack_start(self.grid, expand=True, fill=True, padding=0)

    def clicked_handler(self, button, row, col):
        cell_index = self.grid.get_index(row, col)

        self.grid.discover_cell(row, col)

    @staticmethod
    def exit(self, widget, data=None):
        Gtk.main_quit()


win = Saper(5, 5)
win.window.show_all()
Gtk.main()

怎么了?

隐藏按钮时,也会隐藏其标签。尝试禁用它:

button.set_state_flags(Gtk.StateFlags.INSENSITIVE, True)

用户将无法再次select此字段,您将确保标签显示正确。

问题是您在放置地雷时会创建新按钮。您似乎将这些新按钮放在了磁贴的背景中。因此,如果隐藏前景中的按钮,则只能看到带有标签(即背景)的按钮。

在这个修改后的版本中,我没有这样做,而是重复使用了现有的按钮。如果有地雷,我只是给他们贴上标签。我还在这些标签上使用了 set_no_show_all,这样当网格首次显示为 show_all 时它们就不会显示。然后,发现磁贴只是显示标签(如果存在)并禁用按钮的问题。

顺便说一句,我还通过连接到主 window 的 destroy 信号并调用 gtk_main_quit.

修复了退出应用程序的问题
import gi
from random import randrange

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk


class SaperButton(Gtk.Button):
    def __init__(self):
        Gtk.Button.__init__(self)
        self.set_size_request(50, 50)


class Cell:
    def __init__(self):
        self.mine = False
        self.neighbormines = 0
        self.button = SaperButton()

    def place_mine(self):
        self.mine = True
        label = Gtk.Label("M")
        label.set_no_show_all(True)
        self.button.add(label)

    def is_mine(self):
        return self.mine

    def discover(self):
        print 'discover'
        label = self.button.get_child()
        if label is not None:
            label.show()
        self.button.set_sensitive(False)

    def is_discovered(self):
        return not self.button.get_visible()

    def set_nighbromines(self, number):
        self.neighbormines = number

    def get_nighbromines(self):
        return self.neighbormines

    def get_button(self):
        return self.button


class SaperGrid(Gtk.Grid):
    def __init__(self, rows, cols, ratio):
        self.rows = rows
        self.cols = cols
        self.cells = []
        self.ratio = ratio
        Gtk.Grid.__init__(self)

        for row in range(rows):
            for col in range(cols):
                cell = Cell()
                self.cells.append(cell)
                self.attach(cell.get_button(), row, col, 1, 1)

        self.place_mines()

    def get_cells(self):
        return self.cells

    def get_row_col_button(self, index):

        return (index / self.cols, index % self.cols)

    def place_mines(self):
        mines = 0
        while mines < (self.rows * self.cols * self.ratio):

            row = randrange(0, self.rows)
            col = randrange(0, self.cols)

            i = self.get_index(row, col)

            if not self.cells[i].is_mine():
                mines += 1
                self.cells[i].place_mine()

        for i, val in enumerate(self.cells):
            print self.cells[i]

    def get_index(self, row, col):
        return (row * self.cols) + col

    def discover_cell(self, row, col):
        index = self.get_index(row, col)
        print 'index', index
        self.cells[index].discover()

    def discover_all_cells(self):
        for cell in self.cells:
            cell.discover()


class Saper:
    def __init__(self, rows, cols):
        self.window = Gtk.Window()
        self.rows = rows
        self.cols = cols
        self.vbox = Gtk.VBox()
        self.window.add(self.vbox)
        self.create_grid(rows, cols)
        self.window.connect('destroy', Gtk.main_quit)

    def create_grid(self, rows, cols):

        self.grid = SaperGrid(rows, cols, 0.10)

        for i, cell in enumerate(self.grid.get_cells()):
            (row, col) = self.grid.get_row_col_button(i)
            print 'Button connect in col {} row {}'.format(col, row)
            cell.get_button().connect('clicked', self.clicked_handler, row, col)

        self.grid.set_column_homogeneous(True)
        self.grid.set_row_homogeneous(True)
        self.vbox.pack_start(self.grid, expand=True, fill=True, padding=0)

    def clicked_handler(self, button, row, col):
        cell_index = self.grid.get_index(row, col)
        self.grid.discover_cell(row, col)



win = Saper(5, 5)
win.window.show_all()
Gtk.main()