ständig aktualisirender graph in qt

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

hallo deets ich habe deine Narichten erst nach dem posten meiner angezeigt bekommen
Da der Kamera_Dreher nirgendwo instatiiert wird, ist es aber aufgerufen, ist es wohl doch nicht der Code, der wirklich laeuft. Also doch wieder: bitte den *gesamten* Quellcode zeigen. Nicht irgendwas kuratiertes, von dem du denkst, dass es ausreichend ist.
was meinst du damit ich kann dem ehrlichgesagt nicht folgen.

Code: Alles auswählen

self.classe = Kamera_Dreher(self.queue4 , self.kamera_winkel , self.kamera_grad , richtung , self.queue5, self.signals)
hier wierd die klasse doch instanziert Danach ist das starten des Threads Falsch das müsste self.threadpool.start(self.classe) sein.
dass ist mir nicht aufgefallen , weil ich die funktion in der Kamera_dreher instanziert wird nicht aufgerufen habe
dass das nicht der ganze code war stimmt das war nur die klasse in der in der der fehler lag hier wird diese instanziert:

Code: Alles auswählen

from mainwindow import *
from fernsteuerung import Fernsteuerung
from queue import Queue ,LifoQueue
from PyQt6.QtWidgets import *
from graph import *
from connect_robot import ConnectRobot

main_fern = Queue()
fern_status = Queue()
robo = Queue()
dreh_queue = LifoQueue()
dreh_queue2 = LifoQueue()
graph_queue = LifoQueue()
e_queue = LifoQueue()

threadpool = QThreadPool()

app = QApplication([])

gr = Graph(graph_queue)

window = MainWindow(dreh_queue , robo , dreh_queue2 , main_fern , gr.signals)
fernsteurung=Fernsteuerung(robo , main_fern , gr.signals)
robot = ConnectRobot(robo , graph_queue)

threadpool.start(fernsteurung)
threadpool.start(gr)
robot.start()

app.exec()
LG sauterle
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sauterle: Ich glaube __deets__ hatte es schon mal erwähnt: Ohne den Code zu sehen kann man da nicht viel zu sagen. Entweder läuft `Fernsteuerung.run()` nicht in einem Thread oder `reader()` wird auch vom GUI-Thread aus aufgerufen. Was nicht ganz unwahrscheinlich ist, da diese Methode ja aus irgendeinem Grund als Slot markiert ist, was man nicht machen müsste wenn das nicht von Qt-C++-Code aus aufgerufen werden würde. Diese Aufrufe kennen wird aber nicht.

Grundsätzlich sollte der Code auch mal gründlich aufgeräumt werden. Nackte ``except:``\s müssen da alle raus und man bindet auch nicht einfach *alles* an das Objekt, sondern nur die Werte, die den Zustand ausmachen. Alle Attribute müssen zudem nach Ablauf der `__init__()` existieren und nicht später erst in Methodenaufrufen dazu kommen.

Threadpool wurde ja schon erwähnt: Nicht benutzen solange man nicht *wirklich* einen Threadpool benutzen will. Ein Kriterium ist: Muss der Thread sofort starten, oder ist es okay, wenn der mehr oder weniger beliebig lange verzögert wird. Denn genau das kann bei einem Threadpool ja passieren.

Die Queues sollten sinnvoll benannt werden und natürlich rausfliegen wo sie nicht gebraucht werden, weil man das in Qt über Signal/Slot lösen würde.

Bei den Namen muss sich was ändern. Zum einen natürlich die ganzen nichtssagenden und/oder nummerierten Namen, aber dann auch Methodennamen die keine Tätigkeit beschreiben. Umgekehrt gibt es Attribute deren Namen Tätigkeiten beschreiben, die aber weder Methoden noch Funktionen (oder allgemein aufrufbar) sind.

`broken` ist komisch. Nach dem man drei Fehler gezählt hat wird `broken` False‽ Das ist verwirrend.

Wo und wann wird denn `restart()` aufgerufen? Und ist dann sicher, dass da nicht mehrere `run()`-Aufrufe in mehreren Threads gleichzeitig laufen? Das sieht gefährlich bis kaputt aus.

Sternchen-Importe sind Böse™. Nicht machen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

danke für eure bewertungen
fernsteuerung.reader wird nur von fernsteuerung.run aufgerufen. warum sollte fernsteurung.run nicht in einem Thread laufen es wird doch als ein solcher gestarted. welche stücke des codes fehlen euch den?
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie waere es einfach mal mit dem gesamten Code? Statt Puzzleteile zu liefern.

