Why does my program require me to press the enter key before continuing (python tkinter) - python

I am making a program, using python tkinter, which simply prints some circles to the screen (I call it a board in this program). The program moves on to a different "board" once the mouse cursor moves over the button. The problem I have is that I simply call the "create_board" function 3 times using a for loop however in-between each iteration of the loop the "enter" key must be pressed. This isn't a massive deal but I'm trying to understand why and if there is a way to remove this requirement and have the next board load automatically.
I'm certain it has something to do with the tkinter windows and triggering the command "destroy" once the buttons (circles) are pressed however I'm still learning how to effectively use tkinter and any help would be very much appreciated.
def create_board(user_name, board):
# define the name of tkinter window
win = Tk()
# get the size of the displace for position and size calculations
app = wx.App(False)
w, h = wx.GetDisplaySize()
name = user_name
# define variables based on board number
if board == 0:
gx_pos = int(w/8) # locations of circles
gy_pos = int(h/8)
bx_pos = (w/8)*5
by_pos = (h/8)*5
board_num = str(1)
elif board == 1:
gx_pos = int(w/12)
gy_pos = int(h/12)
bx_pos = (w/6)*5
by_pos = (h/6)*5
board_num = str(2)
elif board == 2:
gx_pos = int(w/3)
gy_pos = int(h/3)
bx_pos = (w/3)*2
by_pos = (h/3)*2
board_num = str(3)
# records the mouse cursor position into a file along with time taken
def record_pos(x, y, board_num, s):
filename = name + "_" + board_num + ".txt"
try:
os.path.isfile('./'+filename)
except:
open(filename, 'r')
with open(filename, 'a') as f:
f.write(str(x) + "," + str(y) + "," + str(s) + "\n")
# determining when left click should be made
def mouse_pos():
flags, hcursor, (x, y) = win32gui.GetCursorInfo()
time_taken = time.time()
record_pos(x, y, board_num, time_taken)
mouse.click('left')
win.after(500, mouse_pos)
# wait 3 seconds before loading first board
time.sleep(3)
geometry = "%dx%d" % (w,h)
win.geometry(geometry)
win.attributes('-fullscreen', True)
win.config(cursor="circle")
# get the grid image
bg = Image.open("grid_image.png")
img = bg.resize((w, h))
grid_img=ImageTk.PhotoImage(img)
image_label = Label(win, image=grid_img)
image_label.place(x=0, y=0, relwidth=1, relheight=1)
# print an image of a green circle
gw = int(w/26)
gh = int(h/15)
g_circle = Image.open('green_circle.png')
g_img = g_circle.resize((gw,gh))
g_circle_image=ImageTk.PhotoImage(g_img)
g_label = Label(win, image=g_circle_image)
g_label.place(x = gx_pos,y = gy_pos)
g_btn = Button(win, image=g_circle_image, command = win.destroy)
g_btn.place(x= gx_pos , y= gy_pos)
# print an image of a blue circle
bw = int(w/26)
bh = int(h/15)
b_circle = Image.open('circle.png')
b_img = b_circle.resize((bw,bh))
b_circle_image=ImageTk.PhotoImage(b_img)
b_label = Label(win, image=b_circle_image)
b_label.place(x=bx_pos, y=by_pos)
b_btn = Button(win, image=b_circle_image, command = win.destroy)
b_btn.place(x=bx_pos, y=by_pos)
# record mouse position
mouse_pos()
win.mainloop()
EDIT: I added the simple for loop that I'm using to iterate through the boards.
for i in range(3):
create_board(user_name, i)

The issue was caused by using time.sleep() in tkinter. After removing this the code runs with out requiring an enter key press each time.

Related

Stop text from overlapping in Tkinter canvas

