Seite 1 von 1
Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Sonntag 26. Juli 2020, 00:45
von maGGTech
Wie kann ich ein Button mit Funktion zum Matplotlib hinzufügen?
Zum Verständnis:
Meine bisheriger Code sieht so aus:
Imports:
Code: Alles auswählen
import matplotlib
matplotlib.rcParams["toolbar"] = "toolmanager"
from matplotlib.backend_tools import ToolBase
import mplcursors
Hinzufügen des Tooltips:
Hinzufügen des Buttons:
Code: Alles auswählen
tm = fig.canvas.manager.toolmanager
tm.add_tool("newtool", NewTool)
fig.canvas.manager.toolbar.add_tool(tm.get_tool("newtool"), "toolgroup")
Hinzufügen des Icons:
Code: Alles auswählen
class NewTool(ToolBase):
image = r"D:\path\toggle_tooltip.png"
Code den ich durch den Button umsetzen möchte:
Code: Alles auswählen
# wenn ich auf den Button klicken soll das Tooltip disabled werden
# wenn man nochmal drauf klickt soll es wieder angezeigt werden
# z.B. war meine Idee so:
num = int(0)
num += 1
if (num % 2) == 0:
cursor = mplcursors.cursor(hover=True)
else:
curser = mplcursors.cursor(hover=False)
Ich weiß nicht wo ich die Funktionalität/die Funktion hinzufügen muss bzw. bin mir nicht ganz sicher, ob der unterer Codeschnipsel so funktionierten könnte. Bei Stackoverflow und anderen Webseiten finde ich leider kaum Beispiele dazu.
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Sonntag 26. Juli 2020, 11:06
von Sirius3
Bei Matplotlib fängt man meist mit der Beispielseite an:
https://matplotlib.org/3.3.0/gallery/us ... gskip.html
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Sonntag 26. Juli 2020, 12:53
von maGGTech
Danke für den Link, ich habe den Code mal angepasst:
Neues Tool:
Code: Alles auswählen
class NewTool(ToolToggleBase):
# overwrites the image which is None on default
image = r"D:\path\toggle_tooltip.png"
description = "toggle Tooltip"
default_toggle = True
def __init__(self, *args, cursor, **kwargs):
self.cursor = cursor
super().__init__(*args, **kwargs)
def enable(self, *args):
self.set_tooltip_visibility(False)
def disable(self, *args):
self.set_tooltip_visibility(True)
def set_tooltip_visibility(self, state):
self.cursor = mplcursors.cursor(hover=state)
Hinzufügen des neuen Buttons:
Code: Alles auswählen
tm = fig.canvas.manager.toolmanager
tm.add_tool("newtool", NewTool.__init__(cursor))
Tooltip:
Code: Alles auswählen
cursor = mplcursors.cursor(hover=True)
cursor.connect("add", self.show_annotation)
Fehlermeldung:
File "D:/path/filename.py", line 150, in matplotCanvas
tm.add_tool("newtool", NewTool.__init__(cursor))
TypeError: __init__() missing 1 required keyword-only argument: 'cursor'
=> Der button funktioniert jetzt insoweit, dass es ein zusätzliches curserfenster (das standard fenster) angezeigt wird. Das bedeutet es werden jetzt dann zwei angezeigt. Das Ausblenden funktioniert jedoch noch nicht und ich muss es irgendwie schaffen, dass das bestimmte cursor objekt übergebe, aber ich weiß noch nicht wie das geht. Wisst ihr wie das geht?
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Sonntag 26. Juli 2020, 12:56
von Sirius3
Zeig den gesamten Code. Aus den Fragmente kann man nichts herauslesen.
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Sonntag 26. Juli 2020, 13:14
von maGGTech
ich darf den gesamten Code glaube ich nicht hier reinschreiben, ich kann dir höchstens als private Nachricht was schicken
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Sonntag 26. Juli 2020, 13:22
von Sirius3
Warum solltest Du den Teil, über den Du Hilfe brauchst, nicht reinschreiben dürfen? Es soll ja nur dazu dienen, nachvollziehen zu können, was Du denn wirklich tust. Bei Deinem anderen Thread war die Lösung ja auch in der Zeile, die Du NICHT gezeigt hast, hier ist es wohl so ähnlich, und ich habe keine Lust, immer raten zu müssen. Über Private Nachrichten beantworte ich keine Programmierfragen, weil das Forum soll ja dazu dienen, anderen, die ein ähnliches Problem haben, auch zu helfen.
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Montag 27. Juli 2020, 00:43
von maGGTech
Habe es jetzt hinbekommen (Das der der Button mein Tooltip hinzufügt und beim nochmal klicken wird es ausgeblendet). @Sirius3 der Teil, bei dem ich Hilfe brauche steht doch da schon.
Ich würde jetzt nur noch gern die anderen Funktionen (wie z.B. Zoom und Pan disablen, wenn man auf den Button drückt)
Code sieht jetzt so aus:
Code: Alles auswählen
matplotlib.rcParams["toolbar"] = "toolmanager"
from matplotlib.backend_tools import ToolBase, ToolToggleBase
class Tooltip(ToolToggleBase):
image = r"D:\path\toggle_tooltip.png"
description = "Show Tooltip"
default_toggle = True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def enable(self, *args):
self.set_tooltip_visibility(True)
self.set_tooltip_connection("add")
self.release_rest()
def disable(self, *args):
self.cursor.remove()
def set_tooltip_visibility(self, state):
self.cursor = mplcursors.cursor(hover=state)
def set_tooltip_connection(self, state):
self.cursor.connect(state, self.show_annotation)
def release_rest(self):
self.ToolPan(self._cancel_action())
self.ToolZoom(self._cancel_action())
#Code der nicht klappt
#if 'Pan' in self.wx_ids.keys():
# self.ToolToggleBase(self.wx_ids['Pan'], False)
#if 'Zoom' in self.wx_ids.keys():
# self.ToggleTool(self.wx_ids['Zoom'], False)
Im Moment stürtzt mein IDE ab, sobald ich auf den Button drücke, was an der Funktion release_rest liegt bzw. an den zwei Testzeilen, die noch nicht stimmen. Ich habe mal in die backend_tools.py reingeschaut, kriege es aber grad noch nicht richtig zusammengebastelt.
Beispiel aus backend_tools.py:
Code: Alles auswählen
class ToolPan(ZoomPanBase):
"""Pan axes with left mouse, zoom with right"""
default_keymap = rcParams['keymap.pan']
description = 'Pan axes with left mouse, zoom with right'
image = 'move'
cursor = cursors.MOVE
radio_group = 'default'
def __init__(self, *args):
ZoomPanBase.__init__(self, *args)
self._idDrag = None
def _cancel_action(self):
self._button_pressed = None
self._xypress = []
self.figure.canvas.mpl_disconnect(self._idDrag)
self.toolmanager.messagelock.release(self)
self.toolmanager.get_tool(_views_positions).refresh_locators()
def _press(self, event):
if event.button == 1:
self._button_pressed = 1
elif event.button == 3:
self._button_pressed = 3
else:
self._cancel_action()
return
x, y = event.x, event.y
self._xypress = []
for i, a in enumerate(self.figure.get_axes()):
if (x is not None and y is not None and a.in_axes(event) and
a.get_navigate() and a.can_pan()):
a.start_pan(x, y, event.button)
self._xypress.append((a, i))
self.toolmanager.messagelock(self)
self._idDrag = self.figure.canvas.mpl_connect(
'motion_notify_event', self._mouse_move)
def _release(self, event):
if self._button_pressed is None:
self._cancel_action()
return
self.figure.canvas.mpl_disconnect(self._idDrag)
self.toolmanager.messagelock.release(self)
for a, _ind in self._xypress:
a.end_pan()
if not self._xypress:
self._cancel_action()
return
self.toolmanager.get_tool(_views_positions).push_current()
self._cancel_action()
def _mouse_move(self, event):
for a, _ind in self._xypress:
# safer to use the recorded button at the _press than current
# button: # multiple button can get pressed during motion...
a.drag_pan(self._button_pressed, event.key, event.x, event.y)
self.toolmanager.canvas.draw_idle()
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Montag 27. Juli 2020, 07:15
von Sirius3
@maGGTech: Dein Code funktioniert gar nicht, weil matplotlib benutzt wird, bevor irgendetwas importiert wird. Dann macht der Code einfach gar nichts, außer zwei Klassen zu definieren, wobei die zweite einfach nur irgendein kopiertes Beispiel ist. Benutzt wird das ganze gar nicht.
Wie soll man da helfen können?
Dazu gehört nunmal ein lauffähiges Beispielprogramm, das den Fehler zeigt, inklusive komplettem Traceback.
Ein "steht doch schon da" stößt die Leute, die hier helfen wollen, vor den Kopf.
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Montag 27. Juli 2020, 09:48
von maGGTech
@Sirus3: Ich habe nie behauptet, dass der Code ein funktionierendes Program wäre, sondern das der Code in meinem Programm jetzt funktioniert hat. Ich kann dir mein Program nicht funkionsfähig hier reinschreiben. Selbst wenn ich alles reinschreiben würde, würde der Code dennoch nicht komplett funktionieren, weil du auch noch Messdaten bräuchtest.
Wenn ich in diesen Forum nur Hilfe bekomme, in dem ich mein Programm extra umschreiben muss (was viel Aufwand wäre), um sensible Daten nicht zu veröffentlichen und es für euch laufbar zu machen, dann hilft mir das nicht.
Ich habe auch häufiger im Java Forum Fragen gestellt, und dort konnte mir auch geholfen werden, selbst wenn ich nicht den gesamten Code reingeschrieben habe, den braucht man häufig auch gar nicht.
Dieses "kopierte Beispiel" ist die backend_tools.py von matplotlib, wie ich schon geschrieben habe, und an der man sich langhangeln kann, um den richtigen Code zu finden.
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Montag 27. Juli 2020, 10:16
von __deets__
Es ist absoluter Standard, das man reproduzierbare Beispiele erstellt. Und die haben oft den positiven Nebeneffekt, dass man sein Problem selbst besser versteht und manchmal schon lösen kann.
Aber wenn’s dir hier nicht gefällt, wie du schon mehrfach bemerkt hast, schlage ich vor, du arbeitest mit Java und dem da so viel besseren Forum. Dir gehts damit besser, und hier vermisst so ein anmaßendes genöle auch keiner.
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Montag 27. Juli 2020, 11:03
von sparrow
Also ich könnte schwören, dass ich den Ausdruck "minimal reproducible example" während meiner Java-Zeit gelernt habe.
Re: Button mit Funktion zu Matplotlib Toolbar hinzufügen
Verfasst: Montag 27. Juli 2020, 11:03
von Sirius3
Sensible Daten sollten nicht im Quelltext drin stehen und da man eh für Tests kleine Test-Programme schreibt, fällt so ein Beispiel quasi nebenher ab.
Es ist Deine Entscheidung, ob Du hier Hilfe erhalten willst, oder nicht.