python 和 Tkinter 中的逻辑:如何无休止地制作 window 运行
Logic within python and Tkinter: how to make a window run endlessly
我目前正在尝试使用 Tkinter 构建战舰游戏。然而,我陷入了僵局,因为我无法正确地制作程序 "wait" 来获得答案并显示 Tkinter window。
我的想法是,只要按下提交按钮,就会将一个值设置为 true。只要该值为 false,程序就会循环执行 while 循环。触发此值时,将给出下一组操作,同时将该值设置回 false,并等待它再次变为 true。这是代码:
from Tkinter import *
import time
class Application(Frame):
def __init__(self,master):
self.user = False
Frame.__init__(self,master)
self.launch()
self.master = master
self.shiplist = []
self.board = [
["A",1],["B",1],["C",1],["D",1],["E",1],["F",1],["G",1],["H",1],["I",1],["J",1],
["A",2],["B",2],["C",2],["D",2],["E",2],["F",2],["G",2],["H",2],["I",2],["J",2],
["A",3],["B",3],["C",3],["D",3],["E",3],["F",3],["G",3],["H",3],["I",3],["J",3],
["A",4],["B",4],["C",4],["D",4],["E",4],["F",4],["G",4],["H",4],["I",4],["J",4],
["A",5],["B",5],["C",5],["D",5],["E",5],["F",5],["G",5],["H",5],["I",5],["J",5],
["A",6],["B",6],["C",6],["D",6],["E",6],["F",6],["G",6],["H",6],["I",6],["J",6],
["A",7],["B",7],["C",7],["D",7],["E",7],["F",7],["G",7],["H",7],["I",7],["J",7],
["A",8],["B",8],["C",8],["D",8],["E",8],["F",8],["G",8],["H",8],["I",8],["J",8],
["A",9],["B",9],["C",9],["D",9],["E",9],["F",9],["G",9],["H",9],["I",9],["J",9],
["A",10],["B",10],["C",10],["D",10],["E",10],["F",10],["G",10],["H",10],["I",10],["J",10],
]
self.letters = [["A",1],["B",2],["C",3],["D",4],["E",5],["F",6],["G",7],["H",8],["I",9],["J",10]]
def launch(self):
self.pack(fill=BOTH, expand=1)
Label(self, text="Your Board").grid(sticky=W,row = 0, column = 0)
Label(self, text="Enemy Board").grid(sticky=W, row = 0,column = 2)
canvas1 = Canvas(self)
canvas1.create_rectangle(2,2,250,250,outline= "black",fill = "white")
canvas1.grid(row=1, column=0, columnspan=2, rowspan=2)
canvas2 = Canvas(self)
canvas2.create_rectangle(2,2,250,250,outline= "black",fill = "white")
canvas2.grid(row=1, column=2, columnspan=2, rowspan=2)
self.actionLabel = Label(self,text = "Currently Placing:")
self.actionLabel.grid(row = 3,column= 0,sticky = W)
self.infoLabel1 = Label(self,text ="")
self.infoLabel1.grid(row = 4,column = 0)
self.infoLabel2 = Label(self,text = "")
self.infoLabel2.grid(row=5,column=0)
self.userinput = Entry(self,text = "Write here")
self.userinput.grid(row=6,column=0)
Button(self,text = "Submit",command = self.action).grid(row = 6,column = 1,sticky = W)
self.errorlabel = Label(self,text = "")
self.errorlabel.grid(row=7,column=0)
self.request_ships()
def action(self):
value = self.userinput.get()
self.user = True
print "action successful"
def request_ship(self,allegiance,name,size):
print allegiance,name,size
ship = [name,size]
error = False
if allegiance == "player":
print "here"
while error == False:
self.user = False
text1 = name + "Size: "+ str(size) + " cells."
self.infoLabel1.configure(text = text1)
self.infoLabel2.configure(text = "Would you like for your ship to be vertical or horizontal? v/h:")
if self.user == True:
if value != "vertical" and value != "horizontal" and value != "h" and value != "v":
self.errorlabel.configure(text = "Error! Incorrect Format!")
error = False
else:
self.user = False
if value == "h":
ship += value
self.infoLabel2.configure(text = "Please enter the leftmost coordinate of where you want to place your ship:")
if self.user== True:
if len(value) > 1 and len(value) <= 3 and (value[0] == "A"
or value[0] == "B" or value[0] == "C" or value[0] == "D"
or value[0] == "E" or value[0] == "F" or value[0] == "G"
or value[0] == "H" or value[0] == "I" or value[0] == "J") and (value[1] == "1"
or value[1] == "2" or value[1] == "3" or value[1] == "4"
or value[1] == "5" or value[1] == "6" or value[1] == "7"
or value[1] == "8" or value[1] == "9" or value[1] == "10"):
for i in range(len(self.board)):
if self.board[i][0] == value[0] and self.board[i][0] == value[1:]:
num = 0
for i in size:
coord+= i + num
num += 1
print ship
def request_ships(self):
print "request ships works"
self.request_ship("player","Aircraft Carrier",5)
def grid(self,gridinfo,shipinfo):
coord = 0
cellnum = 0
for number in range(100):
cell = Canvas(self)
for ship in shipinfo:
## if #####
print "tt"
cell.create_rectangle(coord,coord,25,25,outline="black",fill=color)
def main():
root = Tk()
app = Application(root)
app.geometry = ("1000x1000")
root.title("Battleship")
root.mainloop()
main()
但是,问题是 window 在加载 request_ships 函数时永远不会出现,因为它在 while 循环中无休止地运行。关于如何解决此问题的任何提示?
有些事情需要研究:您有 while error == False
,但在循环中对 error
的唯一引用是将 False
分配给它。在循环中,您分配 self.user = False
,但随后循环中的几乎所有内容都依赖于进入 if self.user == True
。您将 self.userinput.get()
分配给 local 变量 value
而不是实例变量。您应该更多地使用 in
运算符以避免进行许多单独的比较。您只检查了 if self.user == True
内的大型 if
语句中的 value[1]
。您可以直接引用该值,而不是检查值是否等于 True
或 False
,例如if self.user:
,因为表达 True == True
的另一种方式就是 True
(除非该变量具有不确定的类型并且您确实需要检查它是否是 True
或者,比如说,非空字符串)。您正在检查 Entry
框中的内容,然后才真正准备好 - 您应该将 request_ships()
放入某些 Button
的命令中,或者至少用 after()
等一下。您正在检查 self.board[i][0]
是否等于 value[0]
和 value[1]
,只有当用户输入无效的内容(如 AA
时才会为真)。如果我们修复它以同时检查 self.board[i][1]
,它仍然无法工作,因为 Entry
小部件中的所有内容都是字符串,必须将其转换为 int
。您不能将字符串连接到 list
- 使用 append()
。从单个函数中一个接一个地检查 vertical/horizontal、位置等将 运行 变成问题,因为您永远不会等待用户输入不同的值。
这里是 request_ship()
的示例,其中实施了其中一些更改,因此您可以了解去哪里:
def request_ship(self,allegiance,name,size):
print allegiance,name,size
ship = [name,size]
error = True
if allegiance == "player":
print "here"
text1 = name + "Size: "+ str(size) + " cells."
self.infoLabel1.configure(text = text1)
self.infoLabel2.configure(text = "Would you like for your ship to be vertical or horizontal? v/h:")
if self.user:
if self.value not in ("vertical", "horizontal", "h", "v"):
self.errorlabel.configure(text = "Error! Incorrect Format!")
else:
self.user = False
if self.value == "h":
ship.append(self.value)
self.infoLabel2.configure(text = "Please enter the leftmost coordinate of where you want to place your ship:")
if self.user:
try:
v1 = int(self.value[1:])
except ValueError:
pass
if 1 < len(self.value) <= 3 and (self.value[0] in "ABCDEFGHIJ") and (v1 in range(1,11)):
for i in range(len(self.board)):
if self.board[i][0] == self.value[0] and self.board[i][1] == v1:
num = 0
for i in size:
coord+= i + num
num += 1
self.user = False
请注意,上面的代码既不完整,也不是使您的程序正常工作的替代品。您的代码将需要进行一些认真的重组,以处理作为 GUI 程序与命令行程序的区别。
我目前正在尝试使用 Tkinter 构建战舰游戏。然而,我陷入了僵局,因为我无法正确地制作程序 "wait" 来获得答案并显示 Tkinter window。 我的想法是,只要按下提交按钮,就会将一个值设置为 true。只要该值为 false,程序就会循环执行 while 循环。触发此值时,将给出下一组操作,同时将该值设置回 false,并等待它再次变为 true。这是代码:
from Tkinter import *
import time
class Application(Frame):
def __init__(self,master):
self.user = False
Frame.__init__(self,master)
self.launch()
self.master = master
self.shiplist = []
self.board = [
["A",1],["B",1],["C",1],["D",1],["E",1],["F",1],["G",1],["H",1],["I",1],["J",1],
["A",2],["B",2],["C",2],["D",2],["E",2],["F",2],["G",2],["H",2],["I",2],["J",2],
["A",3],["B",3],["C",3],["D",3],["E",3],["F",3],["G",3],["H",3],["I",3],["J",3],
["A",4],["B",4],["C",4],["D",4],["E",4],["F",4],["G",4],["H",4],["I",4],["J",4],
["A",5],["B",5],["C",5],["D",5],["E",5],["F",5],["G",5],["H",5],["I",5],["J",5],
["A",6],["B",6],["C",6],["D",6],["E",6],["F",6],["G",6],["H",6],["I",6],["J",6],
["A",7],["B",7],["C",7],["D",7],["E",7],["F",7],["G",7],["H",7],["I",7],["J",7],
["A",8],["B",8],["C",8],["D",8],["E",8],["F",8],["G",8],["H",8],["I",8],["J",8],
["A",9],["B",9],["C",9],["D",9],["E",9],["F",9],["G",9],["H",9],["I",9],["J",9],
["A",10],["B",10],["C",10],["D",10],["E",10],["F",10],["G",10],["H",10],["I",10],["J",10],
]
self.letters = [["A",1],["B",2],["C",3],["D",4],["E",5],["F",6],["G",7],["H",8],["I",9],["J",10]]
def launch(self):
self.pack(fill=BOTH, expand=1)
Label(self, text="Your Board").grid(sticky=W,row = 0, column = 0)
Label(self, text="Enemy Board").grid(sticky=W, row = 0,column = 2)
canvas1 = Canvas(self)
canvas1.create_rectangle(2,2,250,250,outline= "black",fill = "white")
canvas1.grid(row=1, column=0, columnspan=2, rowspan=2)
canvas2 = Canvas(self)
canvas2.create_rectangle(2,2,250,250,outline= "black",fill = "white")
canvas2.grid(row=1, column=2, columnspan=2, rowspan=2)
self.actionLabel = Label(self,text = "Currently Placing:")
self.actionLabel.grid(row = 3,column= 0,sticky = W)
self.infoLabel1 = Label(self,text ="")
self.infoLabel1.grid(row = 4,column = 0)
self.infoLabel2 = Label(self,text = "")
self.infoLabel2.grid(row=5,column=0)
self.userinput = Entry(self,text = "Write here")
self.userinput.grid(row=6,column=0)
Button(self,text = "Submit",command = self.action).grid(row = 6,column = 1,sticky = W)
self.errorlabel = Label(self,text = "")
self.errorlabel.grid(row=7,column=0)
self.request_ships()
def action(self):
value = self.userinput.get()
self.user = True
print "action successful"
def request_ship(self,allegiance,name,size):
print allegiance,name,size
ship = [name,size]
error = False
if allegiance == "player":
print "here"
while error == False:
self.user = False
text1 = name + "Size: "+ str(size) + " cells."
self.infoLabel1.configure(text = text1)
self.infoLabel2.configure(text = "Would you like for your ship to be vertical or horizontal? v/h:")
if self.user == True:
if value != "vertical" and value != "horizontal" and value != "h" and value != "v":
self.errorlabel.configure(text = "Error! Incorrect Format!")
error = False
else:
self.user = False
if value == "h":
ship += value
self.infoLabel2.configure(text = "Please enter the leftmost coordinate of where you want to place your ship:")
if self.user== True:
if len(value) > 1 and len(value) <= 3 and (value[0] == "A"
or value[0] == "B" or value[0] == "C" or value[0] == "D"
or value[0] == "E" or value[0] == "F" or value[0] == "G"
or value[0] == "H" or value[0] == "I" or value[0] == "J") and (value[1] == "1"
or value[1] == "2" or value[1] == "3" or value[1] == "4"
or value[1] == "5" or value[1] == "6" or value[1] == "7"
or value[1] == "8" or value[1] == "9" or value[1] == "10"):
for i in range(len(self.board)):
if self.board[i][0] == value[0] and self.board[i][0] == value[1:]:
num = 0
for i in size:
coord+= i + num
num += 1
print ship
def request_ships(self):
print "request ships works"
self.request_ship("player","Aircraft Carrier",5)
def grid(self,gridinfo,shipinfo):
coord = 0
cellnum = 0
for number in range(100):
cell = Canvas(self)
for ship in shipinfo:
## if #####
print "tt"
cell.create_rectangle(coord,coord,25,25,outline="black",fill=color)
def main():
root = Tk()
app = Application(root)
app.geometry = ("1000x1000")
root.title("Battleship")
root.mainloop()
main()
但是,问题是 window 在加载 request_ships 函数时永远不会出现,因为它在 while 循环中无休止地运行。关于如何解决此问题的任何提示?
有些事情需要研究:您有 while error == False
,但在循环中对 error
的唯一引用是将 False
分配给它。在循环中,您分配 self.user = False
,但随后循环中的几乎所有内容都依赖于进入 if self.user == True
。您将 self.userinput.get()
分配给 local 变量 value
而不是实例变量。您应该更多地使用 in
运算符以避免进行许多单独的比较。您只检查了 if self.user == True
内的大型 if
语句中的 value[1]
。您可以直接引用该值,而不是检查值是否等于 True
或 False
,例如if self.user:
,因为表达 True == True
的另一种方式就是 True
(除非该变量具有不确定的类型并且您确实需要检查它是否是 True
或者,比如说,非空字符串)。您正在检查 Entry
框中的内容,然后才真正准备好 - 您应该将 request_ships()
放入某些 Button
的命令中,或者至少用 after()
等一下。您正在检查 self.board[i][0]
是否等于 value[0]
和 value[1]
,只有当用户输入无效的内容(如 AA
时才会为真)。如果我们修复它以同时检查 self.board[i][1]
,它仍然无法工作,因为 Entry
小部件中的所有内容都是字符串,必须将其转换为 int
。您不能将字符串连接到 list
- 使用 append()
。从单个函数中一个接一个地检查 vertical/horizontal、位置等将 运行 变成问题,因为您永远不会等待用户输入不同的值。
这里是 request_ship()
的示例,其中实施了其中一些更改,因此您可以了解去哪里:
def request_ship(self,allegiance,name,size):
print allegiance,name,size
ship = [name,size]
error = True
if allegiance == "player":
print "here"
text1 = name + "Size: "+ str(size) + " cells."
self.infoLabel1.configure(text = text1)
self.infoLabel2.configure(text = "Would you like for your ship to be vertical or horizontal? v/h:")
if self.user:
if self.value not in ("vertical", "horizontal", "h", "v"):
self.errorlabel.configure(text = "Error! Incorrect Format!")
else:
self.user = False
if self.value == "h":
ship.append(self.value)
self.infoLabel2.configure(text = "Please enter the leftmost coordinate of where you want to place your ship:")
if self.user:
try:
v1 = int(self.value[1:])
except ValueError:
pass
if 1 < len(self.value) <= 3 and (self.value[0] in "ABCDEFGHIJ") and (v1 in range(1,11)):
for i in range(len(self.board)):
if self.board[i][0] == self.value[0] and self.board[i][1] == v1:
num = 0
for i in size:
coord+= i + num
num += 1
self.user = False
请注意,上面的代码既不完整,也不是使您的程序正常工作的替代品。您的代码将需要进行一些认真的重组,以处理作为 GUI 程序与命令行程序的区别。