Display Google Map API in Python Tkinter window - python

Hi I am working on Google Map API in Python. I am using the source code which can be found at this website
This code when compiled produces a 'htm' file showing a Google Map with the markers placed on the map.
So I have created a Window Frame shown below:
from Tkinter import * # order seems to matter: import Tkinter first
import Image, ImageTk # then import ImageTk
class MyFrame(Frame):
def __init__(self, master, im):
Frame.__init__(self, master)
self.caption = Label(self, text="Some text about the map")
self.caption.grid()
self.image = ImageTk.PhotoImage(im) # <--- results of PhotoImage() must be stored
self.image_label = Label(self, image=self.image, bd=0) # <--- will not work if 'image = ImageTk.PhotoImage(im)'
self.image_label.grid()
self.grid()
im = Image.open("test.html") # read map from disk
# or you could use the PIL image you created directly via option 2 from the URL request ...
mainw = Tk()
mainw.frame = MyFrame(mainw, im)
mainw.mainloop()
And with that Window Frame I want to display the 'htm' image of the Google Map in that Window Frame.

The htm image pymaps produces isn't an image, it's an html file. Basically a little webpage. To display it, you would have to render the html. The only html renderer for TkInter that I know of is TkHTML, although I've never used it, so it might not support all the javascript that you html file uses.
You would be much better off dropping TkInter entirely and switching to a more modern widget toolkit such as wxPython which has html rendering built in. You can see the documentation for html in wxPython here. If you have GTK on your system, I've used pywebkitgtk successfully.
However, do you need to render this frame for something specific? If you just want to open the file from python, you can use the webbrowser built in library to open it with your default browser.
import webbrowser
webbrowser.open('test.htm')
And that's it.

If somebody wants to have an interactive Google-Maps widget inside their Tkinter application like in the example above, I wrote a small library that displays tile based maps. The standard server is OpenStreetMap but you can change it to Google-Maps if you want. But note that the Google-Maps tile server is deprecated and will probably don't work at some point in the future.
Documentation: https://github.com/TomSchimansky/TkinterMapView
Install: pip3 install tkintermapview
With the following code you get a fully working Google-Maps widget inside a Tkinter window:
import tkinter
from tkintermapview import TkinterMapView
root_tk = tkinter.Tk()
root_tk.geometry(f"{600}x{400}")
root_tk.title("map_view_simple_example.py")
# create map widget
map_widget = TkinterMapView(root_tk, width=600, height=400, corner_radius=0)
map_widget.pack(fill="both", expand=True)
# google normal tile server
self.map_widget.set_tile_server("https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}&s=Ga", max_zoom=22)
map_widget.set_address("Berlin Germany", marker=True)
root_tk.mainloop()

Related

Get icon of root window to be used by second window tkinter

I was wondering if there is anyway to get the ico file of one window and use it in the same window, without getting to know the icon location.
from tkinter import *
root = Tk()
root.iconbitmap('img/icn.ico')
top = Toplevel()
root.mainloop()
Here I want top to have icon of root without saying top.iconbitmap() or top.iconphoto(), the closest ive got is top.tk.call('wm','iconbitmap') but I dont know what is to be done with this as i couldnt find a understandable documentation.
Why dont I want to use iconbitmap(), its basically that, with tkinter.messagebox you can see the messagebox automatically inherit the icons from the parent widget. I was trying to duplicate this effect. Where if the icon is the default tk icon, then show blank icon or else show the custom icon.
Thanks in advance :D
[I'm using links into the core Tk documentation here. It's much more accurate than the Tkinter docs for most things, and Tkinter is mostly an obvious thin wrapper around it.]
You don't want wm iconbitmap. That's been effectively obsolete for decades; it uses an object class — bitmap — that's not relevant these days as it is monochrome and uses the weirdest format. (Filenames need to be preceded by # to make them work.)
Instead, you want to manipulate the wm iconphoto of the toplevel windows concerned. These take true photo images (there are many image file formats you can load into them) and you can share them easily.
# Load the image from the file; can also use PNG and other formats
my_image = PhotoImage(file="image.gif")
# Apply the image as the icons
first_toplevel_window.iconphoto(False, my_image)
second_toplevel_window.iconphoto(False, my_image)
Note that how the icon is displayed can vary wildly; it's not under your control.
You can use iconphoto() and set the first argument to True, then the same icon will be used for future created toplevels as well:
import tkinter as tk
root = tk.Tk()
icn = tk.PhotoImage(file='my-icon.png')
root.iconphoto(True, icn)
top = tk.Toplevel(root)
root.mainloop()
If you use the default instead of the bitmap (or first) argument, the icon will automatically be used on all TopLevel windows:
root.iconbitmap('img/icn.ico') # icon set only on root
root.iconbitmap(bitmap='img/icn.ico') # same as above
root.iconbitmap(default='img/icn.ico') # icon set on root and all TopLevels

