Display multiple images in PIL - python-3.x
-------------------------------Solved(Partially)----------------------------------------
My problem is that when I try to display multiple images on the canvas using PIL, I end up with only the last image.
All the images have slightly different characteristics(angle offset). Also the having a plethora of entries, I have to use a loop for sure. Also I'll need to use PIL(tkinter objects not possible) for the angle offset feature.
Here is the code;
#!/usr/bin/python
# Filename: weather_sim.py
import os
import tkinter as tk
import h5py as hp
import numpy as np
import ntpath as ntp
from PIL import Image, ImageTk
from tkinter.filedialog import askopenfilename
def path_leaf(path):
head, tail = ntp.split(path)
return tail or ntp.basename(head)
class CoordFind:
def __init__(self):
self.LatPx = 0
self.LonPx = 0
def find_px(self, Lat, Lon):
self.LatPx = (Lat - LatN)/LatLc
self.LonPx = (Lon - LonW)/LonLc
class PlottingGUI(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.coord = CoordFind()
self.root = parent
self.root.wm_title("-|-|-|-|||Wind Vector Plotter|||-|-|-|-")
self.root.resizable(False, False)
self.path = "None Selected"
self.HaM = 0
self.Lat = 0
self.Lon = 0
self.WiD = 0
self.WiS = 0
self.fr = tk.Frame(self.root, width = (width+20), height = (height+20), bd = 2)
self.fr.grid(row = 1, column = 0)
self.frBro = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frBro.grid(row = 0, column = 0)
self.frHi = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frHi.grid(row = 2, column = 0)
self.cv = tk.Canvas(self.fr, width = width, height = height, background = "white", bd = 0, relief = tk.SUNKEN)
self.cv.grid(row = 0, column = 0)
self.cv.create_image(1, 1, anchor = "nw", image = photo)
self.broButton = tk.Button(self.frBro, text = "Browse Dsets", command = self.analyseDset, height = 3, width = 16, bg = "yellow")
self.broButton.grid(row = 0, column = 0, padx = 20)
self.selFile = tk.Label(self.frBro, text = self.path)
self.selFile.grid(row = 0, column = 1)
self.caution = tk.Label(self.frHi, text = "Optional use. Warning!!, May lead to lags in program", fg = "red")
self.caution.grid(row = 0, column = 1)
self.shoRedBut = tk.Button(self.frHi, text = "Show H1", command = self.show_barbs1().__next__, height = 3, width = 16, bg = "#FF0000", fg = "white", activebackground="#E533B5")
self.shoRedBut.grid(row = 1, column = 0, padx = 7, pady = 2)
self.shoGrnBut = tk.Button(self.frHi, text = "Show H2", command = self.show_barbs2().__next__, height = 3, width = 16, bg = "#00B400", fg = "white", activebackground="#B5E533")
self.shoGrnBut.grid(row = 1, column = 1, padx = 7, pady = 2)
self.shoBluBut = tk.Button(self.frHi, text = "Show H3", command = self.show_barbs3().__next__, height = 3, width = 16, bg = "#0000FF", fg = "white", activebackground="#33B5E5")
self.shoBluBut.grid(row = 1, column = 2, padx = 7, pady = 2)
self.desc1 = tk.Label(self.frHi, text = "100-250 hPa", fg = "white", bg = "black")
self.desc1.grid(row = 2, column = 0)
self.desc2 = tk.Label(self.frHi, text = "250-350 hPa", fg = "white", bg = "black")
self.desc2.grid(row = 2, column = 1)
self.desc3 = tk.Label(self.frHi, text = "350-700 hPa", fg = "white", bg = "black")
self.desc3.grid(row = 2, column = 2)
def analyseDset(self):
self.path = askopenfilename(filetypes = (("Dataset files", "*.h5")
,("All files", "*.*") ))
self.jfname = path_leaf(self.path)
self.selFile = tk.Label(self.frBro, text = self.jfname)
self.selFile.grid(row = 0, column = 1)
self.extDset()
def extDset(self):
hf = hp.File(self.path, 'r')
HaM = hf.get('HEIGHT_ASSIGNMENT_METHOD')
Lat = hf.get('Latitude')
Lon = hf.get('Longitude')
WiD = hf.get('WIND_DIRECTION')
WiS = hf.get('WIND_SPEED')
self.HaM = np.array(HaM)
self.Lat = np.array(Lat)/100
self.Lon = np.array(Lon)/100
self.WiD = np.array(WiD)
self.WiS = np.array(WiS)
self.BrbImR = np.empty((self.HaM.shape[0],1))
self.BrbImB = np.empty((self.HaM.shape[0],1))
def show_barbs1(self):
self.coord = CoordFind()
script_dir = os.path.dirname(os.path.abspath(__file__))
im = Image.open(os.path.join(script_dir, 'Red_Barbs\icons8-wind-speed-43-47-50.png'))
w, h = im.size
im = im.resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im = ImageTk.PhotoImage(im.rotate(45))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 0:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImR[i] = self.cv.create_image(x, y, image = vec_im)
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImR[i], state = tk.NORMAL)
self.shoRedBut.configure(text = "Showing H1")
yield
def show_barbs2(self):
self.coord = CoordFind()
BrbImG = np.empty((self.HaM.shape[0],1))
script_dir = os.path.dirname(os.path.abspath(__file__))
im = Image.open(os.path.join(script_dir, 'Green_Barbs\icons8-wind-speed-43-47-50.png'))
w, h = im.size
im = im.resize((int(w/2), int(h/2)), Image.ANTIALIAS)
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 1:
vec_im = ImageTk.PhotoImage(im.rotate(self.WiD[i]))
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
BrbImG[i] = self.cv.create_image(x, y, image = vec_im)
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(BrbImG[i], state = tk.NORMAL)
self.shoGrnBut.configure(text = "Showing H2")
yield
def show_barbs3(self):
self.coord = CoordFind()
script_dir = os.path.dirname(os.path.abspath(__file__))
im = Image.open(os.path.join(script_dir, 'Blue_Barbs\icons8-wind-speed-43-47-50.png'))
w, h = im.size
im = im.resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im = ImageTk.PhotoImage(im.rotate(180))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 2:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImB[i] = self.cv.create_image(x, y, image = vec_im)
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImB[i], state = tk.NORMAL)
self.shoBluBut.configure(text = "Showing H3")
yield
if __name__ == "__main__":
root = tk.Tk()
backmap = "Map.png"
photo = ImageTk.PhotoImage(file = backmap)
width = photo.width()
height = photo.height()
LatN = 69.5
LatS = -69.3
LonE = 148.9
LonW = 1.0
LatLc = (LatS - LatN)/height
LonLc = (LonE - LonW)/width
app = PlottingGUI(root)
root.mainloop()
The output currently is this;(For the green arrows as that is what I have tested on)
This is what I want;(But with different angles)
I am using Python 3.6 on Windows 10.
Thanks in advance!!
P.S.: Also there is another problem if someone can help me with that. I would like to be able to choose a particular image based on a range factor(Wind Speed) by doing like a switch-case(or if-elif-else) procedure if possible. But when I try to do that it says "No such File or Directory". I may put it in another Question though.
-------------------------------Solved(Till this point)---------------------------------
EDIT: Solved the problem of displaying multiple arrows according to
choice and at different angles.
Here's the code;
#!/usr/bin/python
# Filename: weather_sim.py
import os
import tkinter as tk
import h5py as hp
import numpy as np
import ntpath as ntp
from PIL import Image, ImageTk
from tkinter.filedialog import askopenfilename
def path_leaf(path):
head, tail = ntp.split(path)
return tail or ntp.basename(head)
class CoordFind:
def __init__(self):
self.LatPx = 0
self.LonPx = 0
def find_px(self, Lat, Lon):
self.LatPx = (Lat - LatN)/LatLc
self.LonPx = (Lon - LonW)/LonLc
class PlottingGUI(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.coord = CoordFind()
self.root = parent
self.root.wm_title("-|-|-|-|||Wind Vector Plotter|||-|-|-|-")
self.root.resizable(False, False)
self.path = "None Selected"
self.HaM = 0
self.Lat = 0
self.Lon = 0
self.WiD = 0
self.WiS = 0
self.ima = []
self.fr = tk.Frame(self.root, width = (width+20), height = (height+20), bd = 2)
self.fr.grid(row = 1, column = 0)
self.frBro = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frBro.grid(row = 0, column = 0)
self.frHi = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frHi.grid(row = 2, column = 0)
self.cv = tk.Canvas(self.fr, width = width, height = height, background = "white", bd = 0, relief = tk.SUNKEN)
self.cv.grid(row = 0, column = 0)
self.cv.create_image(1, 1, anchor = "nw", image = photo)
self.broButton = tk.Button(self.frBro, text = "Browse Dsets", command = self.analyseDset, height = 3, width = 16, bg = "yellow")
self.broButton.grid(row = 0, column = 0, padx = 20)
self.selFile = tk.Label(self.frBro, text = self.path)
self.selFile.grid(row = 0, column = 1)
self.caution = tk.Label(self.frHi, text = "Optional use. Warning!!, May lead to lags in program", fg = "red")
self.caution.grid(row = 0, column = 1)
self.shoRedBut = tk.Button(self.frHi, text = "Show H1", command = self.show_barbs1().__next__, height = 3, width = 16, bg = "#FF0000", fg = "white", activebackground="#E533B5")
self.shoRedBut.grid(row = 1, column = 0, padx = 7, pady = 2)
self.shoGrnBut = tk.Button(self.frHi, text = "Show H2", command = self.show_barbs2().__next__, height = 3, width = 16, bg = "#00B400", fg = "white", activebackground="#B5E533")
self.shoGrnBut.grid(row = 1, column = 1, padx = 7, pady = 2)
self.shoBluBut = tk.Button(self.frHi, text = "Show H3", command = self.show_barbs3().__next__, height = 3, width = 16, bg = "#0000FF", fg = "white", activebackground="#33B5E5")
self.shoBluBut.grid(row = 1, column = 2, padx = 7, pady = 2)
self.desc1 = tk.Label(self.frHi, text = "100-250 hPa", fg = "white", bg = "black")
self.desc1.grid(row = 2, column = 0)
self.desc2 = tk.Label(self.frHi, text = "250-350 hPa", fg = "white", bg = "black")
self.desc2.grid(row = 2, column = 1)
self.desc3 = tk.Label(self.frHi, text = "350-700 hPa", fg = "white", bg = "black")
self.desc3.grid(row = 2, column = 2)
def analyseDset(self):
self.path = askopenfilename(filetypes = (("Dataset files", "*.h5")
,("All files", "*.*") ))
self.jfname = path_leaf(self.path)
self.selFile = tk.Label(self.frBro, text = self.jfname)
self.selFile.grid(row = 0, column = 1)
self.extDset()
def extDset(self):
hf = hp.File(self.path, 'r')
HaM = hf.get('HEIGHT_ASSIGNMENT_METHOD')
Lat = hf.get('Latitude')
Lon = hf.get('Longitude')
WiD = hf.get('WIND_DIRECTION')
WiS = hf.get('WIND_SPEED')
self.HaM = np.array(HaM)
self.Lat = np.array(Lat)/100
self.Lon = np.array(Lon)/100
self.WiD = np.array(WiD)
self.WiS = np.array(WiS)
self.BrbImR = np.empty((self.HaM.shape[0],1))
self.BrbImG = np.empty((self.HaM.shape[0],1))
self.BrbImB = np.empty((self.HaM.shape[0],1))
def barb_def(self, WiS):
if WiS < 1:
self.ima = "1.png"
elif WiS < 3:
self.ima = "2.png"
elif WiS < 8:
self.ima = "3.png"
elif WiS < 13:
self.ima = "4.png"
elif WiS < 18:
self.ima = "5.png"
elif WiS < 23:
self.ima = "6.png"
elif WiS < 28:
self.ima = "7.png"
elif WiS < 33:
self.ima = "8.png"
elif WiS < 38:
self.ima = "9.png"
elif WiS < 43:
self.ima = "10.png"
elif WiS < 48:
self.ima = "11.png"
elif WiS < 53:
self.ima = "12.png"
elif WiS < 58:
self.ima = "13.png"
elif WiS < 63:
self.ima = "14.png"
elif WiS < 68:
self.ima = "15.png"
elif WiS < 73:
self.ima = "16.png"
elif WiS < 78:
self.ima = "17.png"
elif WiS < 83:
self.ima = "18.png"
elif WiS < 88:
self.ima = "19.png"
elif WiS < 93:
self.ima = "20.png"
elif WiS < 98:
self.ima = "21.png"
elif WiS < 103:
self.ima = "22.png"
else:
self.ima = "23.png"
def show_barbs1(self):
self.coord = CoordFind()
vec_im = []
im = []
p = []
script_dir = os.path.dirname(os.path.abspath(__file__))
for i in range(0, self.HaM.shape[0]):
self.barb_def(self.WiS[i])
p.append("{}{}".format('Red_Barbs\\', self.ima))
im.append(Image.open(os.path.join(script_dir, p[i])))
w, h = im[i].size
im[i] = im[i].resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im.append(ImageTk.PhotoImage(im[i].rotate(self.WiD[i])))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 0:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImR[i] = self.cv.create_image(x, y, image = vec_im[i])
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImR[i], state = tk.NORMAL)
self.shoRedBut.configure(text = "Showing H1")
yield
def show_barbs2(self):
self.coord = CoordFind()
vec_im = []
im = []
p = []
script_dir = os.path.dirname(os.path.abspath(__file__))
for i in range(0, self.HaM.shape[0]):
self.barb_def(self.WiS[i])
p.append("{}{}".format('Green_Barbs\\', self.ima))
im.append(Image.open(os.path.join(script_dir, p[i])))
w, h = im[i].size
im[i] = im[i].resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im.append(ImageTk.PhotoImage(im[i].rotate(self.WiD[i])))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 1:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImG[i] = self.cv.create_image(x, y, image = vec_im[i])
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImG[i], state = tk.NORMAL)
self.shoGrnBut.configure(text = "Showing H2")
yield
def show_barbs3(self):
self.coord = CoordFind()
vec_im = []
im = []
p = []
script_dir = os.path.dirname(os.path.abspath(__file__))
for i in range(0, self.HaM.shape[0]):
self.barb_def(self.WiS[i])
p.append("{}{}".format('Blue_Barbs\\', self.ima))
im.append(Image.open(os.path.join(script_dir, p[i])))
w, h = im[i].size
im[i] = im[i].resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im.append(ImageTk.PhotoImage(im[i].rotate(self.WiD[i])))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 2:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImB[i] = self.cv.create_image(x, y, image = vec_im[i])
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImB[i], state = tk.NORMAL)
self.shoBluBut.configure(text = "Showing H3")
yield
if __name__ == "__main__":
root = tk.Tk()
backmap = "Map.png"
photo = ImageTk.PhotoImage(file = backmap)
width = photo.width()
height = photo.height()
LatN = 69.5
LatS = -69.3
LonE = 148.9
LonW = 1.0
LatLc = (LatS - LatN)/height
LonLc = (LonE - LonW)/width
app = PlottingGUI(root)
root.mainloop()
But this ended up having a new problem. One set of coloured arrows is showing at a time but when I click the button to display another set it goes "Python stopped working because of some error" and then the shell restarts. Don't know what's the prob though.
Related
tkinter sliders are stuck together
I'm having trouble separating these 2 sliders. They seem to be tracking together, but the variables seem to no be unique, and I can't figure out why. Can anyone help? import tkinter as tk sBoard = tk.Tk() sBoard.geometry("800x400") ch1_Frame = tk.LabelFrame(sBoard, text = "CH 1", bd = 5) ch1_val = 0 ch1 = tk.Scale(ch1_Frame, variable = ch1_val, from_ =100, to = 0, showvalue = 0, width = 25, length = 200) ch1.pack() button1 = tk.Button(ch1_Frame, text = "Power") button1.pack() ch1_Frame.place(x=25, y=50) ch2_Frame = tk.LabelFrame(sBoard, text = "CH 2", bd = 5) ch2_val = 0 ch2 = tk.Scale(ch2_Frame, variable = ch2_val, from_ =100, to = 0, showvalue = 0, width = 25, length = 200) ch2.pack() button2 = tk.Button(ch2_Frame, text = "Power") button2.pack() ch2_Frame.place(x=150, y=50) sBoard.mainloop()
The variable must be one of the tkinter variable types, for example an IntVar: ch1_val = tk.IntVar() ch1 = tk.Scale(ch1_Frame, variable = ch1_val, from_ =100, to = 0, showvalue = 0, width = 25, length = 200) ch1.pack()
Issue with pygame.transform.rotate(), Index is apparently out of range
So I am working on a basic PacMan game, and am trying to get my player to run through its sprite_sheet to show an animation. It works flawlessly when I am moving it right (thats the original orientation of the image), however for any of the other directions where I pygame.transform.rotate() the image, it returns the following: self.image = (PAC_UP[self.spritesheet_index % 4]) IndexError: list index out of range Not sure why this is happening (clearly it has to do with rotation). Any explanation on rotations and why this is happening would be greatly appreciated! Thanks! Heres my code: class sprite_sheet(): def __init__ (self, filename): self.spritesheet = pygame.image.load(filename) def get_image(self, x, y, width, height): image = pygame.Surface((width, height)) image.set_colorkey(BLACK) image.blit(self.spritesheet, (0,0), (x, y, width, height)) return image PAC_RIGHT = [] for x in range(4): image = (sprite_sheet('pacman-spritesheet.png').get_image(x*24, 0, 24, 24)) PAC_RIGHT.append(image) PAC_UP = [] for x in range(4): image = sprite_sheet('pacman-spritesheet.png').get_image(x*24, 0, 24, 24) PAC_RIGHT.append(pygame.transform.rotate(image, 90)) PAC_LEFT = [] for x in range(4): image = sprite_sheet('pacman-spritesheet.png').get_image(x*24, 0, 24, 24) PAC_RIGHT.append(pygame.transform.rotate(image, 180)) PAC_DOWN = [] for x in range(4): image = sprite_sheet('pacman-spritesheet.png').get_image(x*24, 0, 24, 24) PAC_RIGHT.append(pygame.transform.rotate(image, 270)) class Player (pygame.sprite.Sprite): def __init__(self, game, x, y): self.groups = game.all_sprites pygame.sprite.Sprite.__init__(self, self.groups) self.game = game self.image = sprite_sheet('pacman-spritesheet.png').get_image(0, 0, 24, 24) self.x = x * TILESIZE self.y = y * TILESIZE self.rect = self.image.get_rect() self.vx, self.vy = 0, 0 self.spritesheet_index = 0 self.first_time = pygame.time.get_ticks() self.delay = 43 def get_keys(self): self.vx, self.vy = 0, 0 keys = pygame.key.get_pressed() self.spritesheet_index += 1 if keys[pygame.K_LEFT]: self.vx = -PLAYER_SPEED self.second_time = pygame.time.get_ticks() if self.second_time-self.first_time > self.delay: self.image = (PAC_LEFT[self.spritesheet_index % 4]) self.first_time = pygame.time.get_ticks() if keys[pygame.K_RIGHT]: self.vx = PLAYER_SPEED self.second_time = pygame.time.get_ticks() if self.second_time-self.first_time > self.delay: self.image = (PAC_RIGHT[self.spritesheet_index % 4]) self.first_time = pygame.time.get_ticks() if keys[pygame.K_UP]: self.vy = -PLAYER_SPEED self.second_time = pygame.time.get_ticks() if self.second_time-self.first_time > self.delay: self.image = (PAC_UP[self.spritesheet_index % 4]) self.first_time = pygame.time.get_ticks() if keys[pygame.K_DOWN]: self.vy = PLAYER_SPEED self.second_time = pygame.time.get_ticks() if self.second_time - self.first_time > self.delay: self.image = (PAC_DOWN[self.spritesheet_index % 4]) self.first_time = pygame.time.get_ticks()
Looks like you're only adding your sprite images to the PAC_UP list: PAC_RIGHT = [] for x in range(4): image = (sprite_sheet('pacman-spritesheet.png').get_image(x*24, 0, 24, 24)) PAC_RIGHT.append(image) PAC_UP = [] for x in range(4): image = sprite_sheet('pacman-spritesheet.png').get_image(x*24, 0, 24, 24) PAC_RIGHT.append(pygame.transform.rotate(image, 90)) Modify your code to append to the appropriate lists, PAC_DOWN, PAC_LEFT & PAC_RIGHT. Additionally, this looks to be a copy-paste error. Instead of copy-pasting, it would be better to create a function to do your image loading. Here's an untested example: def load_sprite_images(rotation, filename='pacman-spritesheet.png'): """Load four sprite images from the specified file""" images = [] for x in range(4): image = (sprite_sheet(filename).get_image(x*24, 0, 24, 24)) images.append(pygame.transform.rotate(image, rotation)) return images PAC_RIGHT = load_sprite_images(0) PAC_UP = load_sprite_images(90) PAC_LEFT = load_sprite_images(180) PAC_RIGHT = load_sprite_images(270)
How to change background color in ttk python
I've made a simple gui age converter app but i want to change its bg color to black. The problem is in the ttk frame.i don't know how to configure its bg color. I have tried different methods but that didn't work. i would be grateful if you guys could help. here is the code from tkinter import * from tkinter import ttk from PIL import Image def calculate(*args): try: age_sec = int(age.get()) age_sec = age_sec * 12 * 365 * 24 * 60 * 60 age_seconds.set(age_sec) except: age_seconds.set('Either the field is empty or \n value is not numeric.') root = Tk() root.title("Converter") root.configure(background="black") mainframe = ttk.Frame(root, padding = "6 6 12 12") mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S)) mainframe.columnconfigure(0, weight = 1) mainframe.rowconfigure(0, weight = 1) #mainframe['borderwidth'] = 2 #mainframe['relief'] = 'groove' age = StringVar() age_seconds = StringVar() ttk.Label(mainframe, foreground = "#4D4E4F", text = "Enter your Age: ").grid(column = 1, row = 1, sticky = E) age_entry = ttk.Entry(mainframe, width = 30, textvariable = age) age_entry.grid(column = 2, row = 1, sticky = (W, E)) ttk.Label(mainframe, foreground = "#4D4E4F", text = "your age in seconds is ").grid(column = 1, row = 2, sticky = (E)) ttk.Label(mainframe, textvariable = age_seconds, background = "lightyellow", foreground = "#727475", width = 30).grid(column = 2, row = 2, sticky = W) #Mouse Events...\\ butt_image = PhotoImage(file = 'images.gif') ttk.Button(mainframe, compound = TOP, text = "Hit Now", image =butt_image, cursor = "hand2", width= 30, command = calculate).grid(column = 2, row = 4, sticky = W) l2 = ttk.Label(mainframe,foreground = "#4D4E4F", text = "Mouse Events: ").grid(column = 1, row = 3, sticky = E) l = ttk.Label(mainframe,background = "lightyellow", foreground = "#727475", text = 'Measurement is starting...', width = 30) l.grid(column = 2, row = 3, sticky = W) l.bind('<Enter>', lambda e: l.configure(text = 'Moved Mouse Inside')) l.bind('<Leave>', lambda e: l.configure(text = 'Mouse Moved Out')) l.bind('<1>', lambda e: l.configure(text = 'left Mouse clicked')) l.bind('<Double-1>', lambda e: l.configure(text = 'Double clicked')) l.bind('<B1-Motion>', lambda e: l.configure(text = 'Left button drag to %d, %d' %(e.x, e.y))) image = PhotoImage(file = 'waves.gif') ttk.Label(mainframe, compound = CENTER, text = "Image text", font = ('roman', 9, 'normal'), foreground ='green', image = image).grid(column = 3, row = 1, sticky = (N, E)) #if '__name__' == '__main__': for child in mainframe.winfo_children(): child.grid_configure(padx = 15, pady = 15) age_entry.focus() root.bind('<Return>', calculate) root.mainloop()
A ttk.Frame does not have a background / bg option. To change it you need to use style. See ttk.Frame Info If you don't really need to use a ttk.Frame you can just switch to a tkinter.Frame
Odd grid sizing behaviour
I have been using tkinter's grid geometry manager and have configured all the rows and columns to weight = 1. The problem comes when I try to resize a Tk() window. When I resize it vertically only, the width of widgets and the proportion of column widths also change despite their equal weight. Furthermore, the width of the columns isn't in the desired proportions (i.e. all equal) before doing any resizing - to be precise the first column (with labels and buttons) is as wide as other two (holding a canvas with columnspan = 2 and two labels). I think the problem is somehow connected to the PiSimulator._adjust_sizes function which dynamically changes the font or to the use of the canvas with a columnspan of 2. Here's my code: import tkinter as tk from tkinter import font class PiSimulator(tk.Frame): def __init__(self, root, **kwargs): super(PiSimulator, self).__init__(root, **kwargs) self.root = root self.root.title = 'Crtac krugova' self.root.minsize(width = 600, height = 400) self.pack(fill = 'both', expand = 1) self.custom_font = font.Font(size = 20) self.bind('<Configure>', self._adjust_sizes) self.populate() return def populate(self): tk.Label(self, text = 'Radijus:', font = self.custom_font, relief = 'raised',\ fg = 'green').grid(sticky='nswe', row = 0, column = 0) self.radius = tk.IntVar() tk.Spinbox(self, from_ = 1, to = 16, font = self.custom_font, textvariable = self.radius).grid(row = 1, column = 0) tk.Label(self, text = 'Greška', font = self.custom_font, relief = 'raised', anchor='w',\ padx = 5, pady = 5, fg = 'green').grid(sticky='nswe', row = 0, column = 1) self.error = tk.DoubleVar(0.0) tk.Label(self, textvariable = self.error, font = self.custom_font, relief = 'raised',\ anchor='e', pady = 5, fg = 'green').grid(row = 0, column = 2, sticky='nswe') self.canvas = PiCanvas(self, highlightthickness = 0) self.canvas.grid(row = 1, rowspan = 5, column = 1, columnspan = 2, padx = 5, pady = 5, sticky='nswe') tk.Button(self, text = 'Nacrtaj', font = self.custom_font, command = lambda: self.canvas.draw(self.radius.get())).grid(\ column = 0, row = 2, sticky='nswe') tk.Button(self, text = 'Izbriši', font = self.custom_font, command = self.canvas.clear ).grid(\ column = 0, row = 3, sticky='nswe') tk.Label(self, text = 'POVRŠINA', relief = 'groove', font = self.custom_font).grid(column = 0, row = 4, sticky='nswe') self.area = tk.IntVar(0) tk.Label(self, textvariable = self.area, relief = 'groove', font = self.custom_font).grid(column = 0, row = 5, sticky='nswe') for i in range(3): self.columnconfigure(i, weight = 1) for i in range(6): self.rowconfigure(i, weight = 1) return def _adjust_sizes(self, event): new_font = int(event.height/15) - 2 self.custom_font.configure(size = new_font) return class PiCanvas(tk.Canvas): def __init__(self, root, **kwargs): super(PiCanvas, self).__init__(root, background = 'white', relief = 'groove', **kwargs) self.root = root self.cubes = [] self.circle = None def draw(self, radius): self.clear() c_width = self.winfo_width() c_height = self.winfo_height() self.grid_side = int(min([c_width, c_height])) self.grid_side-= 10 self.v_offset = (c_height - self.grid_side)/2 self.h_offset = (c_width - self.grid_side)/2 self.cube_side = self.grid_side/(2*radius) vertix_coord = lambda x, x_cor, y_cor: x_cor*self.h_offset+y_cor*self.v_offset+x*self.cube_side for i in range(2*radius): new_line = [] for j in range(2*radius): cube = self.create_rectangle(vertix_coord(i, 1, 0), vertix_coord(j, 0, 1),\ vertix_coord(i+1, 1, 0), vertix_coord(j+1, 0, 1), tag = 'unused') new_line.append(cube) self.cubes.append(new_line) self.circle = self.create_oval(vertix_coord(0,1,0), vertix_coord(0,0,1),\ vertix_coord(2*radius,1,0), vertix_coord(2*radius,0,1),width = 2) self.color_border_cubes() print(self.circle) def color_border_cubes(self): circle_coords = self.coords(self.circle) print(circle_coords) for i in self.cubes: for j in i: cube_coords = self.coords(j) if self.circle in self.find_overlapping(*cube_coords) + self.find_enclosed(*circle_coords): self.itemconfigure(j, fill = 'green') def clear(self): self.cubes = [] self.circle = None self.delete('all') return root = tk.Tk() a=PiSimulator(root) root.mainloop()
Python Tic Tac Toe using minimax does not make best move
I have been trying to get this to work for over a week now and cant seem to get it to choose the best possible move. Can someone take a look and help me out? I feel like I have missed something stupid. Thanks! from tkinter import * import tkinter.messagebox tk = Tk() tk.title("Tic Tac Toe") click = True X = "X" O = "O" EMPTY = " " TIE = "TIE" NUM_SQUARES = 9 def new_board(): """Create new game board.""" board = [] for square in range(NUM_SQUARES): board.append(EMPTY) return board def Player1Win(board, i): if(board[0]==1 and board[1]==1 and board[2]==1)or(board[0]==1 and board[3]==1 and board[6]==1)or(board[2]==1 and board[5]==1 and board[8]==1)or(board[3]==1 and board[4]==1 and board[5]==1)or(board[6]==1 and board[7]==1 and board[8]==1)or(board[0]==1 and board[4]==1 and board[8]==1)or(board[2]==1 and board[4]==1 and board[6]==1)or(board[1]==1 and board[4]==1 and board[7]==1)or(board[0]==1 and board[3]==1 and board[6]==1): if(i==0): tkinter.messagebox.showinfo("Winner X won") return True else: return False def Player2Win(board, i): if(board[0]==0 and board[1]==0 and board[2]==0)or(board[0]==0 and board[3]==0 and board[6]==0)or(board[2]==0 and board[5]==0 and board[8]==0)or(board[3]==0 and board[4]==0 and board[5]==0)or(board[6]==0 and board[7]==0 and board[8]==0)or(board[0]==0 and board[4]==0 and board[8]==0)or(board[2]==0 and board[4]==0 and board[6]==0)or(board[1]==0 and board[4]==0 and board[7]==0): if(i==0): tkinter.messagebox.showinfo("Winner O won") return True else: return False board2=new_board() board=new_board() def legal_moves(board): """Create list of legal moves.""" moves = [] count = 0 for square in range(NUM_SQUARES): if board[square] == EMPTY: count += 1 moves.append(square) print(count) return moves def minimax(board2): global click #Get all possible steps moves=legal_moves(board2) #Check copy board to win if(Player1Win(board2,2) == True): return 10 if(Player2Win(board2,2) == True): return -10 if(len(moves)==0): return 0 j = 1000 for i in moves: if click: click=True #change to Player X board2[i]=0 #This is a copy of the board is not the main else: click=False #to change Player O board2[i]=1 #This is a copy of the board is not the main v = minimax(board2) # Recursive call functions # # Select the minimum number for O and maximum for X if j == 1000 or (click == False and j < v) or (click == True and v < j): j = v if click: return j-1 # If player O else: return j+1 # If player X def bestMove(): global click # Get all possible steps moves=legal_moves(board) # Move all the data from the main board for k in range(NUM_SQUARES): board2.append(board[k]) j = 1000 best = -1 for i in moves: if click: click = False #change to Player X board2[i]=0 else: click = True #change to Player O board2[i]=1 v = minimax(board2) # Select the minimum number for O and maximum for X if j == 1000 or (click == False and j < v) or (click == True and v < j): j = v best = i return best def Update(board): global click if button1["text"]=="X": board[0]=1 if button2["text"]=="X": board[1]=1 if button3["text"]=="X": board[2]=1 if button4["text"]=="X": board[3]=1 if button5["text"]=="X": board[4]=1 if button6["text"]=="X": board[5]=1 if button7["text"]=="X": board[6]=1 if button8["text"]=="X": board[7]=1 if button9["text"]=="X": board[8]=1 if button1["text"]=="O": board[0]=0 if button2["text"]=="O": board[1]=0 if button3["text"]=="O": board[2]=0 if button4["text"]=="O": board[3]=0 if button5["text"]=="O": board[4]=0 if button6["text"]=="O": board[5]=0 if button7["text"]=="O": board[6]=0 if button8["text"]=="O": board[7]=0 if button9["text"]=="O": board[8]=0 def move(i): global click click = False if i == 0: button1["text"] = "O" board[0]=0 elif i == 1: button2["text"] = "O" board[1]=0 elif i == 2: button3["text"] = "O" board[2]=0 elif i == 3: button4["text"] = "O" board[3]=0 elif i == 4: button5["text"] = "O" board[4]=0 elif i == 5: button6["text"] = "O" board[5]=0 elif i == 6: button7["text"] = "O" board[6]=0 elif i == 7: button8["text"] = "O" board[7]=0 elif i == 8: button9["text"] = "O" board[8]=0 def checker(buttons): global click if buttons["text"] == " ": buttons["text"] = "X" click = True Update(board) best = bestMove() move(best) Player1Win(board, 0) Player2Win(board, 0) buttons = StringVar() button1 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button1)) button1.grid(row=1,column=0,sticky = S+N+E+W) button2 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button2)) button2.grid(row=1,column=1,sticky = S+N+E+W) button3 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button3)) button3.grid(row=1,column=2,sticky = S+N+E+W) button4 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button4)) button4.grid(row=2,column=0,sticky = S+N+E+W) button5 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button5)) button5.grid(row=2,column=1,sticky = S+N+E+W) button6 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button6)) button6.grid(row=2,column=2,sticky = S+N+E+W) button7 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button7)) button7.grid(row=3,column=0,sticky = S+N+E+W) button8 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button8)) button8.grid(row=3,column=1,sticky = S+N+E+W) button9 = Button(tk,text=" ",font=('Times 26 bold'), height = 4, width = 8, command =lambda:checker(button9)) button9.grid(row=3,column=2,sticky = S+N+E+W) tk.mainloop() print ("Please Begin Play")
I would suggest you add print statements to see what is happening. Start with printing "click" for each pass through the for() loop and also print what the return (j +- 1) and the value for "i" right before the return statements (and please don't use "i", "l", or "O" as single digit variable names as they can look like numbers, i.e, o=1, o=l). You can handle the really, really long and really, really, confusing line a lot better with a list of win combinations. ## a simple example that will require some modification by you def check_for_winner(player, board): ## fill in the rest yourself win_combos=[[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 4, 8], [0, 3, 6]] for x, y, z in win_combos: print "checking", x, y, z if board[x] == board[y] == board[z]: print "**** We have a winner", player, x, y, z return True return False