Und ich hab's ja schonmal gesagt: nur weil ein slot auf einem Objekt definiert ist, das irgendwie von QRunnable ableitet, oder ein Thread ist, heisst das NICHT, dass dessen Methoden (und das sind slots) auch automagisch im Thread aufgerufen werden. Das ist ein weitverbeiteter Irrglaube.
Benutzeravatar
grubenfox
User
Beiträge: 432
Registriert: Freitag 2. Dezember 2022, 15:49

sauterle hat geschrieben: Mittwoch 30. August 2023, 13:04
kommentiere ich aber folgende stücke aus und setze ein bsp. print(876) darunter dann tritt er nicht auf:

Code: Alles auswählen

if self.write != None:
            self.port.write(self.write)
            self.write = None
und

Code: Alles auswählen

self.read=self.port.readline()
zu

Code: Alles auswählen

self.read=b""#self.port.readline()
mache ich das print wieder weg tritt der fehler wieder auf
also ist das schreiben/lesen auf `self.port` das Problem bzw. der Auslöser der Probleme oder was?
Vom Code oben diese beiden Zeilen

Code: Alles auswählen

self.port.write(self.write)
self.port.readline()


Was auch immer `self.port` sein mag.

Und bei der Doku vom Modul queue habe ich noch dies gefunden:
Internally, those three types of queues use locks to temporarily block competing threads; however, they are not designed to handle reentrancy within a thread.
Da hat __blackjack__ ja schon geschrieben dass die Queues im Zweifel eher rausfliegen sollten.
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

nocheinmal die Klasse fernsteuerung

Code: Alles auswählen

import serial
from worker import *
import time
from PyQt6.QtCore import *



class Fernsteuerung(QThread):
    def __init__(self, q1 , q2 ,sig ,*args,**kwargs):
        super().__init__()
        self.signals = sig
        self.fernqueue = q2
        self.queue = q1
        self.z=0
        self.threadpool = QThreadPool()
        self.write = b""
        self.broken = True
        self.fehler = 0
        self.port_finder()

    def port_finder(self):
        self.port_try=None
        try:
            self.port = serial.Serial('/dev/ttyUSB0')
        except:
            self.port_try = False
        else:
            self.port_try = True

        if self.port_try == False:
            try:
                self.port = serial.Serial("/dev/ttyUSB1")
            except:
                print("Fehler bei Ferbindungsaufbau zu fernbedienung")

    @pyqtSlot()
    def reader(self):
        self.read=self.port.readline()
        if self.read != b"":
            self.erst = self.read[0:2]
            try:
                self.wert = int(self.read[2:])
            except:
                self.wert = None

            if self.erst == b"j1":
                self.wert = self.lehr_bereich(self.wert)
                self.signals.j1.emit(self.wert)

            if self.erst == b"j2":
                self.wert += 3
                self.wert = self.lehr_bereich(self.wert)
                self.signals.j2.emit(self.wert)

            if self.erst == b"kr":
                self.signals.kamera.emit(self.wert)

            if self.erst == b"kl":
                self.signals.kamera.emit(self.wert)

            if self.erst == b"mk":
                if self.wert == 1:
                    self.signals.rueck.emit()

                if self.wert == 2:
                    self.signals.aus.emit()

                if self.wert == 3:
                    self.signals.vor.emit()

            if self.erst == b"wd":
                self.wert = self.lehrbereich(self.wert)
                self.signals.wd.emit(self.wert)

            if self.erst == b"k1":
                self.signals.k1.emit()

            if self.erst == b"k2":
                self.signals.kk2.emit()


            if self.erst == b"k3":
                self.signals.k3.emit()

        #if self.write != None:
         #   self.port.write(self.write)
          #  self.write = None

    def worker(self):
        warker = Worker(self.write)
        self.threadpool.start(warker)

    def run(self):
        while True:
            if self.broken:
                try:
                    self.write = self.fernqueue.get(block=False)
                except:
                    pass

                try:
                    self.reader()
                except:
                    self.port_finder()
                    print("port mistake")
                    time.sleep(1)
                    self.fehler += 1
                    if self.fehler == 3:
                        self.broken = False
                else:
                    self.fehler = 0

    def restart(self):
        self.broken=True
        self.fehler=0
        self.run()


    def lehr_bereich(self , wert):
        self.bereich = 2
        self.funktions_wert = wert
        if (self.funktions_wert >=50 - self.bereich) and (self.funktions_wert <= 50 + self.bereich):
            self.funktions_wert = 50
        if self.funktions_wert > self.bereich + 50:
            self.funktions_wert -= self.bereich
        if self.funktions_wert <50 -  self.bereich:
            self.funktions_wert += self.bereich
        return self.funktions_wert
self.port ist eine instanz der Klasse Serial von pyserial. in der funktion port_finder wird diese erzeugt(port finder probiert beide infragekommenden usb ports aus).Angehängt an den computer ist eine fersteurung mit knöpfen/Joystics die über uart der Klasse Fernsteurung meldet wenn ein knopf gedrückt wurde. in der funkrtion reader wird self.port ausgelesen und es werden entsprechende Signale an die Klasse mainwindow(auch schon gepostet)geschickt
LG und danke sauterle
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`self.port.readline()` und `self.port.write()` sind blockierende Aufrufe. Wenn das zum blockieren der GUI führt, dann wird das anscheinend nicht in einem eigenen Thread ausgeführt, sondern im GUI-Thread.

Edit: Oder irgendeiner der Slots macht was, was länger dauert und im GUI-Thread ausgeführt wird. Da müsste man aber wieder wissen was da überall gemacht wird. Ich weiss nicht ob das schon mal jemand gesagt hat — __deets__ vielleicht — das es nicht so zielführend ist immer nur Teilstücke zu zeigen, wenn gar nicht klar ist *wo* das Problem steckt.

Und solange da einfach immer *alles* an die Objekte gebunden wird, habe zumindest ich keine grosse Lust das nachzuverfolgen. Das ist ja letztlich als wenn *jede* Variable global definiert wäre.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

ich baue mal ein sleep ein und kuke ob die gui einfriert
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

die gui friert wenn man in die schleife ein sleep setzt nicht ein wenn man kein sleep setzt schon (auch bei 0.0001s oder 2s usw.)

Code: Alles auswählen

    def run(self):
        while True:
            sleep(0.0001)
            if self.broken:
                try:
                    self.write = self.fernqueue.get(block=False)
                except:
                    pass

                try:
                    self.reader()
                except:
                    self.port_finder()
                    print("port mistake")
                    time.sleep(1)
                    self.fehler += 1
                    if self.fehler == 3:
                        self.broken = False
                else:
                    self.fehler = 0
es ist mir ein rätsel: mache ich das sleep weg friert sie wieder ein
LG sauterle
Zuletzt geändert von sauterle am Mittwoch 30. August 2023, 16:07, insgesamt 1-mal geändert.
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

das ist das altbekannte run aus der klasse fernsteuerung
zu euren wüschen den ganzen code zu sehen ich habe eine main datei in der alle klassen instanziert und als thread gestarted werden die klassen habe ich der übersichtigkeit halber in eigene files gepackt.

main.py:

Code: Alles auswählen

from mainwindow import *
from fernsteuerung import Fernsteuerung
from queue import Queue ,LifoQueue
from PyQt6.QtWidgets import *
from graph import *
from connect_robot import ConnectRobot

main_fern = Queue()
fern_status = Queue()
robo = Queue()
dreh_queue = LifoQueue()
dreh_queue2 = LifoQueue()
graph_queue = LifoQueue()
e_queue = LifoQueue()

threadpool = QThreadPool()

app = QApplication([])

gr = Graph(graph_queue)

window = MainWindow(dreh_queue , robo , dreh_queue2 , main_fern , gr.signals)
fernsteuerung=Fernsteuerung(robo , main_fern , gr.signals)
robot = ConnectRobot(robo , graph_queue)

fernsteuerung.start()
gr.start()
robot.start()

app.exec()
an den klasse Graph und Connect_Robot schreibe ich gerade. Bei diesen besteht das problem auch wenn man sie weglässt. und Fernsteuerung und MainWindow kennt ihr ja schon was fehlt denn jetzt noch
LG sauterle
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Keine quasi-globalen Variablen, keine unnötigen Queues, vernünftige Namen, keine Threadpools, kein unbenutzer Code. Also das ganze möglichst auf ein einfaches, nachvollziehbares, lauffähiges Beispiels zusammengekürzt, das trotzdem noch das Problem aufzeigt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

Hallo ich habe mein bestes getan :D (sterncheimporte und threadpool habe ich auch schon aus dem orginal entfernt)

Code: Alles auswählen

from random import randint
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel, QSlider
from PyQt6.QtCore import QThread, pyqtSignal, pyqtSlot, QObject, Qt
import pyqtgraph as pg
from time import sleep

class Signals(QObject):
     plot = pyqtSignal(list,list)
class MainWindow(QMainWindow):

    def __init__(self,signals, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        layout = QVBoxLayout()

        signals.plot.connect(self.plot)

        self.label_start = QLabel("Start")
        self.slider = QSlider(Qt.Orientation.Horizontal)
        self.graphWidget = pg.PlotWidget()
        layout.addWidget(self.label_start)
        layout.addWidget(self.slider)
        layout.addWidget(self.graphWidget)

        w = QWidget()
        w.setLayout(layout)

        self.setCentralWidget(w)

        self.show()


    def plot(self , plotx, ploty):
        self.graphWidget.plot(plotx,ploty)
        print(plotx,ploty)

class Thread2(QThread):
    def __init__(self):
        super().__init__()
        self.ylist = [6, 4, 2, 8, 13, 6, 10, 8, 10, 3, 7, 1, 8, 12, 11, 7, 1, 11, 7, 5, 11, 13, 11, 10, 7, 9, 11, 5, 8, 4, 5, 7, 12, 1, 13]
        self.xlist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
        self.x=35
        self.signals = Signals()

    def zahl(self):
        self.xlist.append(self.x)
        self.ylist.append(randint(0, 15))
        self.x += 1

    @pyqtSlot()
    def emiter(self):
        self.signals.plot.emit(self.xlist, self.ylist)

    def run(self):
        while True:
            sleep(1)
            self.zahl()
            self.emiter()

class Thread3(QThread):
    def __init__(self):
        super().__init__()

    def reader(self):
        try:
            sleep(0.0001)
            self.read = self.port.readline()
        except:
            print("das kann nicht funktionieren one eingesteckte fernbedienung")

    def run(self):
        while True:
            self.reader()




app = QApplication([])

thread3 = Thread3()
thread2 = Thread2()
window = MainWindow(thread2.signals)

thread2.start()
thread3.start()
app.exec()
wenn man den slider schnell bewegt kann man sehen wenn die gui einfriert, auch wenn es in diesem beispiel deutlich kürzer einfriert.je länger das PROGRAMM LÄUft des do länger friert die gui ein
entfernt man das sleep(aus zeile66 (sleep(000.1))) so friert die gui immer kurz ein. macht man es wieder hin friert sie wieder nicht mehr ein. sie friert auch nicht ein wenn man das aktualisiren des grafen unterbricht
das ich self.port nicht instanziert habe liegt daran, dass ich dass ja nicht kann ohne einen uart zu usb converter in meinen pc einzustecken, was ja bei dem orginalprogramm auch nicht anders ist
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

ups ich merkte gerade dass ich dass

Code: Alles auswählen

, type=Qt.ConnectionType.QueuedConnection
vergessen habe aber wenn mas es intigrirt

Code: Alles auswählen

signals.plot.connect(self.plot, type=Qt.ConnectionType.QueuedConnection)
ändert das auch nichts
LG sauterle
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hm, Bei mir friert da nichts ein.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bei mir friert da garnix ein, weil ich keine Dauerschleife produziert habe, die den Reader-Thread auf 100% jagt.

Code: Alles auswählen

from random import randint
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel, QSlider
from PyQt6.QtCore import QThread, pyqtSignal, pyqtSlot, QObject, Qt
import pyqtgraph as pg
from time import sleep


class MainWindow(QMainWindow):

    def __init__(self, data_producer, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        layout = QVBoxLayout()

        data_producer.plot.connect(self.plot,  type=Qt.ConnectionType.QueuedConnection)

        self.label_start = QLabel("Start")
        self.slider = QSlider(Qt.Orientation.Horizontal)
        self.graphWidget = pg.PlotWidget()
        layout.addWidget(self.label_start)
        layout.addWidget(self.slider)
        layout.addWidget(self.graphWidget)

        w = QWidget()
        w.setLayout(layout)
        self.setCentralWidget(w)


    def plot(self , plotx, ploty):
        self.graphWidget.plot(plotx,ploty)


class Thread2(QThread):
    plot = pyqtSignal(list,list)

    def __init__(self):
        super().__init__()
        self.ylist = [6, 4, 2, 8, 13, 6, 10, 8, 10, 3, 7, 1, 8, 12, 11, 7, 1, 11, 7, 5, 11, 13, 11, 10, 7, 9, 11, 5, 8, 4, 5, 7, 12, 1, 13]
        self.xlist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
        self.x=35

    def zahl(self):
        self.xlist.append(self.x)
        self.ylist.append(randint(0, 15))
        self.x += 1

    def run(self):
        while True:
            sleep(.1)
            self.zahl()
            self.plot.emit(self.xlist, self.ylist)

class Thread3(QThread):
    def __init__(self):
        super().__init__()

    def reader(self):
        sleep(1)


    def run(self):
        while True:
            self.reader()



def main():
    app = QApplication([])

    thread3 = Thread3()
    thread2 = Thread2()
    window = MainWindow(thread2)
    window.show()

    thread2.start()
    thread3.start()
    app.exec()


# main guard
if __name__ == '__main__':
    main()
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

Danke für eure Hilfe mit einer kleinen änderung an Fernsteurung.run habe ich das Problem nun gelöst.Dieser Fehler wird mir ein Lehre sen was nutzlose schleifen angeht.Zuletzt hätte ich noch eine Frage welche Tips würdet ihr mir geben was ich an meinem Programirstyle dringend ändern muss abgesehen von:
sinnvolle Namen
keine sternchenimporte

LG und Danke sauterle
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Keine nackten try/excepts.
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und wie gesagt nicht einfach *alles* an `self` binden. Daraus folgend dann keine Funktionen in Klassen stecken, denn mindestens zwei ”Methoden” brauchen `self` überhaupt gar nicht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
sauterle
User
Beiträge: 81
Registriert: Mittwoch 27. Juli 2022, 21:33

Hallo danke für euer feedback
das problem ist LEIDER nur weg solagne man mit kurzen listen arbeitet ab 200 300 stützpunkten ist es wieder da hier eine leicht umgestaltete Form des testprogrammes:

Code: Alles auswählen

from random import randint
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel, QSlider
from PyQt6.QtCore import QThread, pyqtSignal, pyqtSlot, QObject, Qt
import pyqtgraph as pg
from time import sleep

class Signals(QObject):
     plot = pyqtSignal(list,list)
     starter = pyqtSignal()
class MainWindow(QMainWindow):

    def __init__(self,signals, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        layout = QVBoxLayout()

        signals.plot.connect(self.plot, type=Qt.ConnectionType.QueuedConnection)

        self.label_start = QLabel("Start")
        self.slider = QSlider(Qt.Orientation.Horizontal)
        self.graphWidget = pg.PlotWidget()
        layout.addWidget(self.label_start)
        layout.addWidget(self.slider)
        layout.addWidget(self.graphWidget)

        w = QWidget()
        w.setLayout(layout)

        self.setCentralWidget(w)

        signals.starter.emit()

        self.show()


    def plot(self , plotx, ploty):
        self.graphWidget.plot(plotx,ploty)

class Thread2(QThread):
    def __init__(self):
        self.signals = Signals()
        super().__init__()
        self.ylist = []
        self.xlist = []
        self.signals.starter.connect(self.viel_emiter, type=Qt.ConnectionType.QueuedConnection)
        self.x=500


    def zahl(self):
        self.xlist.append(self.x)
        self.ylist.append(randint(0, 15))
        self.x += 1

    @pyqtSlot()
    def emiter(self):
        self.signals.plot.emit(self.xlist, self.ylist)

    def run(self):
        while True:
            sleep(1)
            self.zahl()
            self.emiter()
    def viel_emiter(self):
        for t in range(200):
            sleep(0.0001)
            self.zahl()
            self.emiter()



app = QApplication([])

thread2 = Thread2()
window = MainWindow(thread2.signals)

thread2.start()

app.exec()
das sleep in die funktion viel_emiter habe ich gesetzt da ich nicht so genau weiss was pasiert wenn man pausenlos signale schickt. man muss kurz waten bis am anfang alles signale abgeschickt sind dann kann man wieder mit dem bewegen des sliders sehen wie lange es einfriert
komischerweise tritt es nicht auf wenn ich viel emiter weglasse und von anfang an eine plotliste mit 500 stützpunkten nehme
LG sauterle
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wieso ist da immer noch diese unnoetige Signals-Klasse drin? Wie man ohne die auskommt, habe ich doch gezeigt.

Irgendwann werden es halt zu viele Punkte. Du darfst halt nicht nur dranhaengen. Sondern musst kappen bei einer noch funktionierenden Menge.
Antworten