fixed app terminationg issues by Ctrl-C and window closing in both backends
This commit is contained in:
@ -22,6 +22,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
@ -1732,11 +1733,42 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
ani = FuncAnimation(fig, update, interval=interval_ms, blit=False)
|
ani = FuncAnimation(fig, update, interval=interval_ms, blit=False)
|
||||||
|
cleanup_done = False
|
||||||
|
|
||||||
plt.show()
|
def _cleanup():
|
||||||
# Нормальное завершение при закрытии окна
|
nonlocal cleanup_done
|
||||||
stop_event.set()
|
if cleanup_done:
|
||||||
reader.join(timeout=1.0)
|
return
|
||||||
|
cleanup_done = True
|
||||||
|
stop_event.set()
|
||||||
|
reader.join(timeout=1.0)
|
||||||
|
|
||||||
|
def _handle_sigint(_signum, _frame):
|
||||||
|
_cleanup()
|
||||||
|
try:
|
||||||
|
plt.close(fig)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
prev_sigint = signal.getsignal(signal.SIGINT)
|
||||||
|
try:
|
||||||
|
fig.canvas.mpl_connect("close_event", lambda _evt: _cleanup())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGINT, _handle_sigint)
|
||||||
|
except Exception:
|
||||||
|
prev_sigint = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
plt.show()
|
||||||
|
finally:
|
||||||
|
_cleanup()
|
||||||
|
if prev_sigint is not None:
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGINT, prev_sigint)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def run_pyqtgraph(args):
|
def run_pyqtgraph(args):
|
||||||
@ -1787,6 +1819,10 @@ def run_pyqtgraph(args):
|
|||||||
app.setApplicationName(str(args.title))
|
app.setApplicationName(str(args.title))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
app.setQuitOnLastWindowClosed(True)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
win = pg.GraphicsLayoutWidget(show=True, title=args.title)
|
win = pg.GraphicsLayoutWidget(show=True, title=args.title)
|
||||||
win.resize(1200, 600)
|
win.resize(1200, 600)
|
||||||
|
|
||||||
@ -2279,8 +2315,26 @@ def run_pyqtgraph(args):
|
|||||||
timer = pg.QtCore.QTimer()
|
timer = pg.QtCore.QTimer()
|
||||||
timer.timeout.connect(update)
|
timer.timeout.connect(update)
|
||||||
timer.start(interval_ms)
|
timer.start(interval_ms)
|
||||||
|
sigint_requested = threading.Event()
|
||||||
|
sigint_timer = pg.QtCore.QTimer()
|
||||||
|
sigint_timer.setInterval(50)
|
||||||
|
sigint_timer.timeout.connect(lambda: app.quit() if sigint_requested.is_set() else None)
|
||||||
|
sigint_timer.start()
|
||||||
|
cleanup_done = False
|
||||||
|
|
||||||
def on_quit():
|
def on_quit():
|
||||||
|
nonlocal cleanup_done
|
||||||
|
if cleanup_done:
|
||||||
|
return
|
||||||
|
cleanup_done = True
|
||||||
|
try:
|
||||||
|
timer.stop()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
sigint_timer.stop()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
stop_event.set()
|
stop_event.set()
|
||||||
reader.join(timeout=1.0)
|
reader.join(timeout=1.0)
|
||||||
if control_window is not None:
|
if control_window is not None:
|
||||||
@ -2289,12 +2343,50 @@ def run_pyqtgraph(args):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _handle_sigint(_signum, _frame):
|
||||||
|
sigint_requested.set()
|
||||||
|
|
||||||
|
prev_sigint = signal.getsignal(signal.SIGINT)
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGINT, _handle_sigint)
|
||||||
|
except Exception:
|
||||||
|
prev_sigint = None
|
||||||
|
|
||||||
|
orig_close_event = getattr(win, "closeEvent", None)
|
||||||
|
|
||||||
|
def _close_event(event):
|
||||||
|
try:
|
||||||
|
if callable(orig_close_event):
|
||||||
|
orig_close_event(event)
|
||||||
|
else:
|
||||||
|
event.accept()
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
event.accept()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
app.quit()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
win.closeEvent = _close_event # type: ignore[method-assign]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
app.aboutToQuit.connect(on_quit)
|
app.aboutToQuit.connect(on_quit)
|
||||||
win.show()
|
win.show()
|
||||||
exec_fn = getattr(app, "exec_", None) or getattr(app, "exec", None)
|
exec_fn = getattr(app, "exec_", None) or getattr(app, "exec", None)
|
||||||
exec_fn()
|
try:
|
||||||
# На случай если aboutToQuit не сработал
|
exec_fn()
|
||||||
on_quit()
|
finally:
|
||||||
|
on_quit()
|
||||||
|
if prev_sigint is not None:
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGINT, prev_sigint)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user