我正在将我的旧数独计划从Ruby 1.8
转换为Python 2.7.8.10
。在Ruby中工作得很好。我为数独板的单元格/瓦片使用Tkinter rectangles
(create_rectangle),为数独数字使用Tkinter text
(create_text)。两个小部件都在画布上绘制(middleCenterCanvas
)。
问题:数字(
entryNumbers
)覆盖画布并阻止我的鼠标点击,迫使我点击数字的边缘来执行我的绑定回调功能(mainCellClickedProc())
。 https://github.com/bripkens/fuzzy.js完全通过stackoverflow.com,TkDocs.com和一系列书籍和教程,到目前为止没有运气。无法理解为什么tag_bind
下面的(in createCellEntryNumbers())
也无效。问题:怎么办我点击要传递到画布的数字,这样我就可以关闭我的回调函数了?
self.middleCenterFrame.pack(side=LEFT, fill=BOTH, expand=True)
self.middleCenterCanvas = Canvas(
self.middleCenterFrame, borderwidth=0,
width=435, height=455, relief=GROOVE,
highlightthickness=0, background=self.fillColor)
self.middleCenterCanvas.pack(fill=BOTH, expand=True, padx=0, pady=0)
def drawCells(self, cellSize, xr1c1, yr1c1):
for i in range (9): # Cell Rows
xul = xr1c1
yul = yr1c1 + (i * cellSize)
xlr = xul + cellSize
ylr = yul + cellSize
for j in range(9): # Cell Columns
self.boardRects[(i * 9) + j] = \
self.middleCenterCanvas.create_rectangle(\
xul, yul, xlr, ylr, fill=self.fillColor, \
outline=self.lineColor, width=self.cellLineWidth\
)
xul += cellSize
xlr += cellSize
self.middleCenterCanvas.pack()
def createCellEntryNumbers(self):
xul = self.xr1c1
yul = self.yr1c1
xlr = self.xr1c1 + self.cellSize
ylr = self.yr1c1 + self.cellSize
# Cell Rows
for i in range (9):
xul = self.xr1c1
yul = self.yr1c1 + (i * self.cellSize)
xlr = xul + self.cellSize
ylr = yul + self.cellSize
for j in range(9):
self.entryNumberTags [(i * 9) + j] = \
self.middleCenterCanvas.create_text( \
(xul+(self.cellSize/2)), (yul+(self.cellSize/2)), \
fill=self.lineColor, \
width=self.cellNumberWidth, font=self.cellNumberFont
)
self.entryNumbersWindow [(i * 9) + j] = \
self.middleCenterCanvas.create_window( \
(xul+(self.cellSize/2)), (yul+(self.cellSize/2)), \
anchor=NW, window=self.entryNumberTags [(i * 9) + j])
xul += self.cellSize
xlr += self.cellSize
self.middleCenterCanvas.tag_bind(self.entryNumberTags[(i * 9) + j], \
'<Button>', lambda e: self.mainCellClickedProc(e.num, e.x, e.y))
def writeEntryNumber(self, num, x, y, fgCol, bgCol):
if self.cellValues[self.calcCellFromXYCoords(x, y)] == self.sillyNilly:
entryNumText = " "
else:
entryNumText = str(num)
self.entryNumbers[self.calcCellFromXYCoords(x, y)] = \
Label(self.middleCenterCanvas)
self.entryNumbers[self.calcCellFromXYCoords(x, y)].configure(
text= entryNumText,
#font= 'arial 16 bold',
font= self.cellLabelFont,
foreground= fgCol,
background= bgCol
)
self.entryNumbers[self.calcCellFromXYCoords(x, y)].place(
x=x + 15,
y=y + 16,
width=self.cellLabelWidth,
height=self.cellLabelHeight
)
def mainCellClickedProc(self, btn, x, y):
self.clearStatusLine()
if self.num_x != self.sillyNilly and self.num_y != self.sillyNilly:
x = self.num_x
y = self.num_y
if ((x >= self.xr1c1) and (x <= ((self.xr1c1 - 2) + (9 * self.cellSize)))) and \
(y >= (self.yr1c1) and (y <= ((self.yr1c1 - 2) + (9 * self.cellSize)))):
#self.tell_it(btn, x, y)
self.drawCells(self.cellSize, self.xr1c1, self.yr1c1)
x1 = ((((x + self.xr1c1) / self.cellSize) - 1) * self.cellSize) + self.xr1c1
y1 = ((((y + self.yr1c1) / self.cellSize) - 1) * self.cellSize) + self.yr1c1
x2 = x1 + self.cellSize
y2 = y1 + self.cellSize
self.rw = ((y + self.yr1c1) / self.cellSize)
self.col = ((x + self.xr1c1) / self.cellSize)
self.cel = (((self.rw ) * 9) + self.col)
self.grw = ((y + self.yr1c1 + (2 * self.cellSize)) / self.gridSize)
self.gcol = ((x + self.xr1c1 + (2 * self.cellSize)) / self.gridSize)
self.grid = (((self.grw - 1) * 3) + self.gcol)
if btn == 1:
self.clearLastUnit()
self.loadUnitRowValues(self.rw, self.bgColor)
self.loadUnitColumnValues(self.col, self.bgColor)
self.loadUnitGridValues(self.grid, self.bgColor)
self.drawGrids(self.cellSize, self.xr1c1, self.yr1c1)
self.cellOutline(x1, y1, x2, y2, self.outlineColor)
self.writeInfoLine()
if btn == 1:
self.enterProc()
if self.numBtnToggleOnFlag == True:
self.numBtnPressed(self.entryNumber)
elif btn == 3:
self.loadUnitRowValues(self.rw, self.bgColor)
self.loadUnitColumnValues(self.col, self.bgColor)
self.loadUnitGridValues(self.grid, self.bgColor)
self.loadRow(self.rw)
self.loadColumn(self.col)
self.loadGrid(self.grid)
self.drawGrids(self.cellSize, self.xr1c1, self.yr1c1)
self.cellOutline(x1, y1, x2, y2, self.outlineColor)
self.num_x = self.num_y = self.sillyNilly
return self.cell
答案 0 :(得分:0)
解决方案:好的,我认为这是巨大的!不仅因为它花了我几天才解决它,而是因为,好吧......
原始问题:我的鼠标点击单元格中的数独条目号码似乎没有触发我的mainCellClickedProc()函数...除了他们正在解雇它!只是Tk(inter)发送相对于Label小部件的坐标(0到23之间),而不是画布对象(25到475之间,我计算了我的Sudoku游戏单元格),因此if条件(右)在我的按钮事件的主要回调中,我用来定位单元格,并启动了我所有的“海鸥”游戏逻辑,不断失败。特别是(x&gt; = self.xr1c1和(y&gt; = self.yr1c1)条件,因为self.xr1c1和self.tr1c1都是25,总是为假!现在,踢球者认为这不会发生在程序的Ruby Tcl / Tk版本中,所以我甚至没有查看这个区域完全没有。只是在将程序削减到一个Hello,World-sized的单位之后,我偶然发现了发生的事情。这是一个什么样的问题!它毕竟与绑定无关!!! / p>
以下是代码。不幸的是,Hello,world!-size仍然差不多300行!
另一件事是“旅程”,其中......
我去'网并试图找到一些很好的参考资料,让我不知道我的(咳嗽)“绑定”(咳嗽)到底是怎么回事。我偶然发现了Tcl / Tk网站。我读到了断言,为一个环境创建的Tk代码可以在所有平台上不加修改地运行。我相信炒作。我进一步阅读了系统的背景和历史。维护者谈论积极的发展随着时间的推移。随着时间的推移,它们意味着事情会发生变化。他们没有说这对十年前用一种语言(Ruby 1.8.2 w / Tcl / Tk)编写的应用程序如何影响,并且今天运行在另一种语言(Python 2.7.8.10 w / Tkinter 8.5)上。
我确定我需要可靠的参考资料,而不是在effbot.org甚至tkdocs.com上找到的粗略教程内容,甚至是新墨西哥技术网站上的教程。并不是说他们一定是坏人,而是他们在示例部门都很弱。无论如何,我主要讨论Tkinter 8.5参考:John Shipman的Python GUI,因为毕竟那是我正在移植的平台。但是,我仍然使用其他材料,包括John Grayson撰写的Python和Tkinter Programming以及其他一些材料。
天过去了。在我(*)花费阅读,研究,探索和调试的那些日子里,除了解决方案之外唯一的事情是我不确定我是否有效地学习或只是浪费时间。我在脑海里思考这个想法,“有点无知是危险的事情!”
(*)“我”包括在这个过程中传递了宝贵知识的亲切的灵魂(是的,你知道你是谁......(咳)“布莱恩”(咳))(:&gt;)
P.S。我可能因为这种“诽谤”而受到骂,但它无论如何都不会比我迄今为止所忍受的痛苦更加痛苦。我只能说,道歉和主啊,请原谅我!
解决方案代码(在所有相关位置标注“#Binderooney-related Solution Stuff”评论......
#!/usr/bin/env python
from Tkinter import *
mouseClickNumber = 1
class LabelsAsEventFodderPOC (Frame):
""" Labels as Event Fodder for Proof of Concept class """
def __init__(self, cellSize, xr1c1, yr1c1, master=None):
#Frame.__init__(self, master)
self.cellSize = cellSize
self.xr1c1 = xr1c1
self.yr1c1 = yr1c1
self.button = 0
self.xcoord = 0
self.ycoord = 0
self.sillyNilly = 0
self.gridSize = cellSize * 3;
self.fillColor = 'steelblue'
self.highlightColor = 'steelblue3'
self.outlineColor = 'red'
self.lineColor = 'black'
self.cellLineWidth = 2
self.gridLineWidth = 5
self.rootFont = 'arial 20 bold'
self.timerLabelFont = 'arial 9 bold'
self.msgLabelFont = 'arial 11 bold'
self.buttonTextFont = 'arial 10 bold'
self.numberFont = 'arial 20 bold'
self.numberFontHeight = 23
self.numberFontWidth = 20
self.bgColor = self.fillColor
self.fgColor = self.lineColor
self.hlColor = self.highlightColor
self.olColor = self.outlineColor
self.gridRects = [None] * 9
self.gridL = [None] * 9
self.cell = self.sillyNilly
self.root = Tk()
self.root.option_add('*font', self.rootFont)
self.frame = Frame(self.root)
self.frame.pack(fill=BOTH, expand=True)
self.canvas = Canvas(
self.frame, borderwidth=0, # Set up Canvas
width=200, height=260, relief=GROOVE,
highlightthickness=0, background=self.fillColor)
self.canvas.pack(fill=BOTH, expand=True, padx=0, pady=0)
self.drawCells(cellSize, xr1c1, yr1c1)
self.drawGrid(cellSize, xr1c1, yr1c1)
self.numberLabels = [None] * 9 # Binderooney-related Solution Stuff ...
self.numberLabelsWindow = [None] * 9 # Binderooney-related Solution Stuff ...
self.numberLabelsCellCoords = [] * 9 # Binderooney-related Solution Stuff ...
self.labelID = self.sillyNilly # Binderooney-related Solution Stuff ...
for i in range (3): # Cell Rows # Binderooney-related Solution Stuff ...
xul = self.xr1c1 + (3 * self.cellSize) # Binderooney-related Solution Stuff ...
yul = self.yr1c1 + (i * self.cellSize) + (3 * self.cellSize) # Binderooney-related Solution Stuff ...
xlr = xul + self.cellSize # Binderooney-related Solution Stuff ...
ylr = yul + self.cellSize # Binderooney-related Solution Stuff ...
for j in range(3): # Cell Columns # Binderooney-related Solution Stuff ...
self.numberLabels[(i * 3) + j] = Label(self.numberLabelsWindow[(i * 3) + j]) # Binderooney-related Solution Stuff ...
xul += self.cellSize # Binderooney-related Solution Stuff ...
xlr += self.cellSize # Binderooney-related Solution Stuff ...
# Bind the mouse clicks to the numberLabels # Binderooney-related Solution Stuff ...
self.numberLabels[(i * 3) + j].bind("<Button>", \
lambda e, k=((i * 3) + j): self.binderooney(e.num, e.x, e.y, k), add='+') # !!!!! # Binderooney-related Solution Stuff ...
for i in range (3): # Cell Rows # Binderooney-related Solution Stuff ...
xul = xr1c1 # Binderooney-related Solution Stuff ...
yul = yr1c1 + (i * cellSize) # Binderooney-related Solution Stuff ...
xlr = xul + cellSize # Binderooney-related Solution Stuff ...
ylr = yul + cellSize # Binderooney-related Solution Stuff ...
for j in range(3): # Cell Columns # Binderooney-related Solution Stuff ...
print "In constructor, index is %r!!!!!!!!!!!!!!!!!!!" % ((i * 3) + j) # Binderooney-related Solution Stuff ...
self.numberLabelsCellCoords.append([xul, yul]) # Binderooney-related Solution Stuff ...
xul += cellSize # Binderooney-related Solution Stuff ...
xlr += cellSize # Binderooney-related Solution Stuff ...
print "In constructor, self.numberLabelsCellCoords is %r!!!!!!!!!!!!!!!!" % self.numberLabelsCellCoords # Binderooney-related Solution Stuff ...
self.setupGrid() # Binderooney-related Solution Stuff ...
# Capture the mouse click in the canvas
self.canvas.bind("<Button>", \
lambda e: self.mainCallbackFunction(e.num, e.x, e.y)) # !!!!!
def drawCells(self, cellSize, xr1c1, yr1c1):
""" Draw the grid's 3 by 3 cells """
for i in range (3): # Cell Rows # Binderooney-related Solution Stuff ...
xul = xr1c1
yul = yr1c1 + (i * cellSize)
xlr = xul + cellSize
ylr = yul + cellSize
for j in range(3): # Cell Columns # Binderooney-related Solution Stuff ...
self.gridRects[(i * 3) + j] = \
self.canvas.create_rectangle(\
xul, yul, xlr, ylr, fill=self.fillColor, \
outline=self.lineColor, width=self.cellLineWidth\
) # Binderooney-related Solution Stuff ...
xul += cellSize
xlr += cellSize
self.canvas.pack()
def drawGrid(self, cellSize, xr1c1, yr1c1):
""" Draw a 3 by 3 grid """
gridSize = cellSize * 3 # Grid size
for i in range (1): # Grid Rows # Binderooney-related Solution Stuff ...
xul = xr1c1
yul = yr1c1 + (i * gridSize)
xlr = xul + gridSize
ylr = yul + gridSize
for j in range(1): # Grid Columns # Binderooney-related Solution Stuff ...
self.gridL [(i * 1) + j] = self.canvas.create_rectangle( # Binderooney-related Solution Stuff ...
xul, yul, xlr, ylr,
outline=self.lineColor, width=self.gridLineWidth
)
xul += gridSize
xlr += gridSize
self.canvas.pack()
def setupGrid(self): # Binderooney-related Solution Stuff ...
""" setup the grid """
self.drawCells(self.cellSize, self.xr1c1, self.yr1c1)
self.drawGrid(self.cellSize, self.xr1c1, self.yr1c1)
# Toss in a quit button
pbx = 61
pby = 210
pbw = 75
pbh = 25
pbp = 10
self.quitBtn = Button(
self.frame,
text = 'Quit',
activebackground = self.hlColor,
font = self.buttonTextFont,
bg = self.fillColor,
command = lambda: quit()
)
self.quitBtn.place(
x=pbx,
y=pby,
width=pbw,
height=pbh
)
def cellOutline(self, x1, y1, x2, y2, color):
""" Display an outline around the cell that is clicked """
self.lastCell = self.canvas.create_rectangle(
x1, y1, x2, y2, outline=color, width=self.cellLineWidth
)
self.cellSelectedFlag = True
self.last_x1 = x1
self.last_y1 = y1
self.last_x2 = x2
self.last_y2 = y2
self.canvas.pack()
return self.lastCell
def cellHighlight(self, x1, y1, x2, y2, color):
""" Display an outline around the cell that is clicked """
self.lastCell = self.canvas.create_rectangle(
x1, y1, x2, y2, fill=color, width=self.cellLineWidth
)
self.cellSelectedFlag = True
self.last_x1 = x1
self.last_y1 = y1
self.last_x2 = x2
self.last_y2 = y2
self.canvas.pack()
return self.lastCell
def writeEntryNumber(self, num, x, y, fgCol, bgCol):
""" Write the cell's entry number """
entryNumText = " "
entryNumText = str(num)
self.numberLabels[self.calcCellFromXYCoords(x, y)].configure(
text= entryNumText,
font= self.numberFont,
foreground= fgCol,
background= bgCol
)
self.numberLabels[self.calcCellFromXYCoords(x, y)].place(
x=x + 15,
y=y + 15,
width=self.numberFontWidth,
height=self.numberFontHeight
)
def calcCellFromXYCoords(self, x, y):
""" Calculate the cell from the provided x and y coordinates """
row = ((y - self.yr1c1) / self.cellSize)
col = ((x - self.xr1c1) / self.cellSize)
self.cell = (((row ) * 3) + col) # Binderooney-related Solution Stuff ...
return self.cell
def tell_it(self, btn, x, y):
""" Display the mouse button clicked and its coordinates """
global mouseClickNumber
print "In tell_it(), mouse click number %d, button %d, coordinates (%d, %d)" % \
(mouseClickNumber, btn, x, y)
mouseClickNumber += 1
def binderooney(self, btn, x, y, labelIndex): # Binderooney-related Solution Stuff ...
""" Test-bed for the cell coordinates binding solution! """
print "In binderooney(), labelIndex is %r!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" % labelIndex # Binderooney-related Solution Stuff ...
cx = self.numberLabelsCellCoords[labelIndex] [0] # Binderooney-related Solution Stuff ...
cy = self.numberLabelsCellCoords[labelIndex] [1] # Binderooney-related Solution Stuff ...
self.tell_it(btn, cx, cy) # Binderooney-related Solution Stuff ...
if ((cx >= self.xr1c1) and (cx <= ((self.xr1c1 - 2) + (3 * self.cellSize))) and (cy >= self.yr1c1) and (cy <= ((self.yr1c1 - 2) + (3 * self.cellSize)))): # Binderooney-related Solution Stuff ...
self.button = btn # Binderooney-related Solution Stuff ...
self.xcoord = x # Binderooney-related Solution Stuff ...
self.ycoord - y # Binderooney-related Solution Stuff ...
self.drawCells(self.cellSize, self.xr1c1, self.yr1c1) # Binderooney-related Solution Stuff ...
x1 = ((((x + self.xr1c1) / self.cellSize) - 1) * self.cellSize) + self.xr1c1 # Binderooney-related Solution Stuff ...
y1 = ((((y + self.yr1c1) / self.cellSize) - 1) * self.cellSize) + self.yr1c1 # Binderooney-related Solution Stuff ...
x2 = x1 + self.cellSize # Binderooney-related Solution Stuff ...
y2 = y1 + self.cellSize # Binderooney-related Solution Stuff ...
self.rw = ((y + self.yr1c1) / self.cellSize) # Binderooney-related Solution Stuff ...
self.col = ((x + self.xr1c1) / self.cellSize) # Binderooney-related Solution Stuff ...
self.cel = (((self.rw ) * 3) + self.col) # Binderooney-related Solution Stuff ...
self.grw = ((y + self.yr1c1 + (2 * self.cellSize)) / self.gridSize) # Binderooney-related Solution Stuff ...
self.gcol = ((x + self.xr1c1 + (2 * self.cellSize)) / self.gridSize) # Binderooney-related Solution Stuff ...
self.grid = (((self.grw - 1) * 3) + self.gcol) # Binderooney-related Solution Stuff ...
if btn == 1: # Binderooney-related Solution Stuff ...
self.drawGrid(self.cellSize, self.xr1c1, self.yr1c1) # Binderooney-related Solution Stuff ...
self.cellOutline(cx, cy, cx+self.cellSize, cy+self.cellSize, self.outlineColor) # Binderooney-related Solution Stuff ...
if btn == 1: # Binderooney-related Solution Stuff ...
self.writeEntryNumber(1, cx, cy, self.fgColor, self.bgColor) # Binderooney-related Solution Stuff ...
elif btn == 3: # Binderooney-related Solution Stuff ...
self.cellHighlight(cx, cy, cx+self.cellSize, cy+self.cellSize, self.highlightColor) # Binderooney-related Solution Stuff ...
self.cellOutline(cx, cy, cx+self.cellSize, cy+self.cellSize, self.outlineColor) # Binderooney-related Solution Stuff ...
self.drawGrid(self.cellSize, self.xr1c1, self.yr1c1) # Binderooney-related Solution Stuff ...
self.cellOutline(cx, cy, cx+self.cellSize, cy+self.cellSize, self.outlineColor) # Binderooney-related Solution Stuff ...
return self.cell # Binderooney-related Solution Stuff ...
def mainCallbackFunction(self, btn, x, y):
"""
# On left mouse click, return cell in which it was clicked, drawing a
# red boundary around the cell; on right click, return the cell in which
# it was clicked, removing the red boundary around the clicked cell
"""
if ((x >= self.xr1c1) and (x <= ((self.xr1c1 - 2) + (3 * self.cellSize)))) and \
(y >= (self.yr1c1) and (y <= ((self.yr1c1 - 2) + (3 * self.cellSize)))): # Binderooney-related Solution Stuff ...
print "in mainCallbackFunction(), cell is %r" % (self.calcCellFromXYCoords(x, y)) # Binderooney-related Solution Stuff ...
self.tell_it(btn, x, y)
self.button = btn
self.xcoord = x
self.ycoord - y
self.drawCells(self.cellSize, self.xr1c1, self.yr1c1)
x1 = ((((x + self.xr1c1) / self.cellSize) - 1) * self.cellSize) + self.xr1c1
y1 = ((((y + self.yr1c1) / self.cellSize) - 1) * self.cellSize) + self.yr1c1
x2 = x1 + self.cellSize
y2 = y1 + self.cellSize
self.rw = ((y + self.yr1c1) / self.cellSize)
self.col = ((x + self.xr1c1) / self.cellSize)
self.cel = (((self.rw ) * 3) + self.col) # Binderooney-related Solution Stuff ...
self.grw = ((y + self.yr1c1 + (2 * self.cellSize)) / self.gridSize)
self.gcol = ((x + self.xr1c1 + (2 * self.cellSize)) / self.gridSize)
self.grid = (((self.grw - 1) * 3) + self.gcol) # Binderooney-related Solution Stuff ...
if btn == 1:
self.drawGrid(self.cellSize, self.xr1c1, self.yr1c1)
self.cellOutline(x1, y1, x2, y2, self.outlineColor)
if btn == 1:
self.writeEntryNumber(1, x1, y1, self.fgColor, self.bgColor)
elif btn == 3:
self.cellHighlight(x1, y1, x2, y2, self.highlightColor)
self.cellOutline(x1, y1, x2, y2, self.outlineColor)
self.drawGrid(self.cellSize, self.xr1c1, self.yr1c1)
self.cellOutline(x1, y1, x2, y2, self.outlineColor)
return self.cell
# Cell and Grid sizes, X amd Y Coordinates of Row 1 Col 1 (Upper Left Position)
cellSize = 50; xr1c1 = 25; yr1c1 = 25
# Instantiate the Label POC class
lPOC = LabelsAsEventFodderPOC(cellSize, xr1c1, yr1c1) # Binderooney-related Solution Stuff ...
# Loop-Dee-Doo
if __name__ == '__main__':
lPOC.root.mainloop()
答案 1 :(得分:0)
你可以使用
label.bind("<MouseButton1Down>",function)
代替