Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,17 @@ import tkintermapview

Create the standard tkinter window and place a TkinterMapView in the middle of the window.
The first argument must be the widgets master, then you specify the `width`, `height` and `corner_radius`
of the widget.
of the widget. The `user_agent` argument must be a string that identifies your application, as explained
in the [Nominatim Usage Policy](https://operations.osmfoundation.org/policies/nominatim/).
```python
# create tkinter window
root_tk = tkinter.Tk()
root_tk.geometry(f"{800}x{600}")
root_tk.title("map_view_example.py")

# create map widget
map_widget = tkintermapview.TkinterMapView(root_tk, width=800, height=600, corner_radius=0)
map_widget = tkintermapview.TkinterMapView(root_tk, width=800, height=600, corner_radius=0,
user_agent="Example/1.0")
map_widget.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)
```
If you also call `root_tk.mainloop()` at the end, this is already a fully working example to test the map widget.
Expand Down
5 changes: 3 additions & 2 deletions examples/load_offline_tiles.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import tkintermapview
import os
import tkintermapview


# This scripts creates a database with offline tiles.
Expand All @@ -15,7 +15,8 @@
database_path = os.path.join(script_directory, "offline_tiles_nyc.db")

# create OfflineLoader instance
loader = tkintermapview.OfflineLoader(path=database_path)
loader = tkintermapview.OfflineLoader(path=database_path,
user_agent="TkinterMapViewLoadOfflineTiles/{tkintermapview.__version__}")

# save the tiles to the database, an existing database will extended
loader.save_offline_tiles(top_left_position, bottom_right_position, zoom_min, zoom_max)
Expand Down
5 changes: 3 additions & 2 deletions examples/map_view_demo.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import sys
import tkinter
import tkinter.messagebox
from tkintermapview import TkinterMapView
import tkintermapview


class App(tkinter.Tk):

APP_NAME = "map_view_demo.py"
USER_AGENT = f"TkinterMapViewDemo/{tkintermapview.__version__}"
WIDTH = 800
HEIGHT = 750

Expand Down Expand Up @@ -38,7 +39,7 @@ def __init__(self, *args, **kwargs):
self.search_bar_clear = tkinter.Button(master=self, width=8, text="Clear", command=self.clear)
self.search_bar_clear.grid(row=0, column=2, pady=10, padx=10)

self.map_widget = TkinterMapView(width=self.WIDTH, height=600, corner_radius=0)
self.map_widget = tkintermapview.TkinterMapView(width=self.WIDTH, height=600, corner_radius=0, user_agent=self.USER_AGENT)
self.map_widget.grid(row=1, column=0, columnspan=3, sticky="nsew")

self.marker_list_box = tkinter.Listbox(self, height=8)
Expand Down
11 changes: 6 additions & 5 deletions examples/map_view_marker_example.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from PIL import Image, ImageTk
import tkinter
import os
from tkintermapview import TkinterMapView
import tkinter
import tkintermapview
from PIL import Image, ImageTk

# create tkinter window
root_tk = tkinter.Tk()
root_tk.geometry(f"{1000}x{700}")
root_tk.title("map_view_simple_example.py")
root_tk.title("map_view_marker_example.py")

# create map widget
map_widget = TkinterMapView(root_tk, width=1000, height=700, corner_radius=0)
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0,
user_agent=f"TkinterMapViewMarkerExample/{tkintermapview.__version__}")
map_widget.pack(fill="both", expand=True)

# load images in PhotoImage object
Expand Down
5 changes: 3 additions & 2 deletions examples/map_view_marker_icon_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
# create tkinter window
root_tk = tkinter.Tk()
root_tk.geometry(f"{1000}x{700}")
root_tk.title("map_view_simple_example.py")
root_tk.title("map_view_marker_icon_images.py")

# create map widget
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0)
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0,
user_agent=f"TkinterMapViewMarkerIconImages/{tkintermapview.__version__}")
map_widget.pack(fill="both", expand=True)

# load images
Expand Down
3 changes: 2 additions & 1 deletion examples/map_view_polygon_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
root_tk.title("map_view_polygon_example.py")

# create map widget
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0)
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0,
user_agent=f"TkinterMapViewPolygonExample/{tkintermapview.__version__}")
map_widget.pack(fill="both", expand=True)


Expand Down
3 changes: 2 additions & 1 deletion examples/map_view_simple_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
root_tk.title("map_view_simple_example.py")

# create map widget
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0)
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0,
user_agent=f"TkinterMapViewSimpleExample/{tkintermapview.__version__}")
map_widget.pack(fill="both", expand=True)

# set other tile server (standard is OpenStreetMap)
Expand Down
5 changes: 3 additions & 2 deletions examples/map_with_customtkinter.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import customtkinter
from tkintermapview import TkinterMapView
import tkintermapview

customtkinter.set_default_color_theme("blue")


class App(customtkinter.CTk):

APP_NAME = "TkinterMapView with CustomTkinter"
USER_AGENT = f"TkinterMapViewWithCustomTkinter/{tkintermapview.__version__}"
WIDTH = 800
HEIGHT = 500

Expand Down Expand Up @@ -70,7 +71,7 @@ def __init__(self, *args, **kwargs):
self.frame_right.grid_columnconfigure(1, weight=0)
self.frame_right.grid_columnconfigure(2, weight=1)

self.map_widget = TkinterMapView(self.frame_right, corner_radius=0)
self.map_widget = tkintermapview.TkinterMapView(self.frame_right, corner_radius=0, user_agent=self.USER_AGENT)
self.map_widget.grid(row=1, rowspan=1, column=0, columnspan=3, sticky="nswe", padx=(0, 0), pady=(0, 0))

self.entry = customtkinter.CTkEntry(master=self.frame_right,
Expand Down
10 changes: 5 additions & 5 deletions examples/map_with_offline_tiles.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import tkinter
import os
from tkintermapview import TkinterMapView
import tkinter
import tkintermapview

# create tkinter window
root_tk = tkinter.Tk()
root_tk.geometry(f"{1000}x{700}")
root_tk.title("map_view_simple_example.py")
root_tk.title("map_with_offline_tiles.py")

# path for the database to use
script_directory = os.path.dirname(os.path.abspath(__file__))
database_path = os.path.join(script_directory, "offline_tiles_nyc.db")

# create map widget and only use the tiles from the database, not the online server (use_database_only=True)
map_widget = TkinterMapView(root_tk, width=1000, height=700, corner_radius=0, use_database_only=True,
max_zoom=17, database_path=database_path)
map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0,
database_path=database_path, use_database_only=True, max_zoom=17)
map_widget.pack(fill="both", expand=True)

map_widget.set_address("nyc")
Expand Down
10 changes: 7 additions & 3 deletions tkintermapview/map_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def __init__(self, *args,
database_path: str = None,
use_database_only: bool = False,
max_zoom: int = 19,
user_agent: str = None,
**kwargs):
super().__init__(*args, **kwargs)

Expand Down Expand Up @@ -131,6 +132,9 @@ def __init__(self, *args,
self.max_zoom = max_zoom # should be set according to tile server max zoom
self.min_zoom: int = math.ceil(math.log2(math.ceil(self.width / self.tile_size))) # min zoom at which map completely fills widget

# user agent
self.user_agent = user_agent

# pre caching for smoother movements (load tile images into cache at a certain radius around the pre_cache_position)
self.pre_cache_position: Union[Tuple[float, float], None] = None
self.pre_cache_thread = threading.Thread(daemon=True, target=self.pre_cache)
Expand Down Expand Up @@ -330,7 +334,7 @@ def set_address(self, address_string: str, marker: bool = False, text: str = Non
""" Function uses geocode service of OpenStreetMap (Nominatim).
https://geocoder.readthedocs.io/providers/OpenStreetMap.html """

result = geocoder.osm(address_string)
result = geocoder.osm(address_string, headers={"User-Agent": self.user_agent})

if result.ok:

Expand Down Expand Up @@ -492,11 +496,11 @@ def request_image(self, zoom: int, x: int, y: int, db_cursor=None) -> ImageTk.Ph
# try to get the tile from the server
try:
url = self.tile_server.replace("{x}", str(x)).replace("{y}", str(y)).replace("{z}", str(zoom))
image = Image.open(requests.get(url, stream=True, headers={"User-Agent": "TkinterMapView"}).raw)
image = Image.open(requests.get(url, stream=True, headers={"User-Agent": self.user_agent}).raw)

if self.overlay_tile_server is not None:
url = self.overlay_tile_server.replace("{x}", str(x)).replace("{y}", str(y)).replace("{z}", str(zoom))
image_overlay = Image.open(requests.get(url, stream=True, headers={"User-Agent": "TkinterMapView"}).raw)
image_overlay = Image.open(requests.get(url, stream=True, headers={"User-Agent": self.user_agent}).raw)
image = image.convert("RGBA")
image_overlay = image_overlay.convert("RGBA")

Expand Down
6 changes: 4 additions & 2 deletions tkintermapview/offline_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


class OfflineLoader:
def __init__(self, path=None, tile_server=None, max_zoom=19):
def __init__(self, path=None, tile_server=None, max_zoom=19, user_agent=None):
if path is None:
self.db_path = os.path.join(os.path.abspath(os.getcwd()), "offline_tiles.db")
else:
Expand All @@ -24,6 +24,8 @@ def __init__(self, path=None, tile_server=None, max_zoom=19):

self.max_zoom = max_zoom

self.user_agent = user_agent

self.task_queue = []
self.result_queue = []
self.thread_pool = []
Expand Down Expand Up @@ -68,7 +70,7 @@ def save_offline_tiles_thread(self):

try:
url = self.tile_server.replace("{x}", str(x)).replace("{y}", str(y)).replace("{z}", str(zoom))
image_data = requests.get(url, stream=True, headers={"User-Agent": "TkinterMapView"}).content
image_data = requests.get(url, stream=True, headers={"User-Agent": self.user_agent}).content

self.lock.acquire()
self.result_queue.append((zoom, x, y, self.tile_server, image_data))
Expand Down