0

I write simple minesweeper game in Python 2.7 with Gtk3. I have a problem with show value of label after click using set_sensitive(False).

First case I use button.hide() after click and this works good, label value are shows up.

enter image description here

M - is a mine on board

But I don't want to use hide(). I want to block button after click with set_sensitive() property. I try do this in my discover function return self.button.set_sensitive(False) but after that I don't get any value of my buttons. I clicked all board and all buttons are disable. Why I don't get any value of label?

Board after use set_sensitive(False)

enter image description here

My code:

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()

What's is wrong?

3
  • Can anyone help? Commented Mar 25, 2017 at 20:08
  • If the labels are made after show_all(), you may need to explicitly call label.show() when making the labels, but I'm not sure what else could be wrong... Commented Mar 25, 2017 at 22:56
  • Lables mad on the begining program in function place_mines. Is it possible at all? Do I have to create an additional array and when I click on the button insert a label? Commented Mar 26, 2017 at 9:59

2 Answers 2

1

The problem is that you create new buttons when placing your mines. It seems you put those new buttons in the background of your tiles. Thus, you can only seen the button with the label (which is the background) if you hide the button that is in the foreground.

Instead of doing this, in this modified version I reuse the existing buttons. I just add a label to them if there is a mine. I also use the set_no_show_all on those labels, so that they are not shown when the grid is first display with show_all. Then, discovering a tile is just a matter of showing the label if it exists, and disabling the button.

BTW, I also fixed exiting the application by connecting to the destroy signal of the main window and calling 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()
Sign up to request clarification or add additional context in comments.

4 Comments

Hm if I click on buttons, program hang up.
When I click on button with bomb
After computer restart it's ok... Is there a way for the letter "M" to be seen clearly?
Well, setting the widget as insensitive changes its style into grayed text, which is a normal way of showing a widget is insensitive. What you whant is probably making the widget not respond to clicks, so just connecting a dummy callback to intercept the calls may be enough.
0

When you hide the button, you also hide its label. Try to disable it instead:

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

User won't be able to select this field again and you'll be sure that the label is displayed correctly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.