How to display multiple images inside tkinter window?

I want to display 7 different images and plot them inside tkinter window. I only know to display it using OpenCV which actually displays the image outside the Tkinter GUI window. How to plot the images inside the GUI window?
Tkinter GUI:
I advise you read the documentation of tkinter as it has tons of example on how to achieve a soluction to your problem. I have made a sample GUI which updates image on the GUI with a randomized pixel picture. Note that there are a lot of different approaches how to do this. In my case I have made a class in which I display a frame and a button. The button calls a function to randomize the image (or changes to the next one in your case) and calls the function to update the frame with a new image. Hope it gives you a jump start. Cheers!
P.S.: for multiple images use more labels and functions;)
Code:
import tkinter as tk
from tkinter import *
import cv2
import numpy as np
from PIL import Image, ImageTk
class DisplayImage:
def __init__(self, master):
self.master = master
master.title("GUI")
self.image_frame = Frame(master, borderwidth=0, highlightthickness=0, height=20, width=30, bg='white')
self.image_frame.pack()
self.image_label = Label(self.image_frame, highlightthickness=0, borderwidth=0)
self.image_label.pack()
self.Next_image = Button(master, command=self.read_image, text="Next image", width=17, default=ACTIVE, borderwidth=0)
self.Next_image.pack()
def display_image(self, event=None):
self.cv2image = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGBA)
self.from_array = Image.fromarray(self.cv2image)
self.imgt = ImageTk.PhotoImage(image=self.from_array)
self.image_label.configure(image=self.imgt)
def read_image(self, event=None):
self.img = np.random.randint(255, size=(250,250,3),dtype=np.uint8)
self.master.after(10, self.display_image)
def main():
root = tk.Tk()
GUI = DisplayImage(root)
GUI.read_image()
root.mainloop()
if __name__ == '__main__':
main()
Output:
If you are OK with using a wrapper with tkinter, then PySimpleGUI is a good choice.
There was a new Demo application posted this week that demonstrates how to show a webcam in a GUI window. There's another Demo posted that plays back a video file using OpenCV, again in a GUI window.
The code that generated that screen shot can be found here:
Open and Play Video Using PySimpleGU + OpenCV
You can start with the Demo and expand it by adding more buttons.

TkInter script vs class - Canvas behaviour [duplicate]

