tkinter无法分配文本变量

时间:2014-01-09 00:53:38

标签: python tkinter

问题是我的输入弹出窗口必须是一个顶层窗口,所以将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

1 个答案:

答案 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根),而不是调用mainloopquit (因为您已经在由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命令中所做的那样),但我尝试按照您在代码中设置的样式而不是重写所有内容。