Ausgabe
Ich versuche, ein Programm zu schreiben, das ein X in einem definierten Frame bewegen soll. Zu diesem Zweck sollte eine While-Schleife mit einem KeyPress beginnen und mit einem KeyReleases enden.
Ich habe im Internet nur die Multithreading- oder Multiprocessing-Methoden gefunden, um dies gleichzeitig zu tun. Das Multithreading selbst funktioniert eine gewisse Zeit (immer anders) und dann bekomme ich diverse Fehlermeldungen oder das Programm friert komplett ein.
Oft wird es durch das Signal 11 sigsegv unterbrochen.
Der Code lautet:
# GLOBAL
import faulthandler; faulthandler.enable()
import sys
import time
import requests
from pynput import keyboard
from pynput.keyboard import Key
from qtpy import QtWidgets
from PyQt5 import QtCore
from ui.mainwindow import Ui_MainWindow
# Globale Variablen:
PAN = 250
TILT = 150
SPEED = 1
TIME = 0.01
KEYS = []
THREADS = 0
DIRECTION = []
# HTTP SECTION
payload = {"name": "MK"}
r = requests.get("https://httpbin.org/get", params=payload)
print(r.status_code)
# BUILD GUI
app = QtWidgets.QApplication(sys.argv)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow() # Laden des Style Frames
self.ui.setupUi(self) # Funktion aus Ui_MainWindow ausführen (Fenster zeichnen)
self.ui.tilt.setText(str(TILT))
self.ui.pan.setText(str(PAN))
self.ui.speed.setText(str(SPEED))
## Button Funktionsaufrufe:
self.thread = {}
self.ui.btnUp.clicked.connect(self.moveUP)
self.ui.btnDown.clicked.connect(self.moveDOWN)
self.ui.btnLeft.clicked.connect(self.moveLEFT)
self.ui.btnRight.clicked.connect(self.moveRIGHT)
self.ui.btnCenter.clicked.connect(self.stop_worker)
self.ui.speed.textChanged.connect(self.setSpeed)
# Funktion zum bewegen über die Buttons
def startUp(self):
self.thread[1] = ThreadClass(parent=None, index=1)
self.thread[1].start()
self.thread[1].any_signal.connect(self.my_function)
time.sleep(0.5)
self.thread[1].stop()
print('init thread 1 on startup')
self.thread[2] = ThreadClass(parent=None, index=2)
self.thread[2].start()
time.sleep(0.5)
self.thread[2].stop()
print('init thread 2 on startup')
self.thread[3] = ThreadClass(parent=None, index=3)
self.thread[3].start()
time.sleep(0.5)
self.thread[3].stop()
print('init thread 3 on startup')
self.thread[4] = ThreadClass(parent=None, index=4)
self.thread[4].start()
time.sleep(0.5)
self.thread[4].stop()
print('init thread 4 on startup')
print('... \n \n \n')
print('Status = Ready:')
print('Keys = ', KEYS)
def moveUP(self):
if bool(self.thread[2].isRunning()):
self.stopDOWN()
self.thread[1] = ThreadClass(parent=None, index=1)
self.thread[1].start()
self.thread[1].any_signal.connect(self.my_function)
#self.ui.btnUp.setEnabled(False)
def moveDOWN(self):
# global DIRECTION
# DIRECTION.append('Down')
self.thread[2] = ThreadClass(parent=None, index=2)
self.thread[2].start()
self.thread[2].any_signal.connect(self.my_function)
#self.ui.btnDown.setEnabled(False)
def moveLEFT(self):
# global DIRECTION
# DIRECTION.append('Left')
if bool(self.thread[4].isRunning()):
self.stopRIGHT()
self.thread[3] = ThreadClass(parent=None, index=3)
self.thread[3].start()
self.thread[3].any_signal.connect(self.my_function)
#self.ui.btnLeft.setEnabled(False)
def moveRIGHT(self):
# global DIRECTION
# DIRECTION.append('Right')
self.thread[4] = ThreadClass(parent=None, index=4)
self.thread[4].start()
self.thread[4].any_signal.connect(self.my_function)
#self.ui.btnRight.setEnabled(False)
def stopUP(self):
global KEYS
if bool(self.thread[1].isRunning()):
self.thread[1].stop()
#self.ui.btnUp.setEnabled(True)
KEYS.remove(Key.up)
# DIRECTION.remove('Up')
def stopDOWN(self):
global KEYS
if bool(self.thread[2].isRunning()):
self.thread[2].stop()
#self.ui.btnDown.setEnabled(True)
KEYS.remove(Key.down)
# DIRECTION.remove('Down')
def stopLEFT(self):
global KEYS
if bool(self.thread[3].isRunning()):
self.thread[3].stop()
#self.ui.btnLeft.setEnabled(True)
KEYS.remove(Key.left)
# DIRECTION.remove('Left')
def stopRIGHT(self):
global KEYS
if bool(self.thread[4].isRunning()):
self.thread[4].stop()
#self.ui.btnRight.setEnabled(True)
KEYS.remove(Key.right)
# DIRECTION.remove('Right')
def stop_worker(self):
global DIRECTION
if 'Up' in DIRECTION:
self.thread[1].stop()
#self.ui.btnUp.setEnabled(True)
DIRECTION.remove('Up')
if 'Down' in DIRECTION:
self.thread[2].stop()
#self.ui.btnDown.setEnabled(True)
DIRECTION.remove('Down')
if 'Left' in DIRECTION:
self.thread[3].stop()
#self.ui.btnLeft.setEnabled(True)
if 'Right' in DIRECTION:
self.thread[4].stop()
#self.ui.btnRight.setEnabled(True)
DIRECTION.remove('Right')
def my_function(self, counter):
global KEYS
cnt = counter
index = self.sender().index
if index == 1:
print(cnt)
def setSpeed(self):
global SPEED
if self.ui.speed.text():
SPEED = int(self.ui.speed.text())
# Funktion zum bewegen über die Tasten
def on_press(key):
global KEYS
if key not in KEYS:
if key == Key.up:
MainWindow.moveUP(window)
KEYS.append(key)
print('added: ' + str(key))
if key == Key.down:
if Key.up in KEYS:
pass
else:
MainWindow.moveDOWN(window)
KEYS.append(key)
print('added: ' + str(key))
if key == Key.left:
MainWindow.moveLEFT(window)
KEYS.append(key)
print('added: ' + str(key))
if key == Key.right:
if Key.left in KEYS:
pass
else:
MainWindow.moveRIGHT(window)
KEYS.append(key)
print('added: ' + str(key))
def on_release(key):
global KEYS
if key in KEYS:
if key == Key.up and Key.up in KEYS:
MainWindow.stopUP(window)
if key == Key.down and Key.down in KEYS:
MainWindow.stopDOWN(window)
if key == Key.left and Key.left in KEYS:
MainWindow.stopLEFT(window)
if key == Key.right and Key.right in KEYS:
MainWindow.stopRIGHT(window)
print(KEYS)
if key == Key.esc:
MainWindow.stop_worker(window)
# Collect events until released
listener = keyboard.Listener(
on_press=on_press,
on_release=on_release)
listener.start()
class ThreadClass(QtCore.QThread):
any_signal = QtCore.pyqtSignal(int)
def __init__(self, parent=None, index=0):
super(ThreadClass, self).__init__(parent)
self.index = index
self.is_running = True
def run(self):
global TILT
global PAN
global TIME
global SPEED
print('Starting thread...', self.index)
i = self.index
while (True):
if i == 1:
if TILT <= 0:
pass
else:
TILT -= SPEED
window.ui.tilt.setText(str(TILT))
window.ui.target.setGeometry(PAN, TILT, 10, 16)
# print("T", TILT)
time.sleep(TIME)
if i == 2:
if TILT >= 301:
pass
else:
TILT += SPEED
window.ui.tilt.setText(str(TILT))
window.ui.target.setGeometry(PAN, TILT, 10, 16)
# print('T', TILT)
time.sleep(TIME)
if i == 3:
if PAN <= 0:
pass
else:
PAN -= SPEED
window.ui.pan.setText(str(PAN))
window.ui.target.setGeometry(PAN, TILT, 10, 16)
# print("P", PAN)
time.sleep(TIME)
if i == 4:
if PAN >= 500:
pass
else:
PAN += SPEED
window.ui.pan.setText(str(PAN))
window.ui.target.setGeometry(PAN, TILT, 10, 16)
# print("P", PAN)
time.sleep(TIME)
def stop(self):
self.is_running = False
print('Stopping thread...', self.index)
self.terminate()
window = MainWindow()
window.show()
window.startUp()
sys.exit(app.exec_())
Ich programmiere derzeit in PyCharm auf einem MacBook mit OS 12.6.
Lösung
Ich habe nicht Ihren gesamten Code gelesen, aber Sie versuchen, von einem Thread aus auf die GUI zuzugreifen, der nicht der Hauptthread ist. Dies ist illegal und wird früher oder später zu Abstürzen führen.
Beantwortet von – Jens
Antwort geprüft von – Dawn Plyler (FixError Volunteer)