I'm trying to write a program that should move an X in a defined frame. For this purpose, a while loop should start with a KeyPress and stop with a KeyReleases.
I only found the multithreading or multiprocessing methods on the Internet to do that simultaneously. The multithreading itself works for a certain amount of time (always differently) and then I get various error messages or the program freezes completely.
Often it is interrupted by signal 11 sigsegv.
The code is:
# 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_())
I am currently programming in PyCharm on a MacBook with OS 12.6.
CodePudding user response:
I didn't read all your code, but you are trying to access the GUI from a thread which is not the main thread. This is illegal and will result in crashes sooner or later.