Related
I'm trying to write a script to control movements of a camera. I'm writing it in Thonny on a Raspberry Pi. I receive the following error when trying to move the camera using the GUI buttons. I've asked around and tried troubleshooting the problem but no luck yet.
if anyone can help that'd be awesome.
I appreciate there are alternative workflows to this script but it's me combining an old script with a new GUI so I'd love to see if they could be merged. If not oh well, I'll implement the other workflow.
[Here is the error message from Thonny][1]
from tkinter import *
import RPi.GPIO as GPIO
import time
import datetime, sys, tty, termios
#defining root
root = Tk()
root.title('Operation Little Brother V02')
#setting GPIO board
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3,GPIO.OUT)
servo1 = GPIO.PWM(3, 50)
GPIO.setup(5,GPIO.OUT)
servo2 = GPIO.PWM(5, 50)
#setting servos to off
servo1.start(0)
servo2.start(0)
#user input section
dummy = input('Initiate project. Press Enter')
#setting servos to 90degrees/startup sequence
print('launching start up sequence')
servo1.ChangeDutyCycle(6)
time.sleep(1)
servo1.ChangeDutyCycle(0)
time.sleep(1)
print ('servo 1 test complete')
servo2.ChangeDutyCycle(6)
time.sleep(1)
servo2.ChangeDutyCycle(0)
print ('servo 2 test complete')
# Defining Functions
#x axis movement concept
def x_movement(x_dir):
if x_axis <= limit_x_left and x_axis >= limit_x_right:
x_axis = x_axis + x_dir
servo1.ChangeDutyCycle(x_axis)
time.sleep(0.3)
servo1.ChangeDutyCycle(0)
time.sleep(0.5)
print ('moved camera to position: ' +str(x_axis) + '/' +str(limit_x_left))
return
else:
print ('limits reached')
#y axis movement concept
def y_movement(y_dir):
if y_axis <= limit_y_down and y_axis >= limit_y_up:
y_axis = y_axis + y_dir
servo2.ChangeDutyCycle(y_axis)
time.sleep(0.3)
servo2.ChangeDutyCycle(0)
time.sleep(0.5)
print('moved camera to position: ' +str(y_axis) + '/' +str(limit_y_up))
return y_axis
else:
print ('limits reached')
#centre movement
def centre_movement():
y_axis = 6
servo2.ChangeDutyCycle(6)
servo2.ChangeDutyCycle(0)
time.sleep(0.5)
x_axis = 6
servo1.ChangeDutyCycle(6)
servo1.ChangeDutyCycle(0)
time.sleep(0.5)
print('camera centered to position 6')
return
#off sequence
def off():
servo1.ChangeDutyCycle(0)
servo2.ChangeDutyCycle(0)
servo1.stop()
servo2.stop()
GPIO.cleanup()
print('Whoopty fucking doo it\'s finished')
exit()
#defining limits for x and y axis
limit_x_left = 9
limit_x_right = 3
limit_y_up = 3
limit_y_down = 9
x_axis = 6
y_axis = 6
#frame creation
frame1 = LabelFrame(root, text = 'Welcome to Operation Little Brother', padx = 25, pady = 25, border = 5, fg = '#ffffff', bg = '#3e556b')
#button creation
button1_left = Button(frame1, text = 'Left', padx = 20, pady = 20, fg = 'purple', bg = '#63778a', command = lambda: x_movement(1))
button2_right = Button(frame1, text = 'Right', padx = 20, pady = 20, fg = 'orange', bg = '#63778a', command = lambda: x_movement(-1))
button3_up = Button(frame1, text = 'Up', padx = 20, pady = 20, fg = 'green', command = lambda: y_movement(1))
button4_down = Button(frame1, text = 'Down', padx = 20, pady = 20, fg = 'blue', command = lambda: y_movement(-1))
button5_centre = Button(frame1, text = 'Centre', padx = 20, pady = 20, fg = 'black', command = lambda: centre_movement())
button6_start = Button(frame1, text = 'Start', padx = 10, pady = 10, fg = 'green')
button7_stop = Button(frame1, text = 'Stop', padx = 10, pady = 10, fg = 'red', command = lambda: off())
#positioning the frame
frame1.pack()
#button positioning
button1_left.grid(row = 3, column = 0,)
button2_right.grid(row = 3, column = 2,)
button3_up.grid(row = 2, column = 1)
button4_down.grid(row = 4, column = 1)
button5_centre.grid(row = 3, column = 1)
button6_start.grid(row = 1, column = 0)
button7_stop.grid(row = 1, column = 2)
#Text formatting
button1_left.configure(font='Calibri 15')
button2_right.configure(font='Calibri 15')
button3_up.configure(font='Calibri 15')
button4_down.configure(font='Calibri 15')
button5_centre.configure(font='Calibri 15')
button6_start.configure(font='Calibri 15')
button7_stop.configure(font='Calibri 15')
# Window Loop
root.mainloop()
[1]: https://i.stack.imgur.com/xIc0O.png
I am designing a front end using Tkinter but the .grid() option doesn't work as expected. I want to divide my screen to two section, LEFT and Right. All the buttons and labels on the left and the rest on the right.
# Initialise frames
self.frame_left = tk.Frame(root, bg = "pink", width = 100, height = 100).grid(row = 0, column = 0, sticky = 'E')
self.frame_right = tk.Frame(root, bg = "red", width = 100, height = 100).grid(row = 0, column = 1, sticky = 'W')
root.grid_columnconfigure(0, weight=0)
root.grid_columnconfigure(1, weight=0)
#labels
self.Name_Label = tk.Label(self.frame_left, text = "Name", font = 12, fg = 'green').grid(row = 1, column = 1)
self.Phone_Label = tk.Label(self.frame_left, text = "Phone Number", font = 12, fg= 'green').grid(row = 1, column =2)
self.University_label = tk.Label(self.frame_left, text = "University", font = 12, fg = 'green').grid(row = 1, column = 3)
#Search boxex
self.Name_box = tk.Entry(self.frame_left, width = 12, borderwidth = 2).grid(row = 2, column = 1)
self.Phone_box = tk.Entry(self.frame_left, width = 12, borderwidth = 2).grid(row = 2, column = 2)
self.Phone_box = tk.Entry(self.frame_left, width = 12, borderwidth = 2).grid(row = 2, column = 3)
# Buttons
self.Search_button = tk.Button(self.frame_left, text='Search', padx = 10, pady = 10, font = 12, fg = 'black').grid(row = 5, column = 1)
#Screen
#self.Screen = tk.Listbox(self.frame_right, width = 20, height = 20, font = 1).grid(row = 0, column = 0)
It seems the labels and buttons are being placed on the root window not the frames that has been defined.
Appreciate your help.
Regards
Khisrow
To divide your screen into 2 parts, you need to use the option columnconfigure:
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
This creates a grid on the root window with 2 columns in which your self.frame_left and self.frame_right can be placed.
When you store a .grid() item you are not storing the widget:
self.frame_left = tk.Frame(root, bg = "pink", width = 100, height = 100).grid(row = 0, column = 0, sticky = 'E')
Stores the grid object to the variable, not the Frame.
This can be fixed by doing the creation and grid in two lines.
import tkinter as tk
class Test():
def __init__(self):
root = tk.Tk()
#EXAMPLE OF DIFFERENCE
self.frame_left = tk.Frame(root, bg = "pink", width = 100, height = 100).grid(row = 0, column = 0, sticky = 'E')
print(self.frame_left, "DIDN'T STORE THE FRAME")
self.frame_left = tk.Frame(root, bg = "pink", width = 100, height = 100)
self.frame_left.grid(row = 0, column = 0, sticky = 'E')
print(self.frame_left, "STORED THE FRAME")
#EXAMPLE OF DIFFERENCE
# Initialise frames
self.frame_left = tk.Frame(root, bg = "pink", width = 100, height = 100)
self.frame_left.grid(row = 0, column = 0, sticky = 'E')
self.frame_right = tk.Frame(root, bg = "red", width = 100, height = 100)
self.frame_right.grid(row = 0, column = 1, sticky = 'W')
root.grid_columnconfigure(0, weight=0)
root.grid_columnconfigure(1, weight=0)
#labels
self.Name_Label = tk.Label(self.frame_left, text = "Name", font = 12, fg = 'green').grid(row = 1, column = 1)
self.Phone_Label = tk.Label(self.frame_left, text = "Phone Number", font = 12, fg= 'green').grid(row = 1, column =2)
self.University_label = tk.Label(self.frame_left, text = "University", font = 12, fg = 'green').grid(row = 1, column = 3)
#Search boxex
self.Name_box = tk.Entry(self.frame_left, width = 12, borderwidth = 2)
self.Name_box.grid(row = 2, column = 1)
self.Phone_box = tk.Entry(self.frame_left, width = 12, borderwidth = 2)
self.Phone_box.grid(row = 2, column = 2)
self.Phone_box = tk.Entry(self.frame_left, width = 12, borderwidth = 2)
self.Phone_box.grid(row = 2, column = 3)
# Buttons
self.Search_button = tk.Button(self.frame_left, text='Search', padx = 10, pady = 10, font = 12, fg = 'black').grid(row = 5, column = 1)
#Screen
#self.Screen = tk.Listbox(self.frame_right, width = 20, height = 20, font = 1).grid(row = 0, column = 0)
Test()
EDIT: added a listbox with scrollbar
# Screen
scrollbar = tk.Scrollbar(self.frame_right)
scrollbar.grid(row = 0, column = 1, sticky = 'nsw')
self.Screen = tk.Listbox(self.frame_right, width = 20, height = 5, font = 1)
self.Screen.grid(row = 0, column = 0, sticky = 'e')
self.Screen.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=self.Screen.yview)
-------------------------------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.
The initial goal is to reduce the height of a frame to hide its lower part. This does not seem to work as long as there are still active widgets in the zone. So I use the 'visible' property to hide these widgets and 'height_request' to manage the height of the frame. The statement
self.frSaisie.set_property('height_request', 160)
(start Section of the code and in the callback) is totally inoperative. I even tried hiding the box ... still without result.
In addition, the masking works when it is activated by the CheckButton (but not the resizing), but is not taken into account when launching the application (bottom of the code).
If anyone has an idea, thanks in advance.
Sorry for the code length.
import gi
gi.require_version('Gtk','3.0')
from gi.repository import Gtk
class Appli(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, window_position = 1)
self.connect('delete-event', Gtk.main_quit)
# wid actifs
etNom = Gtk.Entry()
etPrenom = Gtk.Entry()
btValider = Gtk.Button('Valider')
btEnregistrer = Gtk.Button('Enregistrer')
btSupprimer = Gtk.Button('Supprimer')
btEffacer = Gtk.Button('Effacer')
self.ckGerer = Gtk.CheckButton('Gérer...', margin = 12)
self.ckGerer.connect('toggled', self.Gerer)
# wid container
gdIdentite = Gtk.Grid(margin = 6)
self.gdFonctions = Gtk.Grid(margin = 6, halign = 3, row_spacing = 6, column_spacing = 6)
self.frSaisie = Gtk.Frame(label = ' Saisie ', margin = 6, height_request = 400)
# Remplissage Grid
gdIdentite.attach(Gtk.Label('Nom', xalign = 1,margin_right = 6),0,0,1,1)
gdIdentite.attach(etNom,1,0,1,1)
gdIdentite.attach(Gtk.Label('Prénom', xalign = 1,margin_right = 6),0,1,1,1)
gdIdentite.attach(etPrenom,1,1,1,1)
self.gdFonctions.attach(btValider,0,0,1,1)
self.gdFonctions.attach(btEnregistrer,1,0,1,1)
self.gdFonctions.attach(btSupprimer,0,1,1,1)
self.gdFonctions.attach(btEffacer,1,1,1,1)
# Remplissage Box + Frame
self.bxSaisie = Gtk.Box(orientation = Gtk.Orientation(1))
self.bxSaisie.pack_start(gdIdentite, False, False, 0)
self.bxSaisie.pack_start(self.ckGerer, False, False, 0)
self.bxSaisie.pack_start(self.gdFonctions, True, True, 0)
self.frSaisie.add(self.bxSaisie)
self.add(self.frSaisie)
# Start
self.gdFonctions.set_property('visible', False) # not running at start
self.frSaisie.set_property('height_request', 160) # never running
self.show_all()
def Gerer(self, etat):
if self.ckGerer.get_active():
self.gdFonctions.set_property('visible', True)
else:
self.gdFonctions.set_property('visible', False) # running
self.frSaisie.set_property('height_request', 160) # never running
Appli()
Gtk.main()
It works better to resize the top window:
def Gerer(self, etat):
if self.ckGerer.get_active():
self.gdFonctions.set_property('visible', True)
else:
self.gdFonctions.set_property('visible', False) # running
self.resize(50, 50) # never running
Finally I worked around the problem using the Gtk.AspectFrame widget. The behavior is what I expected.
I replaced the declaration of the frame:
self.frSaisie = Gtk.Frame(label = ' Saisie ', margin = 6, height_request = 300)
by
self.frSaisie = Gtk.AspectFrame(label = ' Saisie ', margin = 6, \
height_request = 100, yalign = 0.001)
and I slightly modified the callback to simplify things.
However, I still do not understand why this formatting - now triggered by the function femMini - does not apply to startup.
If anyone could explain to me ... Thank you in advance
class Appli(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, window_position = 1, height_request = 400)
self.connect('delete-event', Gtk.main_quit)
# wid actifs
etNom = Gtk.Entry()
etPrenom = Gtk.Entry()
btValider = Gtk.Button('Valider')
btEnregistrer = Gtk.Button('Enregistrer')
btSupprimer = Gtk.Button('Supprimer')
btEffacer = Gtk.Button('Effacer')
self.ckGerer = Gtk.CheckButton('Gérer...', margin = 12)
self.ckGerer.connect('toggled', self.Gerer)
# wid container
gdIdentite = Gtk.Grid(margin = 6)
self.gdFonctions = Gtk.Grid(margin = 6, halign = 3, row_spacing = 6, column_spacing = 6)
#self.frSaisie = Gtk.Frame(label = ' Saisie ', margin = 6, height_request = 300)
self.frSaisie = Gtk.AspectFrame(label = ' Saisie ', margin = 6, \
height_request = 100, yalign = 0.001)
# Remplissage Grid
gdIdentite.attach(Gtk.Label('Nom', xalign = 1,margin_right = 6),0,0,1,1)
gdIdentite.attach(etNom,1,0,1,1)
gdIdentite.attach(Gtk.Label('Prénom', xalign = 1,margin_right = 6),0,1,1,1)
gdIdentite.attach(etPrenom,1,1,1,1)
self.gdFonctions.attach(btValider,0,0,1,1)
self.gdFonctions.attach(btEnregistrer,1,0,1,1)
self.gdFonctions.attach(btSupprimer,0,1,1,1)
self.gdFonctions.attach(btEffacer,1,1,1,1)
# Remplissage Box + Frame
self.bxSaisie = Gtk.Box(orientation = Gtk.Orientation(1))
self.bxSaisie.pack_start(gdIdentite, False, False, 0)
self.bxSaisie.pack_start(self.ckGerer, False, False, 0)
self.bxSaisie.pack_start(self.gdFonctions, True, True, 0)
self.frSaisie.add(self.bxSaisie)
self.add(self.frSaisie)
# Start
self.fenMini()
self.show_all()
# Méthodes
def fenMini(self):
self.gdFonctions.set_property('visible', False)
self.frSaisie.set_property('height_request', 120)
def fenMaxi(self):
self.gdFonctions.set_property('visible', True)
# Callbacks
def Gerer(self, etat):
if self.ckGerer.get_active():
self.fenMaxi()
else:
self.fenMini()
Appli()
Gtk.main()
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()