This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 7 years ago.
I'm using TkInter to write a GUI that will contain an image and a few buttons in a panel next to the image.
I started by writing a script that would allow me to visualize an image, and it works just fine:
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
import Tkinter
from PIL import Image, ImageTk
window = Tkinter.Tk()
window.title("Test GUI")
window.geometry("640x478")
window.configure(background='grey')
window.grid()
img = ImageTk.PhotoImage(Image.open('./test.jpg'))
canvas = Tkinter.Canvas(window, width=640, height=478, bg='white')
canvas.create_image(0,0,anchor='nw',image=img)
canvas.grid(column=0,row=0)
window.mainloop()
I then tried to rewrite the above code as a class, to implement some event-handling functions. However, the same exact code written in the class initialization function will not visualize the image.
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
import Tkinter
from PIL import Image, ImageTk
class showImageGUI(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def initialize(self):
# the grid layout manager is a simple grid
# where you put your widgets
self.grid()
img = ImageTk.PhotoImage(Image.open('./test.jpg'))
canvas = Tkinter.Canvas(self, width=640, height=478, bg='white')
canvas.create_image(0,0,anchor='nw',image=img)
canvas.grid(column=0,row=0)
if __name__ == "__main__":
app = showImageGUI(None)
app.title('Test GUI')
# event-driven programming: the program will
# loop forever doing nothing but wait for events
# and only react when it receives an event
app.mainloop()
The only difference between the two is:
In the script implementation I assign the parent of the canvas widget to be the whole window.
In the class implementation I assign the parent of the canvas widget to be the self variable for the whole app.
Can someone please explain me why is this breaking the code / how to solve it?
There's a bug in Tkinter that causes images to disappear if there is no external reference to them, even though they should be bound into the Canvas widget somehow. I'm probably not explaining this well, because I've never taken the trouble to really research what is going on. I believe it is explained somewhere on effbot.org.
In any event, change the line
img = ImageTk.PhotoImage(Image.open('./test.jpg'))
to
img = self.img = ImageTk.PhotoImage(Image.open('./test.jpg'))
and I think it will work for you. It works for me.

Python Tkinter: How do I apply a new background image when opening a new tk window?

I used the code below (with different variable names for each section) to create a background image for each tkinter window. Each of these is initiated in a function and both work fine independently.
When loading one function from another however, the second fails to display an image. (I have tried importing all relevant in each function aswell). It works in the case that use tk.destruct(), however if If I want to keep it open, or hide it with . withdraw(), the image fails to display, rendering the second window useless.
background_image=tk.PhotoImage(...)
background_label = tk.Label(parent, image=background_image)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
Ok I've made up a solution for you. Basically all you need is to use tk.Toplevel() for the second tkinter window and make sure that the 'parent' is root2 so the image will appear in the second window.
I have used buttons for the images, you had labels so you may wish to change this, but buttons gave me a way to open a new tk window easily, I have also used .pack(), not .place(), as it was faster for me. May also be helpful for you to know that I used python 3.3 with windows so you might need a capital T for tkinter.
import tkinter as tk
root1 = tk.Tk()
def new_window():
root2 = tk.Toplevel()
# click the last button and all tk windows close
def shutdown():
root1.destroy()
root2.destroy()
background_image2 = tk.PhotoImage(file = '...')
background_button2 = tk.Button(root2, image = background_image2, command = shutdown)
background_button2.pack()
root2.mainloop()
background_image1 = tk.PhotoImage(file = '...')
# have used a button not a label for me to make another tk window
background_button1 = tk.Button(root1, image = background_image1, command = new_window)
background_button1.pack()
root1.mainloop()
#user2589273 Next time you should add more code so answers can be easily given, and tailored to you, just a suggestion. Hope this helps.

Setting Application icon in my python Tk base application (On Ubuntu)

I want to set an image in my GUI application built on Python Tk package.
I tried this code:
root.iconbitmap('window.xbm')
but it gives me this:
root.iconbitmap('window.xbm')
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1567, in wm_iconbitmap
return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
_tkinter.TclError: bitmap "window.xbm" not defined
Can anyone help?
You want to use wm iconphoto. Being more used to Tcl/Tk than Python Tkinter I don't know how that is exposed to you (maybe root.iconphoto) but it takes a tkimage. In Tcl/Tk:
image create photo applicationIcon -file application_icon.png
wm iconphoto . -default applicationIcon
In Tk 8.6 you can provide PNG files. Before that you have to use the TkImg extension for PNG support or use a GIF. The Python PIL package can convert images into TkImage objects for you though so that should help.
EDIT
I tried this out in Python as well and the following worked for me:
import Tkinter
from Tkinter import Tk
root = Tk()
img = Tkinter.Image("photo", file="appicon.gif")
root.tk.call('wm','iconphoto',root._w,img)
Doing this interactively on Ubuntu resulted in the application icon (the image at the top left of the frame and shown in the taskbar) being changed to use my provided gif image.
This worked for me
from tkinter import *
raiz=Tk()
raiz.title("Estes es el titulo")
img = Image("photo", file="pycharm.png")
raiz.tk.call('wm','iconphoto',raiz._w, img)
raiz.mainloop()
Try this:
root.iconbitmap('#window.xbm')
And quote:
Set (get) the icon bitmap to use when this window is iconified. This method are ignored by some window managers (including Windows).
Note that this method can only be used to display monochrome icons. To display a color icon, put it in a Label widget and display it using the iconwindow method instead.

Categories