问题是我的输入弹出窗口必须是一个顶层窗口,所以将tk.Tk()更改为tk.Toplevel()使其工作正常;)
#Josh Harrison
#3008088
from graphics import *
from random import randrange
import winsound, sys
#scale for size of squares
scale = 50
#setupBoard sets up the board with a randomly generated puzzle
def setupBoard(size, color):
board = [[[0, Rectangle(Point(scale*.05,scale*.05),Point(scale*.95,scale*.95))] for x in range(size)] for x in range(size)]
for x in range(size):
for y in range(size):
board[x][y][1] = Rectangle(Point(x*scale+scale*.05,y*scale+scale*.05),Point(x*scale+scale*.95,y*scale+scale*.95))
for i in range(1):
selectTile(board, Point(randrange(size)*scale,randrange(size)*scale), size, color)
return board
#selectTile does the action for selecting tiles
#set color to 0 for black and white and 1 for color rotation
def selectTile(board,point,size,color):
#sets value switch according to if colors are desired or not
if color == 1:
valueSwitch = colorSwitch
else:
valueSwitch = bwSwitch
x = int(point.getX()/scale)
y = int(point.getY()/scale)
#temp is made to preserve the selected tiles state
temp = board[x][y][0]
#swap all square values
#note try and except are also looped
for i in range(3):
for z in range(3):
try:
board[x-1+i][y-1+z][0] = valueSwitch(board[x-1+i][y-1+z][0])
except:
#overlap fix for x maxed
if x == size - 1 and y != size - 1:
board[0][y-1+z][0] = valueSwitch(board[0][y-1+z][0])
#overlap fix for y maxed
if y == size - 1 and x != size - 1:
board[x-1+i][0][0] = valueSwitch(board[x-1+i][0][0])
#overlap fix for bottom right corner
if x == size - 1 and y == size - 1:
board[0][0][0] = valueSwitch(board[0][0][0])
for a in range(2):
board[0][size-a-1][0] = valueSwitch(board[0][size-a-1][0])
board[size-a-1][0][0] = valueSwitch(board[size-a-1][0][0])
#give middle square initial value again
board[x][y][0] = temp
#updateBoard updates the squares to the right colour according to value
def updateBoard(board, size, count):
if count != 0:
winsound.Beep(333, 200)
for x in range(size):
for y in range(size):
if board[x][y][0] == 0:
board[x][y][1].setFill('white')
elif board[x][y][0] == 1:
board[x][y][1].setFill('yellow')
elif board[x][y][0] == 2:
board[x][y][1].setFill('green')
elif board[x][y][0] == 3:
board[x][y][1].setFill('blue')
elif board[x][y][0] == 4:
board[x][y][1].setFill('black')
#drawBoard draws the initial board
def drawBoard(size, board, win):
for x in range(size):
for y in range(size):
board[x][y][1].draw(win)
return
#checks to see if board is white(Winning condition)
def winGame(board, size):
#steps through all x and y values
for x in range(size):
for y in range(size):
if board[x][y][0] != 0:
return 0
#returns true if no black squares are found
return 1
#valueSwitch() just makes switching values easier by checking values and selecting the appropriate one
def colorSwitch(value):
if value == 4:
return 0
else:
return value + 1
#bwSwitch only selects from black and white value
def bwSwitch(value):
if value == 4:
return 0
else:
return 4
#winMessage() displaying a winning message graphic
def winMessage(size, scale, win):
gameMessage = Text(Point(size*scale/2,size*scale/2),"You have won logic!")
gameMessage.setSize(int(scale/4))
gameMessage.setTextColor('red')
gameMessage.draw(win)
#gameMenu() is a menu to select game size
def gameMenu():
win = GraphWin("Logic Menu", 400, 600)
win.setBackground('light blue')
board = [[[Text(Point(0,0),'bleh'),Rectangle(Point(0,0),Point(200,200))] for y in range(3)] for x in range(2)]
#Making and drawing the buttons ;)
for x in range(2):
for y in range(3):
board[x][y][1] = Rectangle(Point(x*200+200*.05,y*200+200*.05),Point(x*200+200*.95,y*200+200*.95))
board[x][y][1].draw(win)
board[0][0][0] = Text(board[0][0][1].getCenter(), 'Click for 5x5 puzzle')
board[1][0][0] = Text(board[1][0][1].getCenter(), 'Click for 7x7 puzzle')
board[0][1][0] = Text(board[0][1][1].getCenter(), 'Click for 9x9 puzzle')
board[1][1][0] = Text(board[1][1][1].getCenter(), 'Click for 12x12 puzzle')
board[0][2][0] = Text(board[0][2][1].getCenter(), 'Click to toggle colors')
board[1][2][0] = Text(board[1][2][1].getCenter(), 'Highscores!')
#drawing button options
for x in range(2):
for y in range(3):
board[x][y][0].draw(win)
#check to see what button is pressed
point = win.getMouse()
x = int(point.getX()/200)
y = int(point.getY()/200)
#colors is either 1 for colors or 0 for no colors
colors = 0
#turning colors on and off
#board[0][2][1] is the rectangle for colors
while y == 2:
if x == 0:
if colors == 0:
winsound.Beep(400, 200)
colors = 1
board[0][2][1].setFill('green')
else:
winsound.Beep(363, 200)
colors = 0
board[0][2][1].setFill('')
else:
winsound.Beep(400, 200)
board[1][2][1].setFill('red')
#board is just passed in for a smother button click effect not necessary for functionality
highscore_board(board)
point = win.getMouse()
x = int(point.getX()/200)
y = int(point.getY()/200)
board[x][y][1].setFill('red')
winsound.Beep(400, 200)
win.close()
if x == 0 and y == 0:
return 5 , colors
if x == 1 and y == 0:
return 7 , colors
if x == 0 and y == 1:
return 9 , colors
if x == 1 and y == 1:
return 12 , colors
return 5 , colors
#highscore() checks to see if player has highscore and outputs a highscore to a text file
def highscore(count):
#checks to see if highscore file exists
try:
scoreInfo = [line.strip() for line in open('highscore.txt')]
#remove all spacing
for i in range(scoreInfo.count('')):
scoreInfo.remove('')
scoreInfo[1]
scores = int(len(scoreInfo)/2)
newEntry = 0
#creates new highscore file is none exist
except:
win = GraphWin("Highscore!", 400, 200)
gameMessage = Text(Point(200,100),"Please input name: ")
gameMessage.setSize(int(scale/4))
gameMessage.setTextColor('red')
gameMessage.draw(win)
name=inputWin()
f = open('highscore.txt', 'w')
f.write(name)
f.write('\n'+str(count))
f.close()
gameMessage.setText(name+': '+str(count)+' - saved!')
time.sleep(1)
win.close()
return
#if there is a new highscore it is added at the beginning of the file
for i in range(scores):
if scores < 10 or count < int(scoreInfo[i*2+1]):
win = GraphWin("Highscore!", 400, 200)
gameMessage = Text(Point(200,100),"Please input name: ")
gameMessage.setSize(int(scale/4))
gameMessage.setTextColor('red')
gameMessage.draw(win)
name=inputWin()
f = open('highscore.txt', 'w')
#max 10 highscores 9 + new highscore
if scores >= 10:
scores = 9
for i in range(scores):
try:
if count < int(scoreInfo[i*2+1]) and not newEntry:
f.write(name)
f.write('\n'+str(count))
f.write('\n\n\n')
newEntry = 1
f.write(scoreInfo[i*2])
f.write('\n')
f.write(scoreInfo[i*2+1])
f.write('\n\n\n')
except:
pass
#if no entries have been added
#the new value is then added to the end
if newEntry == 0:
f.write(name)
f.write('\n'+str(count))
f.write('\n\n\n')
f.close()
gameMessage.setText(name+': '+str(count)+' - saved!')
time.sleep(1)
win.close()
break
pass
#board is just passed in for a smother button click effect not necessary for functionality
def highscore_board(board):
win = GraphWin("Highscores", 200, 500)
win.setBackground('light green')
try:
scoreInfo = [line.strip() for line in open('highscore.txt')]
#remove all spacing
for i in range(scoreInfo.count('')):
scoreInfo.remove('')
Text(Point(50,20),"Highscores:").draw(win)
for i in range(10):
Text(Point(10,45*i+60),str(i+1)+'. ').draw(win)
try:
Text(Point(60,45*i+60),scoreInfo[i*2]).draw(win)
Text(Point(170,45*i+60),scoreInfo[1+i*2]).draw(win)
except:
pass
except:
Text(Point(100,250),"no scores yet.").draw(win)
time.sleep(.05)
board[1][2][1].setFill('')
#prevent program crash if scoreboard is exited through os
try:
win.getMouse()
winsound.Beep(363, 200)
win.close()
except:
winsound.Beep(363, 200)
import tkinter as tk
def getString(ment,mGui):
global hsname
hsname = ment.get()
mGui.destroy()
mGui.quit()
def inputWin():
mGui = tk.Tk()
ment = tk.StringVar()
mGui.title('New Highscore!')
mEntry = tk.Entry(mGui,textvariable=ment).pack(side=tk.LEFT)
mbutton = tk.Button(mGui,text='OK',command=lambda:getString(ment,mGui),fg='red',bg='blue').pack(side=tk.RIGHT)
mGui.mainloop()
return hsname
这是不会工作的部分
import tkinter as tk
def getString(ment,mGui):
global hsname
hsname = ment.get()
mGui.destroy()
mGui.quit()
def inputWin():
mGui = tk.Tk()
ment = tk.StringVar()
mGui.title('New Highscore!')
mEntry = tk.Entry(mGui,textvariable=ment)
mEntry.pack(side=tk.LEFT)
mbutton = tk.Button(mGui,text='OK',command=lambda:getString(ment,mGui),fg='red',bg='blue')
mbutton.pack(side=tk.RIGHT)
mGui.mainloop()
return hsname
我只是在试图为游戏增加一个更高的视觉效果我做了这个代码它本身工作正常但是当我导入它甚至将整个代码复制到带有其他功能的py文件时它只是停止分配任何我不理解的值:/
感谢任何帮助
这是运行游戏的代码
#Josh Harrison
#3008088
from logic_game import *
def playGame():
option = gameMenu()
size = option[0]
color = option[1]
win = GraphWin("Logic Game", size*scale, size*scale)
win.setBackground('light pink')
board = setupBoard(size, color)
drawBoard(size, board, win)
countText = Text(Point(scale,scale/2),'moves: 0')
countText.setTextColor('red')
countText.draw(win)
count = 0
while not winGame(board, size):
updateBoard(board, size, count)
selectTile(board, win.getMouse(), size, color)
count += 1
countText.setText('moves: ' + str(count))
updateBoard(board, size, count)
winMessage(size, scale, win)
highscore(count)
#pauses the window and waits for click before continuing
win.getMouse()
#closes the window "win"
win.close()
playGame()
用于graphics.py的链接 http://mcsp.wartburg.edu/zelle/python/graphics.py
答案 0 :(得分:1)
我不明白你的问题到底出了什么问题,但我很确定我知道问题是什么。
您的大部分程序都使用一些名为graphics
的库来运行GUI。然后,您尝试使用Tkinter
在同一程序中运行另一个GUI。
我不知道那个graphics
库是什么,但除非它建立在Tkinter之上,或者专门设计用于Tkinter,否则这不太可行。他们都将尝试负责您的程序的唯一GUI,处理来自用户/窗口系统的所有事件,等等。其中一个或两个都会失败。
事实上,即使graphics
构建在Tkinter
之上或旨在与之协同工作,也可以在mainloop
上调用Tkinter
在您退出mainloop
之前,窗口最多会冻结GUI的其余部分,最坏的情况是打破其他GUI依赖的外部mainloop
。
从我从其他代码中可以看到,graphics
库似乎有足够的功能来执行您尝试使用Tkinter
做的所有事情 - 创建一个新窗口,在其上放置一些小部件,按一下按钮。那么,为什么不使用它?
现在您已经向我们提供了您正在使用的graphics
库的链接...它看起来像Tkinter
周围的薄包装。这意味着您应该能够轻松地集成它们。您只需要创建一个新的Toplevel
而不是根窗口(因为graphics
已经创建了Tkinter
根),而不是调用mainloop
或quit
(因为您已经在由Tkinter
创建的graphics
主循环中。
由于你还没有给我们SSCCE我可以运行和破解,我在graphics
文档的第一个例子中建立了我自己的超简单版本,您尝试做的事情,还展示了如何与graphics
代码中的Tkinter
窗口进行互动。
from graphics import *
import Tkinter as tk
def getString(ment,mGui):
global win
print(ment.get())
mGui.destroy()
win.close()
def inputWin():
global hsname
mGui = tk.Toplevel()
ment = tk.StringVar()
mGui.title('New Highscore!')
tk.Entry(mGui,textvariable=ment).pack(side=tk.LEFT)
tk.Button(mGui,text='OK',command=lambda:getString(ment,mGui),fg='red',bg='blue').pack(side=tk.RIGHT)
win.getMouse()
def main():
global win
win = GraphWin("My Circle", 100, 100)
c = Circle(Point(50,50), 10)
c.draw(win)
win.getMouse() # Pause to view result
inputWin()
main()
最好重构这个来消除你的全局变量,要么使用OO设计(创建一个类,以便你可以将事物存储为实例属性),要么是功能设计(通过闭包传递值或使用{{烘焙它们) 1}} / lambda
,正如您在partial
命令中所做的那样),但我尝试按照您在代码中设置的样式而不是重写所有内容。