Python GTK:使用另一个按钮向GUI添加按钮

时间:2016-09-04 22:48:02

标签: python oop gtk

我试图通过按下GUI本身上的按钮向GUI添加另一个按钮。基本上我只是想尝试更新它,但我对OOP来说相对较新,所以我遇到了范围问题。

这就是我到目前为止......

  1 #!/usr/bin/env python
  2 import random, gi, sys
  3 from gi.repository import Gtk
  4 import itertools

 23 class Deck:
 24   """A sample card deck"""
 25   def __init__(self):
 26     deck = []
 27     self.color_list = ["red", "green", "blue"]
 28     for color in self.color_list:
 29       for i in range (1,2):
 30         deck.append((color, i))
 31     self.deck = deck
 32 
 33   def draw_card(self):
 34     print self.deck
 35     try:
 36       card = self.deck.pop()
 37       print self.deck
 38       return card
 39     except IndexError:
 40       print "No cards in deck!"
 41       return

 56 class MyWindow(Gtk.Window):
 57 
 58   def __init__(self):
 59     Gtk.Window.__init__(self, title="RGB 3, 2, 1... GO!")
 60     self.set_border_width(10)
 61     self.set_size_request(450,150)
 62 
 63     grid = Gtk.Grid()
 64     self.add(grid)
 65 
 66     draw_button = Gtk.Button(label="Draw Card")
 67     draw_button.connect("clicked", self.on_draw_button_clicked)
 68     grid.attach(draw_button,0,0,1,1)
 69 
 70     end_button = Gtk.Button(label="End Game")
 71     end_button.connect("clicked", self.on_stop_button_clicked)
 72     grid.attach_next_to(end_button,draw_button,Gtk.PositionType.RIGHT,1,1)
 73 
 74     update_button = Gtk.Button(label="Update")
 75     update_button.connect("clicked", self.update, grid)
 76     grid.attach_next_to(update_button,end_button,Gtk.PositionType.RIGHT,1,1)
 77 
 78   def update(self, widget, grid):
 79     card1_button = Gtk.Button(label="card1")
 80     card1_button.connect("clicked", self.on_card1_button_clicked)
 81     grid.attach_next_to(card1_button,draw_button,Gtk.PositionType.BOTTOM,3,1)
 82     
 83   def on_draw_button_clicked(self, widget):
 84 +--- 13 lines: card = my_deck.draw_card()----------------------------------------------------------------------------------------------------
 97 
 98   def on_stop_button_clicked(self, widget):
 99     Gtk.main_quit()
100     
101   def on_card1_button_clicked(self, widget):
102     Gtk.main_quit()

121 # Objects must be instantiated here
122 my_deck = Deck()
123 print my_deck.deck
124 win = MyWindow()
125 win.connect("delete-event", Gtk.main_quit)
126 win.show_all()
127 Gtk.main()

当我运行时,我的GUI弹出。当我点击我的更新按钮时,我收到以下错误:

Traceback (most recent call last):
  File "game1.py", line 85, in update
    grid.attach_next_to(card1_button,draw_button,Gtk.PositionType.BOTTOM,3,1)
NameError: global name 'draw_button' is not defined

如何让我的更新功能识别我已经在def init 功能中创建的GUI /网格?有没有更好的方法来做我想要的?

1 个答案:

答案 0 :(得分:1)

MyWindow课程中定义instance variable以跟踪该按钮。

例如,在您的代码中,只要您看到draw_button将其更改为self.draw_button。它将允许您以其他方式跟踪此按钮。这看起来像是:

import random, gi, sys
from gi.repository import Gtk
import itertools

class Deck:
  """A sample card deck"""
  def __init__(self):
    deck = []
    self.color_list = ["red", "green", "blue"]
    for color in self.color_list:
      for i in range(1,2):
        deck.append((color, i))
    self.deck = deck

  def draw_card(self):
    print self.deck
    try:
      card = self.deck.pop()
      print self.deck
      return card
    except IndexError:
      print "No cards in deck!"
      return