I am creating a game in the tkinter canvas which involves generating text (1 or 2 digit numbers) and I've gotten that to work, but I can't work out how to display them so they don't overlap. At the moment I have this:
import tkinter as tk
from tkinter import font
import random
BOX_SIZE = 300
class Game(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.config(bg = "white")
self.numBox = tk.Canvas(self, height = BOX_SIZE, width = BOX_SIZE , bg = "white", highlightthickness = 0)
self.numBox.pack(expand = True)
self.score = 0
self.numberSpawn()
def placeNumber(self, value):
validSpawn = False
attempts = 0
maxAttempt = False
while not validSpawn and not maxAttempt:
attempts += 1
if attempts > 20:
maxAttempt = True
attempts = 0
size = random.choice([24,36,48,72])
coord = [random.randint(40,BOX_SIZE - 40) for x in range(2)]
self.numBox.update()
pxSize = tk.font.Font(size = size, family = "Times New Roman").measure(value)
if len(str(value)) == 1:
secondCoords = [coord[0] + pxSize *2.5 , coord[1] + pxSize]
else:
secondCoords = [x + pxSize for x in coord]
if not self.numBox.find_overlapping(*coord, *secondCoords):
validSpawn = True
if not maxAttempt:
newTxt = self.numBox.create_text(*coord, font = ("Times New Roman",size), text = value)
def numberSpawn(self):
self.maxNum = random.randint(3,19)
self.placeNumber(self.maxNum)
for i in range(random.randint(4, 16)):
num = random.randint(0, self.maxNum-1)
self.placeNumber(num)
app = Game()
app.mainloop()
value is the number to be displayed, BOX_SIZE is the dimensions of the canvas. I tried using this to stop the text overlapping and this to find the pixel size of the text before creating it. Despite this, the text still overlaps like this:
I'm not sure how to fix this, or why it doesn't work as it is. Any help is appreciated.
Here is a solution for you:
import tkinter as tk
from tkinter import font
import random
def checkOverlap(R1, R2):
if (R1[0]>=R2[2]) or (R1[2]<=R2[0]) or (R1[3]<=R2[1]) or (R1[1]>=R2[3]):
return False
else:
return True
def go():
validSpawn = False
while not validSpawn:
value = random.randint(1,99)
size = random.choice([24,36,48,72])
coord = [random.randint(40,500 - 40) for x in range(2)]
new_number = canvas.create_text(*coord, font = ("Times New Roman",size),text=value)
new_box = canvas.bbox(new_number)
canvas.itemconfigure(new_number, state='hidden')
validSpawn = True
for i in canvas.items:
this_box = canvas.bbox(i)
if checkOverlap(this_box, new_box):
validSpawn = False
break
canvas.itemconfigure(new_number, state='normal')
canvas.items.append(new_number)
root = tk.Tk()
canvas = tk.Canvas(root, width = 500, height = 500, bg='white')
canvas.items = []
canvas.pack()
btn = tk.Button(root, text="Go", command=go)
btn.pack()
root.mainloop()
Instead of having it try to figure out how big the item was going to be, I just had it draw it, take its measurements, hide it and then look for overlaps and either delete it or show it based on the results. You will need to add in your maximum tries in there or it does start to get slower the more numbers there are on the screen. It should not draw a frame in the middle of a function so the user will never see it there while it is taking the measurement.
I also had it keep an array of all the number that are saved to the screen so I can loop through them and run my own overlapping function. That's just how I like to do it, you can go back to using find_overlapping and it should still work.
I think the problem is that:
you are giving up too soon, and
when you hit your limit of attempts, you add the text whether it overlaps or not
You should bump the number of attempts up considerably (maybe a few hundred), and then if the number exceeds the maximum then you shouldn't draw the text.
I think a better strategy might be to first draw the text item, then use the bbox of the method to compute the actual amount of space taken up by the item. Then, use that to find overlapping items. The just-created item will always overlap, but if the number of overlapping is greater than 1, pick new random coordinates.
For example, something like this perhaps:
def placeNumber(self, value):
size = random.choice([24,36,48,72])
coord = [random.randint(40,BOX_SIZE - 40) for x in range(2)]
newTxt = self.numBox.create_text(*coord, font = ("Times New Roman",size), text = value)
for i in range(1000): # 1000 is the maximum number of tries to make
bbox = self.numBox.bbox(newTxt)
overlapping = self.numBox.find_overlapping(*bbox)
if len(overlapping) == 1:
return
# compute new coordinate
coord = [random.randint(40,BOX_SIZE - 40) for x in range(2)]
self.numBox.coords(newTxt, *coord)
# delete the text since we couldn't find a space for it.
self.numBox.delete(newTxt)
Either algorithm will be slow when there isn't much free space. When I created a 1000x1000 canvas with 100 numbers, it laid them out with zero overlaps in under a second.

How do you disable a button when it is clicked?

I am new to python, and self taught. I am trying to make a simplifed minesweeper game called "Mines". This game has a 5 by 5 grid of buttons, with a random number of mines. Everything is working fine, except for one issue. After you click a safe space, the button should be disabled so you cannot gain any more points. With my code, I have no idea how to do this.
I did already try to call a method to disable the button, as well as using the DISABLED command. Neither worked. I want the "white" buttons to be disabled after click, as those are the safe spaces. In a perfect world, I will call the disable() method when the button is clicked and use that method to disable that button.
##Create the canvas of the board.
window = Tk ()
window.title("Mines Game")
window.geometry('819x655')
##Scoring function. The first box clicked awards 1 point, and after that each box is worth double your total points.
def score():
global scores
if (scores == 0):
scores = scores + 1
print ("Safe space hit! You have " + str(scores) + " point.")
else:
scores = scores * 2
print ("Safe space hit! You have " + str(scores) + " points.")
def squares():
##Main method of creating a 5x5 square of buttons.
global scores
scores = 0
less_bombs = True
r = -1
c = 0
x = 0
if less_bombs:
for i in range(5):
r = r + 1
for l in range(5):
y = randint(0,25)
if x == 5:
y = 10
if y < 6:
btn = Button(window, bg = "red", command=end)
btn.grid(column = c,row = r)
#btn.grid(sticky="nesw")
btn.config(height = 8, width = 22)
x = x + 1
else:
btn = Button(window, bg = "white", command=lambda:[score(),DISABLED])
btn.grid(column = c,row = r)
#btn.grid(sticky="nesw")
btn.config(height = 8, width = 22)
c = c + 1
c = 0
def end():
##This method creates the popup after you click a mine.
end = Tk ()
end.title ('Game Over!')
end.geometry ('300x161')
btn = Button(end, text ="Close game", command=close)
btn.grid(column = 0,row = 0)
#btn.grid(sticky="nesw")
btn.config(height = 10, width = 20)
btn = Button(end, text ="Reset game", command=lambda:[reset(),end.destroy()])
btn.grid(column = 1,row = 0)
#btn.grid(sticky="nesw"
btn.config(height = 10, width = 20)
if (scores == 1):
print ("Game over! You hit a mine :(")
print ("Your score for that game was " + str(scores) + " point.")
if (scores != 1):
print ("Game over! You hit a mine :(")
print ("Your score for that game was " + str(scores) + " points.")
def disable():
pass
def close():
sys.exit()
def reset():
squares()
squares()
window.mainloop()
I want the button to be disabled after being clicked, however currently the player can click the button as many times as he or she wants.
You can fix it by changing creation of white Buttonss as indicated below in ALL CAPS. This gives the lambda function a default value for btn which changes each iteration of loop (otherwise the function would always refer to the last one created in the for loop).
def squares():
""" Main method of creating a 5x5 square of buttons. """
global scores
scores = 0
less_bombs = True
r = -1
c = 0
x = 0
if less_bombs:
for i in range(5):
r = r + 1
for l in range(5):
y = randint(0,25)
if x == 5:
y = 10
if y < 6:
btn = Button(window, bg="red", command=end)
btn.grid(column=c, row=r)
#btn.grid(sticky="nesw")
btn.config(height=8, width=22)
x = x + 1
else:
btn = Button(window, bg="white") ## REMOVE command= OPTION. ##
btn.grid(column=c, row=r)
#btn.grid(sticky="nesw")
btn.config(height=8, width=22, # USE command SHOWN BELOW. ##
command=lambda btn=btn: [score(), btn.config(state=DISABLED)])
c = c + 1
c = 0

Tkinter Image Viewer Method

I am an atmospheric scientist, struggling through python (2.7 using PIL and Tkinter) in an attempt to create a simple image viewer that will display some of the forecast products we eventually produce. I would like to implement a start, stop, forward, backward, and loop button. The loop button and its associated callback currently work correctly. The loop method is credited to Glenn Pepper (found an open-source project via google).
Here is the code:
from Tkinter import *
from PIL import Image, ImageTk
import tkMessageBox
import tkFileDialog
#............................Button Callbacks.............................#
root = Tk()
root.title("WxViewer")
root.geometry("1500x820+0+0")
def loop():
StaticFrame = []
for i in range(0,2):
fileName="filename"+str(i)+".gif"
StaticFrame+=[PhotoImage(file=fileName)]
def animation(currentframe):
def change_image():
displayFrame.create_image(0,0,anchor=NW,
image=StaticFrame[currentframe], tag='Animate')
# Delete the current picture if one exist
displayFrame.delete('Animate')
try:
change_image()
except IndexError:
# When you get to the end of the list of images -
#it simply resets itself back to zero and then we start again
currentframe = 0
change_image()
displayFrame.update_idletasks() #Force redraw
currentframe = currentframe + 1
# Call loop again to keep the animation running in a continuous loop
root.after(1000, animation, currentframe)
# Start the animation loop just after the Tkinter loop begins
root.after(10, animation, 0)
def back():
print("click!")
def stop():
print("click!")
def play():
print("click!")
def forward():
print("click!")
#..........................ToolFrame Creation............................#
toolFrame = Frame(root)
toolFrame.config(bg="gray40")
toolFrame.grid(column=0,row=0, sticky=(N,W,E,S) )
toolFrame.columnconfigure(0, weight = 1)
toolFrame.rowconfigure(0, weight = 1)
toolFrame.pack(pady = 0, padx = 10)
backButton = Button(toolFrame, text="Back", command = back)
backButton.pack(side = LEFT)
stopButton = Button(toolFrame, text = "Stop", command = stop)
stopButton.pack(side = LEFT)
playButton = Button(toolFrame, text = "Play", command = play)
playButton.pack(side = LEFT)
forwardButton = Button(toolFrame, text = "Forward", command = forward)
forwardButton.pack(side = LEFT)
loopButton = Button(toolFrame, text = "Loop", command = loop)
loopButton.pack(side = LEFT)
toolFrame.pack(side = TOP, fill=X)
#........................DisplayFrame Creation..........................#
displayFrame = Canvas(root, width=1024,height=768)
displayFrame.config(bg="white")
displayFrame.grid(column=0,row=0, sticky=(N,W,E,S) )
displayFrame.columnconfigure(0, weight = 1)
displayFrame.rowconfigure(0, weight = 1)
displayFrame.pack(pady = 5, padx = 10)
displayFrame.pack(side = LEFT, fill=BOTH)
#...............................Execution...............................#
root.mainloop()
It is rather straightforward. I have searched GitHub for projects, google, and stackoverflow but I am unsure how to make these five methods play nicely with each other. Could anyone share some pointers on how I could construct these other four methods so that they work appropriately? Thank you for your time!
I would replace the current loop function with something like the following (untested). The changes: add some global names to share data between functions; make change_image do everything needed to change an image, given that current_image is valid; except for the starting value, make current_image be always a valid image number when it is changed; factor forward() out of animate() (which is just repeated times forward calls).
n_images = 2
images = [PhotoImage(file="filename"+str(i)+".gif") for i in range(n_images)]
current_image = -1
def change_image():
displayFrame.delete('Animate')
displayFrame.create_image(0,0, anchor=NW,
image=StaticFrame[current_image], tag='Animate')
displayFrame.update_idletasks() #Force redraw
callback = None
def animate():
global callback
forward()
callback = root.after(1000, animate)
Here are three of the other functions.
def forward():
global current_image
current_image += 1
if current_image >= n_images:
current_image = 0
change_image()
def back():
global current_image
current_image -= 1
if current_image < 0:
current_image = n_images-1
change_image()
def stop():
if callback is not None:
root.after_cancel(callback)

tkinter cant assign text variable

the problem was my input popup had to be a toplevel window so changing tk.Tk() to tk.Toplevel() makes it work fine ;)
#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
this is the portion that wont work
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
I'm just screwing around trying to make adding a highscore more visual for a game I made this code it works fine by itself but when I import it or even copy the whole code into a py file with other functions it just stops assigning ment any values I don't understand :/
any help is appreciated
this is the code that runs the game
#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()
link for graphics.py
http://mcsp.wartburg.edu/zelle/python/graphics.py
I don't understand exactly what your problem is doing wrong, but I'm pretty sure I know what the problem is.
Most of your program is using some library named graphics to run a GUI. Then you're trying to use Tkinter to run another GUI in the same program.
I don't know what that graphics library that is, but unless it's either built on top of Tkinter, or specifically designed to work with Tkinter, this is unlikely to work. Both of them are going to try to be in charge of the one and only GUI for your program, handling all of the events from the user/windowing system, and so forth. One or both are going to fail.
In fact, even if graphics were built on top of Tkinter or designed to work together with it, calling mainloop on the Tkinter window is at best going to freeze up the rest of your GUI until you exit that mainloop, and at worst going to break the outer mainloop that the other GUI is relying on.
From what I can see from your other code, that graphics library seems to have enough features to do everything you were trying to do with Tkinter—create a new window, place some widgets on it, handle a button click. So, why not just use that?
Now that you've given us a link to the graphics library you're using… it looks like a thin wrapper around Tkinter. Which means you should be able to integrate them easily. You just have to create a new Toplevel instead of a root window (since graphics has already created a Tkinter root), and not call mainloop or quit (because you're already in a Tkinter main loop created by graphics).
Since you haven't given us an SSCCE that I can just run and hack on, I've built my own super-simple one around the first example in the graphics docs, which does what you were trying to do, and also shows how you can interact with the graphics window from the Tkinter code.
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()
It would be better to refactor this to eliminate your global variables, either using an OO design (create a class so you can store things as instance attributes) or a functional design (pass values through closures or bake them in with lambda/partial, as you're already doing in your Button command), but I tried to follow the style you already set in your code rather than rewrite everything.

Making Tkinter Photoimage crashes python program

I'm writing a minesweeper game using tkinter, and everything appears to function alright, but python crashes every time after a number of clicks, and I believe it is because I've added images for the "flags" used to flag where a mine is. Below is the function that draws all of the cells, which is called with each move/click.
def draw_cake_cell(canvas, row, col):
# draws different cells on the board (blank cell, numbers, cake flags)
margin = 5
cellSize = 30
board = canvas.data['board']
mask = canvas.data['mask']
cake_count = canvas.data['cake_count']
player_board = canvas.data['player_board']
left = margin + col*cellSize
top = margin + row*cellSize
bottom = top + cellSize
right = left+cellSize
flag_img = PhotoImage(file="flag.gif")
flag_label = Label(image = flag_img)
flag_label.image = flag_img
cake_img = PhotoImage(file = "cakeflag.gif")
cake_label = Label(image = cake_img)
cake_label.image = cake_img
canvas.create_rectangle(left,top, right, bottom, fill = 'gray')
if board[row][col] == -1:
if canvas.data['isGameOver'] == True:
canvas.create_image((left+right)/2,(top+bottom)/2,image = cake_img)
elif mask[row][col] == -2:
canvas.create_image((left+right)/2,(top+bottom)/2,image = flag_img)
else:
if cake_count[row][col] > 0 and player_board[row][col] == 1:
value = cake_count[row][col]
canvas.create_rectangle(left,top,right,bottom, fill = 'white')
canvas.create_text((left+right)/2,(top+bottom)/2 , text = str(value), font = ('Helvetica',12))
if mask[row][col] == -2:
canvas.create_image((left+right)/2,(top+bottom)/2,image = flag_img)
if cake_count[row][col] == 0 and player_board[row][col] == 1:
canvas.create_rectangle(left,top,right,bottom, fill = 'white')
Since you are using python3, (left+right)/2 is float, not an int. maybe that's the problem - use (left+right)//2.

Categories