Tkinter:将 canvas 个对象和按钮网格化在一起
Tkinter: gridding canvas objects and buttons together
我想在一个框架中显示 9 套卡片。每张卡片下方都有自己的按钮。我正在使用 SetCard.deal_card(position) 方法将卡片放置在 3x3 网格中的框架中(位置 0-8)。当我 运行 程序时,只有按钮出现。当我注释掉 pickButton.grid() 方法时,卡片就会出现。我不知道为什么我只能拥有一个而不能同时拥有两个。
from tkinter import *
import random
class SetCard(Canvas):
def __init__(self,master,number,color,shape,shading):
# create a 60x60 white canvas with a 5-pixel grooved border
Canvas.__init__(self,master,width=100,height=160,bg='white',\
bd=5,relief=RAISED) #also relief = SUNKEN
# store the valuelist and colorlist
self.number = number
self.color = color
self.shape = shape
self.shading = shading
self.selected=False
self.pickButton=Button(self,text="Pick me!", command=self.toggle_card)
def deal_card(self,position):
'''puts the given card into a position on the 3x3 grid of the frame'''
self.draw_card()
print("row: ",(position//3)*2)
print("col: ",position%3)
self.grid(row=(position//3)*2,column=position%3)
self.pickButton.grid(row=((position//3)*2)+1,column= position %3)
self.master.deck.pop(0)
def toggle_card(self):
self.selected=True
self['bg']='gray'
self['relief']=sunken
def draw_card(self):
'''draws the pips in the correct locations on the card'''
# clear old pips first
self.erase()
# location of which pips should be drawn
if self.number == 1:
self.draw_pip(position=2)
if self.number == 2:
self.draw_pip(position=1)
self.draw_pip(position=3)
if self.number == 3:
self.draw_pip(position=1)
self.draw_pip(position=2)
self.draw_pip(position=3)
def draw_pip(self,position):
'''draws a single pip in the given location'''
if self.shading=='solid':
inside=self.color
else:
inside=''
(topx,topy) = (55,10+ (position-1)*50)
if self.shape == 'diamond':
self.create_polygon(topx, topy, topx+15, topy+20, topx, topy+40, topx-15, topy+20,\
outline=self.color,fill=inside,width=3)
if self.shading=='stripe':
incrementxy=[(5,30),(10,25), (15,20), (10,15), (5,10)]
for xy in incrementxy:
self.create_line(topx-xy[0],topy+xy[1],topx+xy[0],topy+xy[1],fill=self.color)
if self.shape == 'circle':
self.create_oval(topx-20,topy,topx+20,topy+40,fill=inside,outline=self.color,width=3)
if self.shading=='stripe':
incrementxy=[(10,3),(14,7),(17,10),(19,14),(20,20),(18,24),(17,30),(14,33),(10,37)]
for xy in incrementxy:
self.create_line(topx-xy[0],topy+xy[1],topx+xy[0],topy+xy[1], fill= self.color)
if self.shape == 'square':
self.create_polygon(topx-20,topy,topx+20,topy,topx+20,topy+40,topx-20,topy+40,fill=inside,outline=self.color,width=3)
if self.shading=='stripe':
for increment in range(5,40,5):
self.create_line(topx-20, topy+increment,topx+20,topy+increment, fill = self.color)
def erase(self):
'''erases all the pips'''
pipList = self.find_all()
for pip in pipList:
self.delete(pip)
class SetGameFrame(Frame):
'''frame for a game of Set'''
def __init__(self,master):
'''creates a new Set frame'''
# set up Frame object
Frame.__init__(self,master)
self.grid()
colorList=['red','green','magenta']
shadingList=['solid','stripe','open']
shapeList=['circle','diamond','square']
self.dealt_cards=[]
self.deck=[]
for number in range(3):
for color in colorList:
for shading in shadingList:
for shape in shapeList:
self.deck.append(SetCard(self,number+1,color,shape,shading))
random.shuffle(self.deck)
for position in range(9):
self.deck[0].deal_card(position)
self.dealt_cards.append(self.deck[0])
self.setButton=Button(self,text="SET!",command=self.pick_set)
self.setButton.grid(row=6,column=1,rowspan=2)
def pick_set(self):
pass
def play_Set():
root = Tk()
root.title('Set Game')
game = SetGameFrame(root)
root.mainloop()
play_Set()
你的错误在于让选择按钮成为卡片的奴隶而不是 canvas。
将定义更改为
self.pickButton=Button(master,text="Pick me!", command=self.toggle_card)
您的代码将起作用。你所拥有的代码发生了什么,卡片在 canvas 中被网格化,但是按钮在卡片中被网格化,你所看到的只是按钮。
第一个参数 (master) 应该是 self 似乎很自然(至少对我而言),因为按钮是卡片的一个属性。但是,Tk(tkinter 下的 GUI 工具包)中的 widget 层次结构与此无关。这里的第一个参数并不意味着 self.PickButton 是 objected-oriented 意义上的 child master,而是那个 master(canvas 小部件)正在管理 self-pickButton的"geometry"。
顺便说一下,您的代码中存在语法错误。在第 30 行,单词 "sunken."
应该有引号
我想在一个框架中显示 9 套卡片。每张卡片下方都有自己的按钮。我正在使用 SetCard.deal_card(position) 方法将卡片放置在 3x3 网格中的框架中(位置 0-8)。当我 运行 程序时,只有按钮出现。当我注释掉 pickButton.grid() 方法时,卡片就会出现。我不知道为什么我只能拥有一个而不能同时拥有两个。
from tkinter import *
import random
class SetCard(Canvas):
def __init__(self,master,number,color,shape,shading):
# create a 60x60 white canvas with a 5-pixel grooved border
Canvas.__init__(self,master,width=100,height=160,bg='white',\
bd=5,relief=RAISED) #also relief = SUNKEN
# store the valuelist and colorlist
self.number = number
self.color = color
self.shape = shape
self.shading = shading
self.selected=False
self.pickButton=Button(self,text="Pick me!", command=self.toggle_card)
def deal_card(self,position):
'''puts the given card into a position on the 3x3 grid of the frame'''
self.draw_card()
print("row: ",(position//3)*2)
print("col: ",position%3)
self.grid(row=(position//3)*2,column=position%3)
self.pickButton.grid(row=((position//3)*2)+1,column= position %3)
self.master.deck.pop(0)
def toggle_card(self):
self.selected=True
self['bg']='gray'
self['relief']=sunken
def draw_card(self):
'''draws the pips in the correct locations on the card'''
# clear old pips first
self.erase()
# location of which pips should be drawn
if self.number == 1:
self.draw_pip(position=2)
if self.number == 2:
self.draw_pip(position=1)
self.draw_pip(position=3)
if self.number == 3:
self.draw_pip(position=1)
self.draw_pip(position=2)
self.draw_pip(position=3)
def draw_pip(self,position):
'''draws a single pip in the given location'''
if self.shading=='solid':
inside=self.color
else:
inside=''
(topx,topy) = (55,10+ (position-1)*50)
if self.shape == 'diamond':
self.create_polygon(topx, topy, topx+15, topy+20, topx, topy+40, topx-15, topy+20,\
outline=self.color,fill=inside,width=3)
if self.shading=='stripe':
incrementxy=[(5,30),(10,25), (15,20), (10,15), (5,10)]
for xy in incrementxy:
self.create_line(topx-xy[0],topy+xy[1],topx+xy[0],topy+xy[1],fill=self.color)
if self.shape == 'circle':
self.create_oval(topx-20,topy,topx+20,topy+40,fill=inside,outline=self.color,width=3)
if self.shading=='stripe':
incrementxy=[(10,3),(14,7),(17,10),(19,14),(20,20),(18,24),(17,30),(14,33),(10,37)]
for xy in incrementxy:
self.create_line(topx-xy[0],topy+xy[1],topx+xy[0],topy+xy[1], fill= self.color)
if self.shape == 'square':
self.create_polygon(topx-20,topy,topx+20,topy,topx+20,topy+40,topx-20,topy+40,fill=inside,outline=self.color,width=3)
if self.shading=='stripe':
for increment in range(5,40,5):
self.create_line(topx-20, topy+increment,topx+20,topy+increment, fill = self.color)
def erase(self):
'''erases all the pips'''
pipList = self.find_all()
for pip in pipList:
self.delete(pip)
class SetGameFrame(Frame):
'''frame for a game of Set'''
def __init__(self,master):
'''creates a new Set frame'''
# set up Frame object
Frame.__init__(self,master)
self.grid()
colorList=['red','green','magenta']
shadingList=['solid','stripe','open']
shapeList=['circle','diamond','square']
self.dealt_cards=[]
self.deck=[]
for number in range(3):
for color in colorList:
for shading in shadingList:
for shape in shapeList:
self.deck.append(SetCard(self,number+1,color,shape,shading))
random.shuffle(self.deck)
for position in range(9):
self.deck[0].deal_card(position)
self.dealt_cards.append(self.deck[0])
self.setButton=Button(self,text="SET!",command=self.pick_set)
self.setButton.grid(row=6,column=1,rowspan=2)
def pick_set(self):
pass
def play_Set():
root = Tk()
root.title('Set Game')
game = SetGameFrame(root)
root.mainloop()
play_Set()
你的错误在于让选择按钮成为卡片的奴隶而不是 canvas。
将定义更改为
self.pickButton=Button(master,text="Pick me!", command=self.toggle_card)
您的代码将起作用。你所拥有的代码发生了什么,卡片在 canvas 中被网格化,但是按钮在卡片中被网格化,你所看到的只是按钮。
第一个参数 (master) 应该是 self 似乎很自然(至少对我而言),因为按钮是卡片的一个属性。但是,Tk(tkinter 下的 GUI 工具包)中的 widget 层次结构与此无关。这里的第一个参数并不意味着 self.PickButton 是 objected-oriented 意义上的 child master,而是那个 master(canvas 小部件)正在管理 self-pickButton的"geometry"。
顺便说一下,您的代码中存在语法错误。在第 30 行,单词 "sunken."
应该有引号