Code Monkey home page Code Monkey logo

tkintermapview's People

Contributors

arnehaak avatar davidoesch avatar tomschimansky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tkintermapview's Issues

Typo in examples

self.map_widget.set_tile_server("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png") # OpenStreetMap (default)
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) # google normal
self.map_widget.set_tile_server("https://mt0.google.com/vt/lyrs=s&hl=en&x={x}&y={y}&z={z}&s=Ga", max_zoom=22) # google satellite
self.map_widget.set_tile_server("http://c.tile.stamen.com/watercolor/{z}/{x}/{y}.png") # painting style
self.map_widget.set_tile_server("http://a.tile.stamen.com/toner/{z}/{x}/{y}.png") # black and white
self.map_widget.set_tile_server("https://tiles.wmflabs.org/hikebike/{z}/{x}/{y}.png") # detailed hiking
self.map_widget.set_tile_server("https://tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png") # no labels
self.map_widget.set_tile_server(""https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg") # swisstopo map

Last entry has an extra set of quotations.

Polygons with donut holes

Hi Tom,
I'm trying to display a "donut" polygon that has an outer ring and an inner ring. The way the polygon is with a None type point separating the outer ring points from the inner ring. Something like this (Note, these are just example points from a more complex polygon):
[ (35.966916026000035, -119.73706605599995),
(35.963160585000026, -119.73713219299998),
(35.96310003800005, -119.75422644199995),
(35.96358683400007, -119.75421395799998),
(35.963579872000025, -119.75467458899999),
(35.96310092900006, -119.75467313499996),
(35.96313411600005, -119.77193926999996),
(35.96316571400007, -119.78990182199999),
(35.963125637000076, -119.79867769199996),
(35.96308466200003, -119.80750611499997),
(35.96311094600003, -119.82515756999999),
None,
(36.04973748100008, -119.80665732999995),
(36.04978930400006, -119.80665667099998),
(36.049910225000076, -119.80665513499997),
(36.05006180300006, -119.82450578099997) ]

I've been racking my brain on how to display it in your widget (very awesome btw), but can't think of a better method that this one: https://stackoverflow.com/questions/50071801/erase-area-within-polygon-in-tkinter-canvas. This would work for the most part, but I thought I ask if you had any ideas?

Smoother Zoom

At the moment, the zoom step size is 1. Is it possible to set it to something like 0.1 to make a smooth zoom effect?

_tkinter.TclError: image "pyimage3" doesn't exist

Thought I'd try to implement your TkinterMapView into my program today and as soon as I tried to display an instance of TkinterMapView:

agency_map = TkinterMapView(map_window, width=1920, height=1080, corner_radius=0) agency_map.grid(row=0, column=0)

I got the error mentioned in the title, referring to a series of tkintermapview functions.
Has support ended for this library?

Thanks,
JR

Question: delete a marker?

When a marker is activated by pressing the mouse, what name will it get? Can this name be used directly to to delete the marker by "marker".delete?

Question about paths

Hello Tom,

Would it be possible to add similar functionality to paths that you added recently to markers? (styling, colours, callbacks?)

I've taken it upon myself to learn Python (a bit) and am trying to recreate some basic GUI items that I already have in a Matlab application. Amongst these items is the drawing of multiple polylines. I've found your tkintermapview and already succeeded in drawing a polyline by using your path option. However, for multiple paths of different categories, I'd like to have a visual difference between the paths.

In this respect, I'm trying to understand how the paths work with the canvas of tkinter. Are these essentially sparsely filled bitmaps stacked ontop of each other or are these actually "clickable" lines? In the basis I'm trying to get a feeling how scalable the approach of using the canvas is to draw many polylines on a map.

Marcel

Question about offline usage

Hey first of all great Project,

i have a quick question, is it possible to use this offline without the workaround with a local hosted map tile server?

e.g something like a caching function or a setting to specify a local map/tiles?

marker color will not update until it moves off screen then back on.

I am trying to have a marker change color when I click it. the command looks like this

    def click_command(self, marker):
        marker.marker_color_circle=self.blue
        marker.draw()
        print(marker.text)

This does not work until I move the screen so the marker goes out of view, and when it comes back into view it works.

Offline Map

The offline map: https://github.com/TomSchimansky/TkinterMapView/blob/main/examples/map_with_offline_tiles.py
Is not showing the content downloaded and stored in the db file.

I have used the load_offline_tiles.py to generate the nyc database and afterwards the [map_with_offline_tiles.py] (https://github.com/TomSchimansky/TkinterMapView/ blob/main/examples/map_with_offline_tiles.py)

The window showed is blank and nothing is displayed. If I change the property of the "use_database_only" to False, everythin is loaded except to nyc, which means that the database is not properly created with the script or the widget is not properly getting the information from the database.

Answer: It a matter of the osm tile policies, this means the tiles requested by the downloader do not have the tile.

Thanks in advance

problem in an async tkinter app 'PhotoImage' object has no attribute '_PhotoImage__photo'

I exactly followed your example codes but not working inside my async Tkinter app... you example files works fine but don't working inside my app... is there a compatibility problem with async_tkinter_loop?

This is how I add your widget just after my other widgets
map_widget = tkintermapview.TkinterMapView(root, width=200, height=200, corner_radius=0) map_widget.pack() map_widget.set_position(48.860381, 2.338594) # Paris, France map_widget.set_zoom(15)

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Exception ignored in: <function PhotoImage.del at 0x7f831923b0e0>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/ImageTk.py", line 146, in del
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'

Click on Placed Marker on Map and Obtain Attributes (A Request/Question)

Hi,
Thanks for the wonderful library you created.

I'd like to get the attributes of an already placed marker on the map so that I can edit it. Similar to the "Properties" feature of Google Earth when a user right-clicks on the pin mark to see the attributes and to change the pin name or description. I understand the entire process will be a function or another class to specify the process. However, I'm wondering how to obtain the address/id of an already placed marker by clicking on the area covered by the marker.

image

I'd appreciate your input.
Thanks

Path.add_position(x,y) Doesnt Update

When adding a valid position, using the path.add_position() function, the map is not redrawn.

This is because Line 49 of canvas_path.py is commented out.

Line 49 of canvas_path.py needs uncommenting to fix this issue

AttributeError set_text from df out of xlsx File

I do a map app wich reads names of places from an xlsx file. So i say map_widget.set_text(myplaces) and this works fine for my xlsx file i wrote by myself, but iwant to use another file that has the same colums an rows in it but i did not create this one. It is some kind of export. Any idea would be much appreciatet.

marker.set_text(df_someplace['name'][ind])
Error is: AttributeError: bool object has no attribute set_text

Support for local map tile servers without http:

Hi,

request_image() supports online mapservers and offline database. But it would be great if it would also support offline directories in the form of tileserver = /path/{z}/{x}/{y}.jpg. It could access the images directly with Image.open, without inserting requests.get. But I don't know how you would detect whether the supplied tileserver is an url or a path.

Usecase would be e.g. a standalone PC as a kiosk with its own local tileserver, without the need to install a webserver.

Cheers

Possible usage policy violation

I've been using your library for about a week without any issues, and it's been working as intended. But without making any changes to my code, today the map stopped displaying tiles. I've tried messing with environments and even used one of your examples, but it's still just a grey image. Upon further debugging, it seems like it fails in the request and returns a 403 restricted in this line of code.

image = Image.open(requests.get(url, stream=True).raw)

But if I add a User-Agent header it works again. Not sure exactly what's going on, but there is this section on their Tile Usage Policy. Here are some resources on their help site: 1, 2. It may be the case that you have to specify a custom User-Agent to adhere to their technical usage requirements since it's not being requested from a browser.

Toplevel

In windows
Toplevel window stop showing when i add the
top.resizable(width=False,height=False)
in mac os it's ok
could u please check it

code
//
import customtkinter as t

root=t.CTk()
root.geometry('600x300+100+100')
root.resizable(width=False,height=False)
def win():
top=t.CTkToplevel(root)
top.geometry('200x200+600+600')
top.resizable(width=False,height=False)

t.CTkButton(root,text='new win',command=win).pack()

root.mainloop()
//

Click on map to get city name

Hello,

Firstly, let me thank you for sharing the module.
I would like to know is there any way to click on the map and get Lat/Lon or City Name from it in pop-up window so I can manipulate this info for my needs.
Thanks in advance.

Clicking on Polygon and displaying attributes

Hi Tom,

I was trying to add a call back function when left clicking.

Basically I was using the following snippet to create a polygon and aggregate its information:

kwargs = {'fill_color':'',
                'border_width':3,
                'outline_color': "#e74c3c",
                'data': {'btrn': row[self.btrn_col], 
                        'gba_id_e': row[self.gba_id_e_col],
                        'name': row['name']},}
        self.map_widget.set_polygon(coordinates, command=self.display_polygon_info, **kwargs)

As you can see, coordinates are stored in a list (I created when starting the iteration in the for loop), then, I modified certain attributes of the polygon to be created (fill_color, border_width, outline_color , and data). As you can see I added the method within my class called self.display_polygon_info, as callback.

I declared at the beginning this method as well to be added as left_click_method as follows:

 self.map_widget.add_left_click_map_command(self.display_polygon_info)

The command or method for this sake, contains the following information:

def display_polygon_info(self, polygon): 
    print(f"polygon clicked - text: {polygon.data['name']}") 

So my problem, is: when I left click on the polygon being displayed on the tkintermapview, only in the terminal the information I am interested on is displayed, but not in the map. Is there something wrong with the approach I am taking to display information of a polygon on the map view?

Kind Regards

And thank you for the valuable contribution with this package!

Scope of mapview (colours, labels etc.)

Evening Tom,

Hope you're well, we talked earlier because I thought there was an issue with your software. I thought I'd open a discussion with you if you're happy to discuss the scope of the project? What are your plans for TkinterMapView?

I'm particularly interested in different coloured markers and adding labels to markers (tooltips/popups). I had a peep on some of your source files to see if I could change some attributes and maybe affect the colour of the markers. Unfortunately I could only find the attribute for the colour of the dark red circle inside the marker.

It has occurred to me however that the map may be displayed on a canvas? Since this is the case, is it possible for people to add their own images on top of the OSM map?

Thanks!

Zoom value limit at 19 ?

Hello,

Great work !
I was looking for resources to create a prototype tool with data entry on a map and your work meets my needs perfectly.

I started adding new methods to the TkinterMapView class to manually edit the map. I'll share those code parts once I'm done if you're interested.

I have a question about the zoom value limit which is set to 19. I would like to zoom a bit more (20 or 21) but even changing the max_value in the library doesn't seem to work. Is there a reason for this limit?

Another question, I saw on Reddit and in the logs that you had implemented auto-resizing. Is it for the map widget to keep the same size as the window? If so, I can't get it to work. If I enlarge the window, the widget keeps the same size as when it was created.

Regards,

Mouse scroll on linux returns delta = 0. For mouse wheel support under Linux, use Button-4 (scroll up) and Button-5 (scroll down).

Hi!
As I was trying out your nice program, I saw that mouse-scrolling does not work under linux. Event.delta always returns zero. As taken from this example online, I got it to work by adding the following lines to map_widget.py:

        self.canvas.bind("<MouseWheel>", self.mouse_zoom)
        self.canvas.bind("<Button-4>", self.mouse_zoom)
        self.canvas.bind("<Button-5>", self.mouse_zoom)

and

def mouse_zoom(self, event):
        relative_mouse_x = event.x / self.width
        relative_mouse_y = event.y / self.height
        print(event.num)
        if sys.platform == "darwin":
            new_zoom = self.zoom + event.delta * 0.1
        elif "win" in sys.platform:
            new_zoom = self.zoom + event.delta * 0.01
        elif event.num == 4:
            new_zoom = self.zoom + 1
        elif event.num == 5:
            new_zoom = self.zoom - 1

Cheers.

Customizable icon for position marker

Hi Tom,

The current icon for position marker looks good. However, sometimes it can be crowded when there are a lot of position markers in a small area. Would it be better if the icons for position markers are customizable? For example, dots, circles, crosses, stars, or squares with adjustable size, line width, line colour, filling colour, etc.

And thank you for your great work on this package!

Kind Regards

example map_with_customtkinter

Can you confirm there is no configuration needed for map_with_customtkinter example?

Does not seem to run as written. Thanks!

cannot import coordinate_convert_functions since version 1.10

As written in the title, since version 1.10 (released on April 24 2022) of this module, "from tkintermapview import coordinate_convert_functions" results in:

Import Error: cannot import name 'coordinate_convert_functions' from 'tkintermapview' (XXX/.local/pathon3.10/site-packages/tkintermapview/init.py)

This behaviour is not present in 1.9

I used the num2deg function of the coordinate_convert_functions to determine the coordinates of the position on the map, which I clicked on.

x_ratio = event.x/map_widget.winfo_width()
y_ratio = event.y/map_widget.winfo_height()

click_pos = math.num2deg(map_widget.upper_left_tile_pos[0] + (map_widget.lower_right_tile_pos[0] - map_widget.upper_left_tile_pos[0]) * x_ratio,
              map_widget.upper_left_tile_pos[1] + (map_widget.lower_right_tile_pos[1] - map_widget.upper_left_tile_pos[1]) * y_ratio,
              round(map_widget.zoom))

have the coordinate_convert_functions been renamed and if so, what is their new name? alternatively, what is currently the best way to retrieve the coordinates of a location on the map, that I clicked on?

Range Circles

Great job! Thank you for creating this super handy widget.

Feature Request: The ability to add a range circle centered on the specified lat, long with a radius in meters? [with a specified stroke/fill color w/alpha]. This could also be used as a smaller alternate waypoint indicator which would vary in size based on zoom level.

Regards

How to animate map movement

Hi, thanks for Tkintermapview.

Here is a support question, I hope you have the time to point me in the right direction.

I am trying to create an app where the user can choose two points on a map, and then let the app create an animated panning movement between the two points. I am using my own local tileserver, which are basically tiles of high resolution scans from antique maps. They aren't georeferenced, so it's just basically pixel coordinates.

I'm struggling with getting the map to move. I had hoped the self.map_widget.draw_move() call would do it, but it doesn't seem to.

Question about frame rate

Thanks for the project and I have a suggestion:
Currently if I drag and release the mouse, your map moves very smoothly when it is fading automatically. If I use my mouse to drag the map roughly in the same velocity like the fading part does, the movement look slightly less smooth, exactly like your gif here. Is there a way to fix?
圖片

Tkintermapview do not display the map

I create an ip location tracker with a GUI. The app supposed to show details of an specific ip from an API. Everything works right, but when I want to display a map for that specific location, the canvas for map appear but the map is not appear.

To display map I used tkintermapview from tkinter. To display the map I used latitude and longitude from that API to parse them to my map.

Here is the code:

import tkinter as tk
import tkintermapview
import requests
import ipaddress

from tkinter import *
from tkinter.ttk import *

def ipFinder(outputMsg, inputValue):
    try:
        ipAddress = inputValue.get()
        ipaddress.ip_address(ipAddress)
        response = requests.get(f'https://ipapi.co/{ipAddress}/json/').json()
        ip_version = response.get("version")
        city = response.get("city")
        region = response.get("region")
        country = response.get("country_name")
        postalcode = response.get("postal")
        continent = response.get("continent_code")
        lat = response.get("latitude")
        lng = response.get("longitude")
        outputMsg.config(text= "Information for " + inputValue.get() + " are:" + "\n"
                            "IP Version" + ' : ' + str(ip_version) + "\n"
                            "CITY" + ' : ' + str(city) + "\n"
                            "REGION" + ' : ' + str(region) + "\n"
                            "Country" + ' : ' + str(country) + "\n"
                            "Postal Code" + ' : ' + str(postalcode) + "\n"
                            "Continent" + ' : ' + str(continent) + "\n" 
                            "Latitude" + ' : ' + str(lat) + "\n" 
                            "Longitude" + ' : ' + str(lng) + "\n")   
    except:
        outputMsg.config(text="Please Enter Correct IP")
    
    # Define LabelFrame to show the map on my app
    my_label = tk.LabelFrame(Tk)
    my_label.grid(pady=20)

    # tkintermapview to fullfield my label with exact location of phone using lat and lng
    map_widget = tkintermapview.TkinterMapView(my_label, width=300, height=300, corner_radius=0)
    map_widget.set_position(lat, lng)
    # set_marker to set the marker on my map to see the location
    map_widget.set_marker(lat, lng, text = "Ip Location")
    # set_zoom to set the zoom on my map to actually see something
    map_widget.set_zoom(10)
    map_widget.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
    map_widget.grid()


Tk = tk.Tk()

Tk.geometry("600x600+{}+{}".format(600, 600))

authorLable = tk.Label(Tk, text="Robert", background='#28334A', foreground="#FFFFFF")
authorLable.grid(row=0, columnspan=4)

inputString = tk.StringVar()

websiteName = tk.Label(Tk, text="Enter ip", background='#28334A', foreground="#F65058")
input_entry = tk.Entry(Tk, textvariable=inputString)
websiteName.grid(row=1)
input_entry.grid(row=1, column=1)

outputMsg = tk.Label(Tk, background='#28334A', foreground="#F65058")
outputMsg.grid(row=3, columnspan=4)


button = tk.Button(Tk, text="Check IP", command=lambda : ipFinder(outputMsg, inputString))
button.grid(row=2, columnspan=4)

Tk.title('IP Checker')
Tk.configure(background='#28334A')
Tk.rowconfigure(0, weight=1)
Tk.columnconfigure(0, weight=1)
Tk.rowconfigure(2, weight=1)
Tk.columnconfigure(2, weight=1)
contents = tk.Frame(Tk)
contents.grid(row=1, column=1)
Tk.mainloop()

Any help will be welcome. Thanks in advenced.

Adding Functionality to draw polygons - Polygon dissapears when zoomin in and out.

Hi Tom. I am very happy to see such a well developed tool as this one. I think it would be very useful for a project I am developing. My goal for now is to make something similar to the web tool geojson.io (https://geojson.io)
I need to be able to not only draw markers and path, but also to be able to draw a polygon and export it in a geopackage. I have made a couple of trials around your code. As far as I understand the TkinterMapView object is based on Tkinter.Canvas and on top of it you can draw markers and lines between points (I have seen that for this there are utilities that allow to transform OSM basemap coordinates to canvas coordinates).
I took this idea to modify the code in such a way:

   def set_marker(self, deg_x: float, deg_y: float, text: str = None, **kwargs) -> CanvasPositionMarker:
        marker = CanvasPositionMarker(self, (deg_x, deg_y), text=text, **kwargs)
        marker.draw()
        self.canvas_marker_list.append(marker)
        return marker

    def create_polygon(self, position_list: list) -> CanvasPolygon:
        polygon = CanvasPolygon(self, position_list)
        polygon.draw() 
        return polygon

    def set_path(self, position_list: list, **kwargs) -> CanvasPath:
        path = CanvasPath(self, position_list, **kwargs)
        path.draw()
        self.canvas_path_list.append(path)
        return path`

the create_polygon function I put it between the methods set_marker and set_path of the TkinterMapView class, and as you can see a polygon for this class is created by calling the draw method of this new class I created called CanvasPolygon (I stored it as a new python file called canvas_polygon.py).
I simply copied everything from CanvasPath class from the canvas_path.py file, and tried to figure out how to make it draw me a polygon, passing the stored coordinates (naturally I have restrictions to be able to make polygon based on at least 3 points (markers)).
When I draw on the canvas, it does so, however, when I zoom out or zoom in, this polygon is lost, it appears and disappears continuously. This does not happen with the CanvasPaths and CanvasPositionMarkers, and I wonder if it has to do with being able to add features that allow me to resize the polygon automatically when the zoom changes.

I would be very grateful if you could help me with this issue. Below is the code for the CanvasPolygon Builder. Thank you very much for your excellent work.

Roger

import tkinter
import sys
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .map_widget import TkinterMapView

from .coordinate_convert_functions import deg2num, num2deg


class CanvasPolygon:
    def __init__(self, map_widget: "TkinterMapView", position_list, color="#3E69CB", command=None, name=None):
        self.map_widget = map_widget
        self.position_list = position_list
        self.canvas_polygon_positions = []
        self.connection_list = []
        self.deleted = False

        self.path_color = color
        self.command = command
        self.canvas_line = None
        self.name = name

        self.last_upper_left_tile_pos = None
        self.last_position_list_length = len(self.position_list)

    #def __del__(self):
    #    self.map_widget.canvas.delete(self.canvas_line)
    #    self.canvas_line = None

    #def delete(self):
    #    self.__del__()

    def appear(self):
        self.deleted = False
        self.draw()

    #def add_position(self, deg_x, deg_y, index=-1):
    #    if index == -1:
    #        self.position_list.append((deg_x, deg_y))
    #    else:
    #        self.position_list.insert(index, (deg_x, deg_y))
        # self.draw()

    #def remove_position(self, deg_x, deg_y):
    #    self.position_list.remove((deg_x, deg_y))
    #    self.draw()

    def get_canvas_pos(self, position, widget_tile_width, widget_tile_height):
        tile_position = deg2num(*position, round(self.map_widget.zoom))

        canvas_pos_x = ((tile_position[0] - self.map_widget.upper_left_tile_pos[0]) / widget_tile_width) * self.map_widget.width
        canvas_pos_y = ((tile_position[1] - self.map_widget.upper_left_tile_pos[1]) / widget_tile_height) * self.map_widget.height

        return canvas_pos_x, canvas_pos_y

    #def mouse_enter(self, event=None):
    #    if sys.platform == "darwin":
    #        self.map_widget.canvas.config(cursor="pointinghand")
    #    elif sys.platform.startswith("win"):
    #        self.map_widget.canvas.config(cursor="hand2")
    #    else:
    #        self.map_widget.canvas.config(cursor="hand2")  # not tested what it looks like on Linux!

    #def mouse_leave(self, event=None):
    #    self.map_widget.canvas.config(cursor="arrow")

    #def click(self, event=None):
    #    if self.command is not None:
    #        self.command(self)

    def draw(self, move=False):
        self.last_position_list_length = len(self.position_list)

        widget_tile_width = self.map_widget.lower_right_tile_pos[0] - self.map_widget.upper_left_tile_pos[0]
        widget_tile_height = self.map_widget.lower_right_tile_pos[1] - self.map_widget.upper_left_tile_pos[1]

        if move is True and self.last_upper_left_tile_pos is not None: #and new_line_length is False:
            x_move = ((self.last_upper_left_tile_pos[0] - self.map_widget.upper_left_tile_pos[0]) / widget_tile_width) * self.map_widget.width
            y_move = ((self.last_upper_left_tile_pos[1] - self.map_widget.upper_left_tile_pos[1]) / widget_tile_height) * self.map_widget.height

            for i in range(0, len(self.position_list)* 2, 2):
                self.canvas_polygon_positions[i] += x_move
                self.canvas_polygon_positions[i + 1] += y_move
        else:
            self.canvas_polygon_positions = []
        for position in self.position_list:
            canvas_positions = self.get_canvas_pos(position, widget_tile_width, widget_tile_height)
            #canvas_positions = [item for t in canvas_positions for item in t]
            self.canvas_polygon_positions.append(canvas_positions)
            #self.canvas_line_positions.append(canvas_position[0])
            #self.canvas_line_positions.append(canvas_position[1])

        if not self.deleted:
            if self.canvas_line is None:
                self.map_widget.canvas.delete(self.canvas_line)
                self.canvas_polygon = self.map_widget.canvas.create_polygon(self.canvas_polygon_positions)
                                                                      #width=9, fill=self.path_color,
                                                                      #capstyle=tkinter.ROUND, joinstyle=tkinter.ROUND,
                                                                      #tag="path")

                if self.command is not None:
                    self.map_widget.canvas.tag_bind(self.canvas_line, "<Enter>", self.mouse_enter)
                    self.map_widget.canvas.tag_bind(self.canvas_line, "<Leave>", self.mouse_leave)
                    self.map_widget.canvas.tag_bind(self.canvas_line, "<Button-1>", self.click)
            else:
                self.map_widget.canvas.coords(self.canvas_line, self.canvas_line_positions)
        else:
            self.map_widget.canvas.delete(self.canvas_line)
            self.canvas_line = None

        self.map_widget.manage_z_order()
        self.last_upper_left_tile_pos = self.map_widget.upper_left_tile_pos

Variable within marker placement issue

def pins():
global translation
global rdata
conn = sqlite3.connect('address_book.db')
c = conn.cursor()
c.execute("SELECT * FROM parking")
data1 = c.fetchone()
rdata = (data1[0])
print(rdata)
marker_1 = map_widget.set_marker(rdata, text="52.55, 13.4")

conn.commit()

conn.close()

53.727830, -1.353003

not sure what to do as when I paste that co ordinate or address manually instead of 'rdata' or 'data1[0]' it works fine and loads the map up with the pin in the location I want, but when I put in rdata it seems to be having none of it even if I translate it into an address and put it through. New to Tkinter so Im probs missing something silly, help would be appreciated. cheers

If I use the mouse to move or zoom the map, the next map.set_position centers intermittently in random places

Hi, I'm having a problem with a moving map for aircraft. If I just let it run it works great, but if I move the map display with the mouse or change the zoom with the mouse, the next time this code is run, it intermittently centers in Brazil. Once that happens, it never centers in the correct place again. Can you help?

This code runs on a timer:

            self.map_widget.set_position(self.address_lat, self.address_lon)
            if self.auto_zoom_flag.get() == True:
                # Set zoom level based on aircraft speed 1 is zoomed all the way out, 
                # 19 all the way in
                zoom_level = 19-int(flight_position_data[0].get("speed")/600*19)
                if zoom_level <= 3:
                    zoom_level = 3
                elif zoom_level >= 14: zoom_level = 14
                self.map_widget.set_zoom(zoom_level)
            self.airplaneMarker.set_position(self.aircraft_lat, self.aircraft_lon)

Suggestion - add the ability to append 'attributes' to CanvasPositionMarker and CanvasPath

Hi Tom,

It would be useful to provide the ability to add an attributes object to the marker object so that when it is returned to the marker_click(marker) command, the marker object carries with it this attributes object.

I have called it 'attributes' in the modified constructor for the CanvasPositionMarker object.

class CanvasPositionMarker
    def __init__(self, map_widget: "TkinterMapView", position, text=None, attributes=None, text_color="#652A22", font=None,
                 marker_color_circle="#9B261E", marker_color_outside="#C5542D", command=None, image=None,
                 image_zoom_visibility=(13, float("inf"))):
        self.map_widget = map_widget
        self.position = position
        self.text_color = text_color
        self.marker_color_circle = marker_color_circle
        self.marker_color_outside = marker_color_outside
        self.text = text
        self.image = image
        self.image_hidden = False
        self.image_zoom_visibility = image_zoom_visibility
        self.connection_list = []
        self.deleted = False
        self.command = command

        self.polygon = None
        self.big_circle = None
        self.canvas_text = None
        self.canvas_image = None
        self.attributes = None  #added line here.

        if font is None:
            if sys.platform == "darwin":
                self.font = "Tahoma 13 bold"
            else:
                self.font = "Tahoma 11 bold"
        else:
            self.font = font

I suggest modifying the CanvasPath in the same way would also be extremely useful as it would provide for having this data within the command on path_click event.

I am adding an attributes dictionary to the marker object as per the modified constructor above in my test app and having this data available within the marker_click handler method is pretty valuable.

Just a suggestion!

Thanks again for taking the time to build this awesome little library.

David.

Digitizing /collect coordinates: Draw polygon and get coordinates of vertex into an array

Question

based on https://github.com/TomSchimansky/TkinterMapView/blob/main/examples/map_with_customtkinter.py
i would like to change the function of " Set marker" to "draw polygon" to digitze a polygon and set get coordinates
I 'm a noob in tkinter , tried to implement it via https://stackoverflow.com/questions/42381856/drawing-a-rectangle-using-tkinter
and then use marker.position to get the coords

maybe such an example would be nize: digitzing is a common use case

Load KML into Map as a line/point

I am wanting to preview KML files in a larger python script, as to not separately use google earth. Is there a way to load in a KML file (specifically a line and several points) into the map, and make it viewed? My KMLs are 3d, but are okay to be viewed in 2d.

Addition of multiple right click events

Hi Tom,

Great map control, really enjoying exploring the functionality it has.

When adding multiple events using the tkintermapview.add_right_click_menu_command() method, the user is correctly presented with a list of labelled of options on right click. However, the command invoked is always the command added last (i.e. the bottom most one) and not the command for the selected item.
I'm assuming the intention was to allow for multiple options on right-click?

David

Thank you

I would like to thank the author of this module, Tom Schimansky, for upgrading the module to a newer version, so that it works. Thanks a ton for the modification.

Add information to polygons and display it when clicking on them.

Good Morning Tom. I am building up an application, and part of it is to plot polygons and display some information from their properties (name, survey date etc). I was wondering if this is possible by iterating over a table with the coordinates for every polygon, and then the properties of the polygon could be stored in the .data attribute of the CanvasPolygon object declared in yhe canvas_polygon.py file.

Kind Regards

class CanvasPolygon:
def __init__(self,
             map_widget: "TkinterMapView",
             position_list: list,
             outline_color: str = "#3e97cb",
             fill_color: str = "gray95",
             border_width: int = 5,
             command: Callable = None,
             name: str = None,
             data: any = None):

    self.map_widget = map_widget
    self.position_list = position_list  # list with decimal positions
    self.canvas_polygon_positions = []  # list with canvas coordinates positions
    self.canvas_polygon = None
    self.deleted = False

    self.name = name
    self.data = data

Path line color and line width options

I am looking at changing the line thickness and colors of GPS path, but I cannot see the option.
Ideally I would like to change the line color with other metrics (e.g. speed, altitude...) , using rainbow or parula chart

Is there any methods to control these line options?

Specify line width

It would be nice to be able to add a "width" keyword argument to the CanvasPath class, so then the line width could be set instead of just using a single default value.

Suggestions

Lots of people are flying drones and make their own hi res orthophoto map tiles.
It would be very useful if one could add custom lokal map tiles in your tkintermapview.OfflineLoader and add them to an existing downloaded local database at an higher zoom level, maybe up to 22 or 23.
I have tried to understand your code to do this myself, but i suck at sql.
Tkintermapview is an awsome base for a lot of cool innovative applications and projects.
Thank you!

Different size for marker?

Hi, thank you for creating this lib & customtkinter. Both are my favourite libs and I'm using them for every Python GUI project :)

I started to use this lib recently and I feel that the marker on the map is a bit too big. Is it possible to allow us to configure the size of the marker? Like extra args when creating it.

Thank you :)

Show image instead of marker

Hello,

is it possible to show only the image and hide the orange/red marker at map_view_marker_example? So show the choosen image instead of the marker.
Thanks your answer in advance!

BR,
Aron

Photo Image Error

Hi. I love this project, but I sometimes receive these errors upon closing a window containing this widget. I experimented a bit, but I couldn't find a pattern for when it happens. It looks like it's trying to update the images and when you close the window right while the update happens, you get this error. But I could be wrong. It was never harmful anyways. It's just a mysterious text in the console, but it causes no problems. Still, I would like to find a way to remove/avoid this error. Can you give me some insight into it?

Exception in thread Thread-1 (pre_cache):
Traceback (most recent call last):
  File "/usr/lib/python3.10/threading.py", line 1009, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.10/threading.py", line 946, in run
    self._target(*self._args, **self._kwargs)
  File "/home/milan/.local/lib/python3.10/site-packages/tkintermapview/map_widget.py", line 278, in pre_cache
    self.request_image(zoom, x, self.pre_cache_position[1] + radius, db_cursor=db_cursor)
  File "/home/milan/.local/lib/python3.10/site-packages/tkintermapview/map_widget.py", line 348, in request_image
    image_tk = ImageTk.PhotoImage(image)
  File "/usr/lib/python3.10/site-packages/PIL/ImageTk.py", line 112, in __init__
    self.__photo = tkinter.PhotoImage(**kw)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 4093, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 4026, in __init__
    master = _get_default_root('create image')
  File "/usr/lib/python3.10/tkinter/__init__.py", line 297, in _get_default_root
    raise RuntimeError(f"Too early to {what}: no default root window")
RuntimeError: Too early to create image: no default root window
Exception ignored in: <function PhotoImage.__del__ at 0x7fa69afba5f0>
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/PIL/ImageTk.py", line 118, in __del__
    name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'

Facing Error while using the module

Whenever, the map widget is called using the tkintermapview.TkinterMapView(), the result is just a box with the zoom in an out buttons. I was able to see the map, two days before, but I am unable to see it now. As I said earlier, just a box is only visible. Hope this would be resolved as soon as possible. Thank you
Screenshot (24)
Screenshot (25)

Error initializing with arguments corner_radius and bg_color

Hello. Error when creating a mapview with arguments corner_radius and bg_color.

Version

tkintermapview==1.14

Test script: mapviewtest.py

import tkinter
import tkintermapview

# create tkinter window
root_tk = tkinter.Tk()
root_tk.geometry(f"{640}x{480}")
root_tk.title("map_view_example.py")

# create map widget
map_widget = tkintermapview.TkinterMapView(root_tk, corner_radius=30, bg_color="red")
map_widget.pack(expand=True, fill="both")
root_tk.mainloop()

Error message:

Traceback (most recent call last):
  File "/home/alejandro/Privado/projects/pygubu-project/issues/designer/mapviewtest.py", line 10, in <module>
    map_widget = tkintermapview.TkinterMapView(root_tk, corner_radius=30, bg_color="red")
  File "/home/alejandro/.local/share/fades/23e7c1fd-ebeb-4f2b-bdd9-3e00791ade44/lib/python3.10/site-packages/tkintermapview/map_widget.py", line 153, in __init__
    self.draw_rounded_corners()
  File "/home/alejandro/.local/share/fades/23e7c1fd-ebeb-4f2b-bdd9-3e00791ade44/lib/python3.10/site-packages/tkintermapview/map_widget.py", line 167, in draw_rounded_corners
    style=tkinter.ARC, tag="corner", width=10, outline=self.bg_color, start=-90)
AttributeError: 'TkinterMapView' object has no attribute 'bg_color'

Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.