Im using python 2.7 to build a satellite tracker for a cubesat project at my university. Now I've got the whole thing running as I want it to. I produce 4 images and a load of text based on the ISS's orbit parameters as our cubesat is not yet flying.
The 4 pictures are:
1) Satellite's current position on a globe based on its TLE straight from celestrak.
2) Satellite's current position on a mercator(flat) map.
3) Its current lat/lon position translated to a google earth view to physically interpret where it is.
4) Its current lat/lon position based on current weather maps, for whether or not there are clouds in the region, obscuring the satellites remote sensing imaging capabilities. (Reason why the picture looks ugly and purple, is because this region had no current weather data at the time of retrieving data)
Then I need to implement a text box with information on altitude, velocity, spatial resolution etc.
It's all nice and dandy. But I cant for the love of god figure out how to get this Tkinter GUI to play nice! I'm a geoscientist, not a computer scientist and python programming is very new to me :D
Anyway I did a quick layout in photoshop as of how I want the finished data to be produced in a Tkinter GUI. See the primitive image below:
Now here is my shameful code below:
import Tkinter as tk
from PIL import ImageTk, Image
#This creates the main window of an application
window = tk.Tk()
window.title("Satellite Control Center")
window.geometry("1000x800")
window.configure(background='grey')
#Imports the pictures.
pic1 = "Globeview.png"
pic2 = "MercatorView.png"
pic3 = "currentweathercroppedsmall.png"
pic4 = "GECurrentcroppedsmall.png"
#Creates a Tkinter-compatible photo image, which can be used everywhere Tkinter expects an image object.
img1 = ImageTk.PhotoImage(Image.open(pic1))
img2 = ImageTk.PhotoImage(Image.open(pic2))
img3 = ImageTk.PhotoImage(Image.open(pic3))
img4 = ImageTk.PhotoImage(Image.open(pic4))
#The Label widget is a standard Tkinter widget used to display a text or image on the screen.
globeview = tk.Label(window, image = img1)
mercatorview = tk.Label(window, image = img2)
currentweather= tk.Label(window, image = img3)
gearth = tk.Label(window, image = img4)
#The Pack geometry manager packs widgets in rows or columns.
globeview.pack(side = "top", fill = "both", expand = "yes")
mercatorview.pack(side = "top", fill = "both", expand = "yes")
currentweather.pack(side = "bottom", fill = "both", expand = "yes")
gearth.pack(side = "bottom", fill = "both", expand = "yes")
#Start the GUI
window.mainloop()
Which produces this horror show!
My issues are clearly:
1) Images are not aligned in any way I want. Normally in HTML I'd set up table rows, align and fit it with spacers as I want. But I don't know how to define that here and I've spend hours being frustrated of this by now.
2) I need to add a text box. Every time I've tried to add various versions of text boxes. I get weird pyimage'xx' errors and no text box seems to materialize.
3) For the future: A button under the images that will show the full size uncropped picture. But that's not imperative right now!
So I'm hoping one of you have a nice way to do this, or can point me in a direction.. or perhaps even have done something like it where I can see your code and just tweak the numbers of a bit for aligning the pixels.
Thank you in advance.
You are trying to lay everything out in a single frame. That can be done, but it's much easier to make subframes for things that fall in neat rows, columns or grids, and then put the subframes into the final arrangement.
Totally untested guess:
import Tkinter as tk
from tkFont import Font
from PIL import ImageTk, Image
#This creates the main window of an application
window = tk.Tk()
window.title("Aarhus University Satellite Control Center")
window.geometry("1000x800")
window.configure(background='grey')
#Imports the pictures.
pic1 = "Globeview.png"
pic2 = "MercatorView.png"
pic3 = "currentweathercroppedsmall.png"
pic4 = "GECurrentcroppedsmall.png"
#Creates a Tkinter-compatible photo image, which can be used everywhere Tkinter expects an image object.
img1 = ImageTk.PhotoImage(Image.open(pic1))
img2 = ImageTk.PhotoImage(Image.open(pic2))
img3 = ImageTk.PhotoImage(Image.open(pic3))
img4 = ImageTk.PhotoImage(Image.open(pic4))
header = tk.Label(window, text="Header", font=Font(size=40))
header.pack()
toprow = tk.Frame(window)
globeview = tk.Label(toprow, image = img1)
globeview.pack(side = "left") # the side argument sets this to pack in a row rather than a column
infobox = tk.Text(toprow)
infobox.pack(side = "left")
toprow.pack() # pack the toprow frame into the window
bottomrow = tk.Frame(window)
mercatorview = tk.Label(bottomrow, image = img2)
currentweather= tk.Label(bottomrow, image = img3)
gearth = tk.Label(bottomrow, image = img4)
mercatorview.pack(side = "left")
currentweather.pack(side = "left")
gearth.pack(side = "left")
bottomrow.pack()
#Start the GUI
window.mainloop()
import Tkinter as tk
from PIL import ImageTk, Image
#This creates the main window of an application
window = tk.Tk()
window.title("Aarhus University Satellite Control Center")
window.geometry("1000x800")
window.configure(background='grey')
#Imports the pictures.
pic1 = "Globeview.png"
pic2 = "MercatorView.png"
pic3 = "currentweathercroppedsmall.png"
pic4 = "GECurrentcroppedsmall.png"
#Creates a Tkinter-compatible photo image, which can be used everywhere Tkinter expects an image object.
img1 = ImageTk.PhotoImage(Image.open(pic1))
img2 = ImageTk.PhotoImage(Image.open(pic2))
img3 = ImageTk.PhotoImage(Image.open(pic3))
img4 = ImageTk.PhotoImage(Image.open(pic4))
#The Label widget is a standard Tkinter widget used to display a text or image on the screen.
globeview = tk.Label(window, image = img1).grid(row=0,column=0)
mercatorview = tk.Label(window, image = img2).grid(row=1,column=0)
currentweather= tk.Label(window, image = img3).grid(row=1,column=1)
gearth = tk.Label(window, image = img4).grid(row=1,column=2)
#Start the GUI
window.mainloop()
You need to add row and column in the label grid option. After you are creating the Label , put the grid and mention row and column . I have updated the code, just check it . If you face any problem write us back, and remove pack, which I deleted in the code :) Cheers
Related
I am attempting to rotate an label with an image which is on a canvas with tkinter.
I have three images that need rotating (pitch, roll and yaw) and they will eventually rotate according to IMU sensor outputs.
import tkinter as tk
from tkinter import PhotoImage
from PIL import Image
root = tk.Tk()
root.title('Pitch/Roll/Yaw Simulator')
# pick image file
fname = "PRY_Diag_Dials.png"
bg_image = tk.PhotoImage(file=fname)
# get the width and height of the image
w = bg_image.width()
h = bg_image.height()
# size the window so the image will fill it
root.geometry("%dx%d+50+30" % (w, h))
cv = tk.Canvas(root, width=w, height=h)
cv.pack(side='top', fill='both', expand='yes')
cv.create_image(0, 0, image=bg_image, anchor='nw')
#add images
pitch = tk.PhotoImage(file="Pitch2.gif")
pitch_lbl = tk.Label(cv, image=pitch,bg="white")
pitch_lbl.image = pitch
pitch_lbl.place(x=60, y=180)
roll = tk.PhotoImage(file="Roll2.gif")
roll_lbl = tk.Label(cv, image=roll,bg="white")
roll_lbl.image = roll
roll_lbl.place(x=325, y=180)
yaw = tk.PhotoImage(file="Yaw2.gif")
yaw_lbl = tk.Label(cv, image=yaw,bg="white")
yaw_lbl.image = yaw
yaw_lbl.place(x=590, y=180)
root.mainloop()
How can I rotate the image labels through tkinter?
tkinter doesn't have any support for rotating canvas items.
From the official tcl/tk documentation (tkinter is a wrapper around a tcl interpreter):
Individual items may be moved or scaled using widget commands described below, but they may not be rotated.
If you are looking to simple rotate 90, 180 or flip then you can use PIL to transpose.
See this link for the details: Transpose.
Here is the important bits just in case link brakes in the future:
Image.transpose(method)
Transpose image (flip or rotate in 90 degree steps)
Parameters: method – One of:
PIL.Image.FLIP_LEFT_RIGHT
PIL.Image.FLIP_TOP_BOTTOM
PIL.Image.ROTATE_90
PIL.Image.ROTATE_180
PIL.Image.ROTATE_270
PIL.Image.TRANSPOSE
Returns: Returns a flipped or rotated copy of this image.
I am preparing data for deep running. So I have to get certain pixel coordinates for each picture. Only one coordinate per photo is required.
So when I use PIL to input one click, I try to implement coordinates so that I can go to the next picture.
However, when I write the code as below, the coordinates are output in duplicate to only one picture, and the next picture does not appear on the screen.
How can I make sure that only one coordinate is recorded on a single picture?
from PIL import Image, ImageTk
import tkinter
import os
URL = './SavedImage/'
imgList = os.listdir(URL)
print(imgList)
width = 852
height = 480
stepW = 852/4
stepH = 480/5
def callback(event):
print("clicked at: ", event.x, event.y)
window = tkinter.Tk(className='pla')
for file in sorted(imgList):
a=True
image = Image.open(os.path.join(URL, file))
print(image)
canvas = tkinter.Canvas(window, width=image.size[0], height=image.size[1])
canvas.pack()
image_tk = ImageTk.PhotoImage(image)
canvas.create_image(image.size[0]//2, image.size[1]//2, image=image_tk)
canvas.bind("<Button-1>", callback)
tkinter.mainloop()
I am not 100% sure I understand what you need but it looks like to me you are trying to get one set of cord's for each image in a list of images.
I would do this by creating a function and a tracking variable to loop through each image on at a time and on click update a new list with the image and cord's then loop to next image.
Let me know if you have any questions.
Example:
from PIL import Image, ImageTk
import tkinter
import os
URL = './SavedImage/'
imgList = os.listdir(URL)
width = 852
height = 480
stepW = 852/4
stepH = 480/5
tracker = 0
list_images_with_cords = [] # added list for final results
def callback(event):
# Added global's.
global tracker,list_images_with_cords
# Used to append final results to list.
list_images_with_cords.append([imgList[tracker], event.x, event.y])
# This tracker lets us go through each item on the list.
tracker += 1
# After appending list go to next image.
open_next()
window = tkinter.Tk(className='pla')
# Creates just one canvas that we can update later.
canvas = tkinter.Canvas(window)
canvas.pack()
def open_next():
# Adding global's.
global image, canvas, image_tk, tracker
# Clearing canvas before drawing new image.
canvas.delete("all")
# Checking for valid index in list.
if tracker < len(imgList):
image = Image.open(os.path.join(URL, imgList[tracker]))
# use config() to update canvas.
canvas.config(width=image.size[0], height=image.size[1])
image_tk = ImageTk.PhotoImage(image)
canvas.create_image(image.size[0]//2, image.size[1]//2, image=image_tk)
canvas.bind("<Button-1>", callback)
else:
# This else statement is just for when we run out of images.
# It will display all the results in a textbox.
canvas.destroy()
txt = tkinter.Text(window, width=25)
txt.pack()
for item in list_images_with_cords:
txt.insert("end", "{}\n\n".format(item))
open_next()
tkinter.mainloop()
I am trying to use tkingter to make a card game.
set a table image as background of the canvas.
draw cards on top of the table background. This will be triggered by clicking a button (not shown here)
The problem is I can't create card image on top of table background. what's the right way to do it? do i need to create another canvas for card, in stead of directly drawing on table background? I feel there is something fundamental that i am missing here.
from tkinter import *
from PIL import Image, ImageTk
# globals
table_dir = "C:/Python36/resourse/table.png"
card_dir = "C:/Python36/resourse/card.jpg"
#CREATE APP
root = Tk()
#LOAD IMAGES
table_PIL = Image.open(table_dir)
table_image = ImageTk.PhotoImage(table_PIL)
card_PIL = Image.open(card_dir)
card_image = ImageTk.PhotoImage(card_PIL)
#make canvas and set background image with a label
canv = Canvas(root, width=table_PIL.width, height=table_PIL.height, background="white")
background_label = Label(canv, image = table_image)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
canv.grid(row=0, column=0)
#trying to create card image on top of background table, not working
canv.create_image(200, 100, image=card_image)
root.mainloop()
Don't use a label for the background. Use canv.create_image(...) to create the background, just like you do for creating cards.
I have worked out how to have an image for a button, thats positioned on top of a label (I think I maybe doing it the long-winded way because I can't install PIL on my Mac for some reason). Anyhow, it works as it should to a certain degree - the problem I have is it's adding white space either side, and then the image itself is not displaying its transparent background.
The code I am using is as follows:
from tkinter import *
#from PIL import Image
root = Tk()
#Removes the title bar and places over mac top bar
root.tk.call("::tk::unsupported::MacWindowStyle", "style", root._w, "plain", "none")
# Makes the app full screen
#root.wm_attributes('-fullscreen', 1)
root.geometry('{}x{}'.format(480, 320))
#root.attributes('-topmost', True)
def quitApp():
# mlabel = Label (root, text = 'Close').pack()
root.destroy()
background_img = PhotoImage(file="images/bg.gif")
scanBtn_img = PhotoImage(file="images/scanBtn.gif")
background = Label(root,
compound = CENTER,
quitButton = Button(image=scanBtn_img, command = quitApp).pack(),
image = background_img).pack(side="right")
background.image = background_img # keep a reference!
root.mainloop()
From what I understand tkinter natively supports transparency on images like GIF.
I chopped up your code a little but it does work for me. Maybe there is a problem with how you have set up your code. Your label also has a button in it. I don't think you need to have both. You can just created the button where you want it.
Just for reference I created a Label and a Button packed on different sides with a black background to show the transparency of the image.
Here is the code I used to test a gif I have that has transparency. I tested this on both python 3.6 and 2.7 just in case.
from tkinter import *
root = Tk()
def quitApp():
root.destroy()
background_img = PhotoImage(file="Colors/sa.gif")
scanBtn_img = PhotoImage(file="Colors/sa.gif")
background = Label(root,bg='black', image = background_img).pack(side = RIGHT)
quitButton = Button(bg='black', image=scanBtn_img, command = quitApp).pack(side = LEFT)
backgroundimage = background_img # keep a reference!
root.mainloop()
Update: I used the gif you link in the comment
Here is the result.
Update:
After doing some more digging I found what might work for Mac OS:
I don't have a Mac to test on right now so let me know if this works for you:
from tkinter import *
root = Tk()
# Hide the root window drag bar and close button
root.overrideredirect(True)
# Make the root window always on top
root.wm_attributes("-topmost", True)
# Make the window content area transparent
root.wm_attributes("-transparent", True)
# Set the root window background color to a transparent color
root.config(bg='systemTransparent')
def quitApp():
root.destroy()
background_img = PhotoImage(file="Colors/1.gif")
scanBtn_img = PhotoImage(file="Colors/1.gif")
background = Label(root,bg='black', image = background_img)
background.pack(side = RIGHT)
background.config(bg='systemTransparent')
quitButton = Button(bg='black', image=scanBtn_img, command = quitApp)
quitButton.pack(side = LEFT)
quitButton.config(bg='systemTransparent')
backgroundimage = background_img # keep a reference!
root.mainloop()
I started to learn Python one month ago. Sorry if my question is not good, this is my first question here.
I have made a small game using tkinter, but I have a problem.
I made a big label with a picture on it as background. Whenever I make more labels with text on them, the text will have gray background. However what I want is for every text to have the picture that I already placed as background.
Here's some code to explain it:
from tkinter import*
x=Tk()
x.geometry("1000x1000")
z=PhotoImage(file="D:\\Blue.gif")
v=Label(x,text="hi",font=100,fg="red",compound=CENTER,image=z,width=1000,height=1000)
v.place(x=0,y=0)
v1=Label(x,text="OO",font=100,fg="red")
v1.place(x=300,y=400)
x.mainloop()
The v label works very well as long as I use compound with it. It shows the picture with the text "hi" on it.
However I want the v1 label to have the same background as v, instead of gray background.
All widgets have background - they can't be transparent.
You can use tk.Canvas to put text without background on image or transparent image on text.
effbot.org: Canvas, PhotoImage
#!/usr/bin/env python3
import tkinter as tk
from PIL import Image, ImageTk
# --- constants ---
WIDTH = 800
HEIGHT = 600
# --- main ---
root = tk.Tk()
c = tk.Canvas(root, width=WIDTH, height=HEIGHT)
c.pack()
# only GIF and PGM/PPM
#photo = tk.PhotoImage(file='test.gif')
# other formats
image = Image.open('test_transparent.png')
photo = ImageTk.PhotoImage(image)
# use in functions - solution for "garbage collector" problem
c.image = photo
i = c.create_image((WIDTH//2, HEIGHT//2), image=photo)
t = c.create_text((WIDTH//2, HEIGHT//2), text='Hello World')
root.mainloop()
Change order and you get image on text
t = c.create_text((WIDTH//2, HEIGHT//2), text='Hello World')
i = c.create_image((WIDTH//2, HEIGHT//2), image=photo)
test_transparent.png (image with transparent background)