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 io
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
@ -1732,11 +1733,42 @@ def main():
|
||||
)
|
||||
|
||||
ani = FuncAnimation(fig, update, interval=interval_ms, blit=False)
|
||||
cleanup_done = False
|
||||
|
||||
plt.show()
|
||||
# Нормальное завершение при закрытии окна
|
||||
stop_event.set()
|
||||
reader.join(timeout=1.0)
|
||||
def _cleanup():
|
||||
nonlocal cleanup_done
|
||||
if cleanup_done:
|
||||
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):
|
||||
@ -1787,6 +1819,10 @@ def run_pyqtgraph(args):
|
||||
app.setApplicationName(str(args.title))
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
app.setQuitOnLastWindowClosed(True)
|
||||
except Exception:
|
||||
pass
|
||||
win = pg.GraphicsLayoutWidget(show=True, title=args.title)
|
||||
win.resize(1200, 600)
|
||||
|
||||
@ -2279,8 +2315,26 @@ def run_pyqtgraph(args):
|
||||
timer = pg.QtCore.QTimer()
|
||||
timer.timeout.connect(update)
|
||||
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():
|
||||
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()
|
||||
reader.join(timeout=1.0)
|
||||
if control_window is not None:
|
||||
@ -2289,12 +2343,50 @@ def run_pyqtgraph(args):
|
||||
except Exception:
|
||||
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)
|
||||
win.show()
|
||||
exec_fn = getattr(app, "exec_", None) or getattr(app, "exec", None)
|
||||
exec_fn()
|
||||
# На случай если aboutToQuit не сработал
|
||||
on_quit()
|
||||
try:
|
||||
exec_fn()
|
||||
finally:
|
||||
on_quit()
|
||||
if prev_sigint is not None:
|
||||
try:
|
||||
signal.signal(signal.SIGINT, prev_sigint)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user