Печать

На Python, используя среду Glade напишем программу с 8 кнопками - игру Flip-Flop с современным стандартным графическим интерфейсом Gtk+ 3.

 Запустите IDE Glade, создайте новый проект.

Создайте Окно класса GtkWindow, на вкладке Основные свойства присвойте ему идентификатор ID: window. Там же, на вкладке Основные свойства присвойте окну Заголовок Flip-Flop. На вкладке Сигналы событию destroy задайте обработчик on_destroy.

Поверх окна window разместите Контейнер GtkBox. На вкладке Основные свойства укажите Количество элементов: 2. 

В верхней части контейнера GtkBox разместите контейнер GtkGrid, с атрибутами на вкладке Основные свойства Строки Count: 2 и Столбцы Count: 5.

В нижней части контейнера GtkBox разместите контейнер GtkButtonBox, с атрибутами на вкладке Основные свойства Количество элементов 1.

В контейнере GtkGrid разместите в каждой ячейке по 1 кнопочке Control GtkButton (всего 8 кнопок). Каждой кнопке на вкладке Основные свойства присвойте идентификатор ID: btnX, где X номер кнопки по порядку 0 ...7. У всех кнопок на вкладке Основные свойства удалите надпись. Для всех кнопок на вкладке Сигналы событию clicked задайте обработчик on_btn_clicked. На вкладке Общие свойства каждой кнопки задайте Имя виджетаX, где X номер кнопки по порядку 0 ...7.

В контейнере GtkButtonBox разместите кнопку Control GtkButton. На вкладке Основные свойства для этой кнопки задайте надпись: Новая игра. На вкладке Сигналы событию clicked задайте обработчик on_btn_new.

В IDE Glade сохраните проект под именем, например, examle. В результате вы получите файл example.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window">
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">Flip-Flop</property>
    <signal name="destroy" handler="on_destroy" swapped="no"/>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="halign">center</property>
        <property name="valign">center</property>
        <property name="margin_left">10</property>
        <property name="margin_right">10</property>
        <property name="margin_top">10</property>
        <property name="margin_bottom">10</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkGrid">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">center</property>
            <property name="valign">center</property>
            <property name="row_spacing">5</property>
            <property name="column_spacing">6</property>
            <child>
              <object class="GtkButton" id="btn0">
                <property name="label" translatable="yes"> </property>
                <property name="name">0</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn1">
                <property name="label" translatable="yes"> </property>
                <property name="name">1</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn2">
                <property name="label" translatable="yes"> </property>
                <property name="name">2</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">2</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn3">
                <property name="label" translatable="yes"> </property>
                <property name="name">3</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">3</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn4">
                <property name="label" translatable="yes"> </property>
                <property name="name">4</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn5">
                <property name="label" translatable="yes"> </property>
                <property name="name">5</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn6">
                <property name="label" translatable="yes"> </property>
                <property name="name">6</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">2</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn7">
                <property name="label" translatable="yes"> </property>
                <property name="name">7</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_btn_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">3</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkButtonBox">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">center</property>
            <property name="valign">end</property>
            <property name="spacing">6</property>
            <property name="layout_style">center</property>
            <child>
              <object class="GtkButton">
                <property name="label" translatable="yes">Новая игра</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="margin_top">6</property>
                <signal name="clicked" handler="on_btn_new" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

В текстовом редакторе или, например, в IDE IDLE напишите программу example.py следующего содержания:

#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width:$

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf, Gdk
import os, sys, random
XML_FILE = "example.glade"
myGame = [True,False,True,False,False,False,True,True]
N = 0

def rendering():
    global window, but, myGame, N
    X = 0
    for i in range(8):
        if (myGame[i]):
            but[i].set_label('X')
            X +=1
        else:
            but[i].set_label('O')
    if X == 8:
        window.set_title(("Победа! " if N<8 else "Плохо ") + str(N)+ (" хода" if N<5 else " ходов"))
        N = 0
    else:
        window.set_title(" Сделай все Х")
        N += 1

class Handler:
    def on_destroy(self, *args):
        print("Программа завершена")
        Gtk.main_quit()

    def on_btn_clicked(self, button):
        global myGame
        n=int(button.get_name())
        myGame[n] = not(myGame[n])
        for i in range(int(not(n//4))*4, 4 + int(not(n//4))*4):
            myGame[i] = not(myGame[i])
        rendering()

    def on_btn_new(self, button):
        global myGame
        Y = int(1+253*random.random())
        for i in range(8):
            X = Y & 0b00000001
            Y >>= 1
            myGame[i] = bool(X)
        rendering()

builder = Gtk.Builder()
builder.add_from_file(XML_FILE)
builder.connect_signals(Handler())
window = builder.get_object("window")
window.show_all()
##Создаём список кнопок btni (где i 0...7)
but = [builder.get_object('btn'+str(i)) for i in range(8)]
Gtk.main()

Наш проект состоит их 2-х файлов example.py и example.glade. Теперь можно запускать нашу программу через терминал в папке проекта или через IDE IDLE:

dior@U18pro:~/Python/Anjuta/pygtk007/src$ ./example.py

Работает: