Tkintermapview attribute state

Hello

As per a previous post, I am working on a game project (personal) using tkinter widgets along with tkintermapview. In general, things are working pretty good but I do have a question regarding map markers.
In the game, I create a lot of map markers referencing airports and paths between airports representing jobs. Because there are different types of jobs, I hide paths and airports according to a selection button.
tkintermapview did not have a built-in attribute for setting the state so I modified the module to add the state attribute and methods to show or hide the markers and paths as needed.

Surprisingly, it works well with the exception of scrolling the map. If I generate markers with a state of normal, and then later change the state to hidden, the markers disappear as desired. However, if I scroll the map or zoom the map, any marker whose position goes outside the bounds of the frame revert to a normal state when they re-enter the frame. If they are created in a hidden state, and then change the state to normal, they will revert to hidden when scrolled out of the frame.

Anyone know of a way to keep the marker state locked as set. The path objects do not have this behavior.

I can sort of compensate using a zoom event to reset the state to my chosen state but have not figured out a event that would be triggered on scroll.

Any thoughts appreciated.

Hi,

apparently someone has experienced a similar issue with tkinter where variables were being reset.
Their fix was declaring certain variable as global.

Per a post:

" …code that declares the button and handles the click is relevant to the question and should be included."

Maybe, relevant variables need to be global for persistence. Begin by testing with one marker in your script.

Thanks for the reply. Unfortunately, I don’t believe this is the issue.

I am not technically declaring a variable as in Weight = 10, but instead am calling a module method that creates markers.

fm = map.set_marker(52.57, 13.4, text="Berlin", icon='some image', state='normal', command=0)

and then add the marker to a list

markerList.append(fm)

this way you can loop through the list and call the show or hide method in the module.

for fm in markerList:
fm.hide()
or fm.show()
or fm.delete()

these methods all takes place in the imported module tkintermapview.

It is interesting that you have set command = 0. The command value sets the function to call (hence ‘callback’ function) when an event has occurred. If you are not using it, can you try NOT setting it to a 0 value.

Since you did not provide the code, can you start by not populating the command value, as in:

fm = map.set_marker(52.57, 13.4, text="Berlin", icon='some image', state='normal')

By the way, how did you set up or implement your application? Are you using classes or did you use a functional approach?

Can you also use a different looping variable. Instead of fm, use marker, for example.

for marker in markerList:
    marker.hide()
    marker.show()
    marker.delete()

The command attribute is part of the marker object, it can be left out of the method call or used to call a method in my code. While building I do a lot of trial and error testing. Setting command=0 is a placeholder, typically I am calling a method to do something if you click on the marker. In this case, fm is a Fleet Marker that I currently am not doing any action if you click on the icon. It’s a copy of the same marker code I use to make airport markers that I was using a command function call. I am now also using a mouse hover event on the path to create a popup window with job information.

I changed the code to use marker but it made no difference. fm/marker is just a reference to the current item in the list I created, it represents one map marker object.

mostly I am using classes (Still playing with color scheme)

When asking here about the behavior of a third party module, I helps to say so.

You might need to direct the issue to the author.

Generally it is not a good idea to use looping variable names with existing variable names. It is best to use distinct names. Here is an example that highlights this point.

tempVar = 55     # Independent variable

values = [1,2,3,4,5,6]

for tempVar in values:   # Notice the looping variable name used here
    print(tempVar, end=' ')

print('The value of tempVar is: ', tempVar)  # What value will it have? 55 or 6?

# Furthermore, what if you intended to use that variable somewhere in a critical calculation:
result = 10 * tempVar
print('The result value is: ', result)

Notice the result? If you’re using a similar coding approach in other areas, make the necessary corrections.

If you’re using classes, then variables should have persistence. Maybe it is an issue with the module? Review your code more carefully to verify if it is an issue with the module and not your code.

[Terry Jan Reedy]

Sorry for any confusion. I thought by referencing the module name, it would be recognized. I was not thinking specifically about it being a third party module.

Paul:

I understand what you are saying regarding variable names. In this instance, I am still leaning to something in the tkintermapview module. I did look on github for a way to contact the author but did not see any links to leave a message. I’ll give it a second look.

I created a test code creating an instance of the map with one marker. I then hide the marker via a button. the marker is hidden are desired. I then scroll the map until that portion of the map is outside the viewing frame and back. The marker reappears.

As the state attribute was added by me to the module, I have to assume the internal code doesn’t handle the state change in some part of the code that handles the draw functions.

Regarding variable names, when I created the test map, I called my map “map”. Neither of my Hide or Show method was working. I scratched my head for a good bit until it occurred to me that maybe my object name was causing the problem. Renamed the map object to something else and my methods started working…Live and Learn

Yup, this will do it. :wink:

Hears a related link:

I believe I have solved my problem.

When a map marker is created, the module creates the marker object. It then calls a draw method that draws the marker object on the canvas. The marker object is then placed in a list (canvas_marker_list).

Inside the canvas_position_marker class (This is the object created for each marker) is where I added the state attribute along with the show and hide methods. It appears that calling the show and hide methods in the canvas_position_marker class was changing the canvas object as desired (what you actually see on the map) but once the marker went out of frame and came back, the canvas draw method was redrawing the object from the main class canvas_marker_list.

I modified my test map to alter the canvas_marker_list object state as well as altering the object in the canvas_position_marker class.

code in the main class : map_widget

def setMarkerState(self, inText, inState):
       
        for mkr in self.canvas_marker_list:
            if mkr.text == inText:
                mkr.state = inState
                CanvasPositionMarker.setState(mkr, inState)

code in the marker class: canvas_position_marker

def setState(self, inState):
        self.map_widget.canvas.itemconfigure(self.canvas_icon, state=inState)
        self.map_widget.canvas.itemconfigure(self.canvas_text, state=inState)

Now when I scroll the map portion that has the marker out and back into the frame, the marker object remains in the state last set.

1 Like