Seite 1 von 1

Triggern von dynamisch generierten Checkboxen

Verfasst: Donnerstag 18. Juni 2015, 20:54
von hueschel
Hallo!

Im Moment vezweifele ich daran, eine dynamische Anzahl von QCheckBox-Elementen zu generieren, die ein jeweils zugehöriges QLineEdit-Element freigeben bzw. sperren.
Unten das Minimalbeispiel.


Dabei meldet sich der Fehler File "D:\python\slmauto\slmgui-minimum.py", line 34, in __init__
self.check.toggled.connect(self.invertcheck(i))
TypeError: argument 1 has unexpected type 'NoneType'


Wenn ich die Zeile

Code: Alles auswählen

self.check[i].toggled.connect(self.invertcheck(i))
ausklammere, werden keine Fehler mehr generiert und das GUI sieht aus, wie es vorgesehen ist.
Ich kann mir leider nicht erklären wo der Fehler liegt :?

Achja, wenn ich statt

Code: Alles auswählen

self.code = []
self.code.append(QLineEdit())
self.code.append(QLineEdit())
self.code.append(QLineEdit())
self.code.append(QLineEdit())


einfach schreibe

Code: Alles auswählen

self.code = [0]*4
dann kommt die Fehlermeldung File "D:\python\slmauto\slmgui-minimum.py", line 48, in invertcheck
self.code.setEnabled(True)
AttributeError: 'int' object has no attribute 'setEnabled'


Daher der Umweg mit der append-Funktion. Gibt es hier vielleicht auch eine elegantere Lösung?


Viele Grüße
hueschel

Code: Alles auswählen

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import * 


class Dialog(QDialog):

   
    def __init__(self):
        super(Dialog, self).__init__()

       
        SamplesGroupBox = QGroupBox("Samples:")
        sampleslayout = QGridLayout()
 
        
        self.check = []
        self.check.append(QCheckBox())
        self.check.append(QCheckBox())
        self.check.append(QCheckBox())
        self.check.append(QCheckBox())
        self.code = []
        self.code.append(QLineEdit())
        self.code.append(QLineEdit())
        self.code.append(QLineEdit())
        self.code.append(QLineEdit())
        for i in range(1,4):
            self.check[i] = QCheckBox("Sample #" + str(i))
            self.check[i].setChecked(True)     
            sampleslayout.addWidget(self.check[i], 2*i-1, 0)
            self.check[i].toggled.connect(self.invertcheck(i))
            
            self.code[i] = QLineEdit()
            sampleslayout.addWidget(QLabel("sample code:"), 2*i, 1)
            sampleslayout.addWidget(self.code[i], 2*i, 2)
            self.code[i].setEnabled(True)

        
        SamplesGroupBox.setLayout(sampleslayout)
 
    
        self.setWindowTitle("slmgui")        
        mainlayout = QVBoxLayout()
        mainlayout.addWidget(SamplesGroupBox)
        self.setLayout(mainlayout)
    
    def invertcheck(self,i):
        if self.check[i].isChecked():
             self.code[i].setEnabled(True)
        else:
            self.code[i].setDisabled(True)


if __name__ == '__main__':

    import sys
    app = QApplication(sys.argv)
    dialog = Dialog()
    sys.exit(dialog.exec_())
    

Re: Triggern von dynamisch generierten Checkboxen

Verfasst: Freitag 19. Juni 2015, 07:11
von Sirius3
@hueschel: In Python werden keine Listen vorbelegt, um dann die Elemente zu überschreiben. Du erzeugst ja auch völlig unnötigerweise QCheckBoxen, die Du danach wieder verwirfst. connect erwartet eine Funktion als Argument. Welche Funktion liefert denn der Aufruf von self.invertcheck(i) zurück? Wenn code und check zusammen gehören, sollten das auch keine zwei Listen sein, sondern eine mit Tuplen.

Re: Triggern von dynamisch generierten Checkboxen

Verfasst: Freitag 19. Juni 2015, 07:57
von MagBen
Probier das mal aus:

Code: Alles auswählen

from PyQt5.QtGui import *
 
class Dialog(QDialog):
   
    def __init__(self):
        super(Dialog, self).__init__()
 
        self.code = []       
        samplesGroupBox = QGroupBox("Samples:")
        self.sampleslayout = QGridLayout()
        for i in range(4): # i geht von 0 bis 3
            self.code.append(self.addRow(i))
       
        samplesGroupBox.setLayout(self.sampleslayout)
        self.setWindowTitle("slmgui")        
        mainlayout = QVBoxLayout()
        mainlayout.addWidget(samplesGroupBox)
        self.setLayout(mainlayout)
        
    def addRow(self, rowNo):
        self.sampleslayout.addWidget(QLabel("sample code:"), rowNo, 1)

        code = QLineEdit()
        self.sampleslayout.addWidget(code, rowNo, 2)
        
        check = QCheckBox("Sample #%i" % (rowNo+1))
        check.setChecked(True)    
        self.sampleslayout.addWidget(check, rowNo, 0)
        check.toggled.connect(lambda: code.setEnabled(check.isChecked()))
        
        return code
   
if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    dialog = Dialog()
    sys.exit(dialog.exec_())
In Python ist die Indizierung 0-basiert, der 1. Index einer Liste oder eines Arrays ist 0. Die Liste self.code wird in diesem Beispiel so nicht gebraucht, ich habe sie trotzdem hinzugefügt, damit Du Zugriff auf die Benutzereingaben hast. Eine Liste self.check ist aber nicht erforderlich.

Re: Triggern von dynamisch generierten Checkboxen

Verfasst: Freitag 19. Juni 2015, 09:54
von hueschel
Guten Morgen!

Super, ich habe mir schon gedacht, dass mein Skript sehr chaotisch ist. Im Moment habe ich leider kein PyQt Modul zur Verfügung, aber heute abend werde ich es ausprobieren. :)

Re: Triggern von dynamisch generierten Checkboxen

Verfasst: Montag 29. Juni 2015, 14:40
von AxXel001
Um mal genau auf deine Frage zu antworten, die Funktion invertcheck gibt nichts zurück, also ist ihr Rückgabewert None. Du versuchst also das toggled Signal in Zeile 31 an einen Slot zu knüpfen, der None ist. Das generiert offensichtlich einen Fehler.