Last active
February 27, 2025 17:33
-
-
Save derrickturk/aaa6c52d96b1719ea22ea25c644434a8 to your computer and use it in GitHub Desktop.
race condition in matplotlib.widgets.TextBox with QTAgg back end and toolmanager in use
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import matplotlib | |
import matplotlib.pyplot as plt | |
from matplotlib.widgets import TextBox | |
matplotlib.use('QTAgg') | |
matplotlib.rcParams['toolbar'] = 'toolmanager' | |
class SnitchBox(TextBox): | |
def __init__(self, name, *rest) -> None: | |
self.name = name | |
super().__init__(*rest) | |
def begin_typing(self) -> None: | |
print(f'{self.name} BEGIN TYPING') | |
super().begin_typing() | |
def stop_typing(self) -> None: | |
print(f'{self.name} STOP TYPING') | |
super().stop_typing() | |
def main(argv: list[str]) -> int: | |
fig, ax = plt.subplots() | |
plt.subplots_adjust(bottom=0.2) | |
xs = list(range(25)) | |
ys = [x ** 3 for x in xs] | |
plt.plot(xs, ys) | |
tb1 = SnitchBox('TB1', plt.axes([0.15, 0.05, 0.3, 0.075]), 'TB1') | |
tb2 = SnitchBox('TB2', plt.axes([0.55, 0.05, 0.3, 0.075]), 'TB2') | |
plt.show() | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main(sys.argv)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import matplotlib | |
import matplotlib.pyplot as plt | |
from matplotlib.widgets import TextBox | |
matplotlib.use('QTAgg') | |
matplotlib.rcParams['toolbar'] = 'toolmanager' | |
def main(argv: list[str]) -> int: | |
fig, ax = plt.subplots() | |
plt.subplots_adjust(bottom=0.2) | |
xs = list(range(25)) | |
ys = [x ** 3 for x in xs] | |
plt.plot(xs, ys) | |
tb1 = TextBox(plt.axes([0.15, 0.05, 0.3, 0.075]), 'TB1') | |
tb2 = TextBox(plt.axes([0.55, 0.05, 0.3, 0.075]), 'TB2') | |
plt.show() | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main(sys.argv)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import matplotlib | |
import matplotlib.pyplot as plt | |
from matplotlib.axes import Axes | |
from matplotlib.widgets import TextBox | |
matplotlib.use('QTAgg') | |
matplotlib.rcParams['toolbar'] = 'toolmanager' | |
class SnitchBox(TextBox): | |
def __init__(self, name, *rest) -> None: | |
self.name = name | |
super().__init__(*rest) | |
def begin_typing(self) -> None: | |
print(f'{self.name} BEGIN TYPING') | |
super().begin_typing() | |
def stop_typing(self) -> None: | |
print(f'{self.name} STOP TYPING') | |
super().stop_typing() | |
def unfuck_keypresslock(axes: Axes) -> None: | |
fig = axes.get_figure(root=True) | |
if fig is None: | |
return | |
toolmanager = getattr(fig.canvas.manager, "toolmanager", None) | |
if toolmanager is None: | |
return | |
class UnfuckedLock: | |
def __init__(self) -> None: | |
self._owners: set[int] = set() | |
def __call__(self, owner: object) -> None: | |
self._owners.add(id(owner)) | |
def release(self, owner: object) -> None: | |
self._owners.remove(id(owner)) | |
def locked(self) -> bool: | |
return bool(self._owners) | |
toolmanager.keypresslock = UnfuckedLock() | |
def main(argv: list[str]) -> int: | |
fig, ax = plt.subplots() | |
plt.subplots_adjust(bottom=0.2) | |
xs = list(range(25)) | |
ys = [x ** 3 for x in xs] | |
plt.plot(xs, ys) | |
unfuck_keypresslock(ax) | |
tb1 = SnitchBox('TB1', plt.axes((0.15, 0.05, 0.3, 0.075)), 'TB1') | |
tb2 = SnitchBox('TB2', plt.axes((0.55, 0.05, 0.3, 0.075)), 'TB2') | |
plt.show() | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main(sys.argv)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment