Python GTK:使用另一个按钮将按钮添加到 GUI
Python GTK: Add a button to a GUI with another button
我正在尝试通过按 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/grid?有没有更好的方法来做我想做的事?
在您的 MyWindow
class 中定义一个 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 之前停止。我不确定那是您想要的。
- 您应该在
MyWindow.update()
方法的末尾添加一个 self.show_all()
否则您将看不到新创建的按钮。
- 您应该在
MyWindow.on_stop_button_clicked()
和 MyWindow.on_card1_button_clicked()
方法中使用 self.close()
而不是 Gtk.main_quit()
否则您的代码将无法正确破坏您的 window 单击这些按钮时。
这是这些建议的样子:
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()
我正在尝试通过按 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/grid?有没有更好的方法来做我想做的事?
在您的 MyWindow
class 中定义一个 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 之前停止。我不确定那是您想要的。- 您应该在
MyWindow.update()
方法的末尾添加一个self.show_all()
否则您将看不到新创建的按钮。 - 您应该在
MyWindow.on_stop_button_clicked()
和MyWindow.on_card1_button_clicked()
方法中使用self.close()
而不是Gtk.main_quit()
否则您的代码将无法正确破坏您的 window 单击这些按钮时。
这是这些建议的样子:
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()