class MyWindow(Gtk.Window):

  def __init__(self):
    Gtk.Window.__init__(self, title="RGB 3, 2, 1... GO!")
    self.set_border_width(10)
    self.set_size_request(450,150)

    grid = Gtk.Grid()
    self.add(grid)

    # Here we create the instance variable and use it afterward
    self.draw_button = Gtk.Button(label="Draw Card")
    self.draw_button.connect("clicked", self.on_draw_button_clicked)
    grid.attach(self.draw_button,0,0,1,1)

    end_button = Gtk.Button(label="End Game")
    end_button.connect("clicked", self.on_stop_button_clicked)
    grid.attach_next_to(end_button, self.draw_button, Gtk.PositionType.RIGHT, 1, 1)

    update_button = Gtk.Button(label="Update")
    update_button.connect("clicked", self.update, grid)
    grid.attach_next_to(card1_button, self.draw_button, Gtk.PositionType.BOTTOM, 3, 1)

  def update(self, widget, grid):
    card1_button = Gtk.Button(label="card1")
    card1_button.connect("clicked", self.on_card1_button_clicked)
    # Here we recall the value stored in self.draw_button
    grid.attach_next_to(card1_button, self.draw_button, Gtk.PositionType.BOTTOM, 3, 1)

  def on_draw_button_clicked(self, widget):
    for x in range(13):
      card = my_deck.draw_card()

  def on_stop_button_clicked(self, widget):
    Gtk.main_quit()

  def on_card1_button_clicked(self, widget):
    Gtk.main_quit()

# Objects must be instantiated here
my_deck = Deck()
print my_deck.deck
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

但您的代码中还存在其他一些问题:

  • 我认为您使用的是Gtk 3.0。如果是这种情况,您应该在导入Gtk之前要求它:

    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk
    
  • Deck.__init__()中,您在for循环中使用了range(1,2)。问题是range(1, 2)等同于[1],因为你要求的范围从1开始,但在2之前停止。我不确定那是你想要的。

  • 您应该在self.show_all()方法的末尾添加MyWindow.update(),否则您将无法看到新创建的按钮。
  • 您应该在self.close()Gtk.main_quit()方法中使用MyWindow.on_stop_button_clicked()代替MyWindow.on_card1_button_clicked(),否则您的代码将无法在单击这些按钮时正确销毁您的窗口。

这就是这些建议的看法:

import random, gi, sys
import itertools

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

class Deck:
  """A sample card deck"""
  def __init__(self):
    deck = []
    self.color_list = ["red", "green", "blue"]
    for color in self.color_list:
      for i in range(1,2):    # Check to see if this is valid
        deck.append((color, i))
    self.deck = deck

  def draw_card(self):
    print self.deck
    try:
      card = self.deck.pop()
      print self.deck
      return card
    except IndexError:
      print "No cards in deck!"
      return

class MyWindow(Gtk.Window):

  def __init__(self):
    Gtk.Window.__init__(self, title="RGB 3, 2, 1... GO!")
    self.set_border_width(10)
    self.set_size_request(450,150)

    grid = Gtk.Grid()
    self.add(grid)

    self.draw_button = Gtk.Button(label="Draw Card")
    self.draw_button.connect("clicked", self.on_draw_button_clicked)
    grid.attach(self.draw_button,0,0,1,1)

    end_button = Gtk.Button(label="End Game")
    end_button.connect("clicked", self.on_stop_button_clicked)
    grid.attach_next_to(end_button, self.draw_button, Gtk.PositionType.RIGHT, 1, 1)

    update_button = Gtk.Button(label="Update")
    update_button.connect("clicked", self.update, grid)
    grid.attach_next_to(update_button, end_button, Gtk.PositionType.RIGHT, 1, 1)

  def update(self, widget, grid):
    card1_button = Gtk.Button(label="card1")
    card1_button.connect("clicked", self.on_card1_button_clicked)
    grid.attach_next_to(card1_button, self.draw_button, Gtk.PositionType.BOTTOM, 3, 1)
    self.show_all()      # So that we can see the freshly created button

  def on_draw_button_clicked(self, widget):
    for x in range(13):
      card = my_deck.draw_card()

  def on_stop_button_clicked(self, widget):
    self.close()         # Instead of Gtk.main_quit()

  def on_card1_button_clicked(self, widget):
    self.close()         # Instead of Gtk.main_quit()

# Objects must be instantiated here
my_deck = Deck()
print my_deck.deck
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()