auf QtWidgets.QDialogButtonBox reagieren ???

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Ernie1412
User
Beiträge: 160
Registriert: Freitag 10. Januar 2020, 20:38

ich habe eine DialogButtonBox
QtWidgets.QDialogButtonBox

Code: Alles auswählen

       self.OK_Btn.accepted.connect(Abfrage.accept)        
        self.OK_Btn.rejected.connect(Abfrage.reject)
ich müsste doch nach einem "exec_() reagieren können
weil ich wenn ich auf einem Button klicke schliesst sich das Fenster

wie genau fange ich accept bzw reject ab bzw frage ich es ab ?
ich hab da nichts passendes im Internet finden können
bei QDialog gehts ja mit:

Code: Alles auswählen

       if dialog.exec_() == QtWidgets.QDialog.Accepted:
            dirname = dialog.selectedFiles()[0]  # returns a list
            return dirname
und danke für den Tip mit QDialog. damit ging es. nun hab ich wie beschrieben ein 2. Problem :D
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Mit dem Codefragment kann man nichts anfangen.
Was ist denn `Abfrage`?
Ernie1412
User
Beiträge: 160
Registriert: Freitag 10. Januar 2020, 20:38

Code: Alles auswählen

def setupUi(self, Abfrage):
        Abfrage.setObjectName("Abfrage")
        Abfrage.resize(750, 450)
        self.OK_Btn = QtWidgets.QDialogButtonBox(Abfrage)
dort habe ich 2 Buttons "OK" und "Cancel"

wenn ich OK klicke soll er zur Funktion "Bla1"
wenn Cancel oder fenster schliesse zur Funktion "Bla2"
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

So wie Du das machst, sollte es eigentlich funktionieren, deshalb hilft es nicht, nur Code-Fragmente zu posten, denn da ist irgendwo an anderer Stelle etwas nicht richtig.
Ernie1412
User
Beiträge: 160
Registriert: Freitag 10. Januar 2020, 20:38

Code: Alles auswählen

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Abfrage(object):
    def __init__(self,fname):
        self.fname = fname
    def setupUi(self, Abfrage):
        Abfrage.setObjectName("Abfrage")
        Abfrage.resize(739, 477)
        self.Info = QtWidgets.QLabel(Abfrage)
        self.Info.setGeometry(QtCore.QRect(50, 10, 431, 20))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.Info.setFont(font)
        self.Info.setObjectName("Info")
        self.rBtn = QtWidgets.QRadioButton(Abfrage)
        self.rBtn.setGeometry(QtCore.QRect(50, 40, 631, 20))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(80)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.rBtn.sizePolicy().hasHeightForWidth())
        self.rBtn.setSizePolicy(sizePolicy)
        self.rBtn.setMinimumSize(QtCore.QSize(0, 0))
        self.rBtn.setSizeIncrement(QtCore.QSize(0, 0))
        self.rBtn.setBaseSize(QtCore.QSize(0, 0))        
        self.rBtn.setObjectName("rBtn")
        self.splitter = QtWidgets.QSplitter(Abfrage)
        self.splitter.setGeometry(QtCore.QRect(210, 420, 331, 23))
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setObjectName("splitter")
        self.OK_Btn = QtWidgets.QPushButton(self.splitter)
        self.OK_Btn.setObjectName("OK_Btn")
        self.Cancel_Btn = QtWidgets.QPushButton(self.splitter)
        self.Cancel_Btn.setObjectName("Cancel_Btn")
        for i in range(len(self.fname)):
            self.rBtn = QtWidgets.QRadioButton(Abfrage)
            self.rBtn.setGeometry(QtCore.QRect(50, 40+i*30, 651, 20))
            self.rBtn.setMinimumSize(QtCore.QSize(80, 20))
            if i==0:
                self.rBtn.setChecked(True)
            else:
                self.rBtn.setChecked(False)
            self.rBtn.setObjectName("rBtn_{}".format(i))
            self.rBtn.setText("{}".format(self.fname[i]))
        self.retranslateUi(Abfrage)

        QtCore.QMetaObject.connectSlotsByName(Abfrage)
 
    def retranslateUi(self, Abfrage):
        _translate = QtCore.QCoreApplication.translate
        Abfrage.setWindowTitle(_translate("Abfrage", "Dialog"))       
        self.OK_Btn.setText(_translate("Abfrage", "OK"))
        self.Cancel_Btn.setText(_translate("Abfrage", "Cancel"))
        self.Cancel_Btn.clicked.connect(lambda:self.closeFenster(Abfrage)) 
        self.OK_Btn.clicked.connect(lambda: self.okFenster(self.rBtn.isChecked()))

    def closeFenster(self,Abfrage):
        msg=QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Information)
        msg.setWindowTitle('Info')
        msg.setText("keine Umbenennung der Datei !")
        msg.setInformativeText("Die Datei ist so geblieben wie sie war")
        msg.exec_()
        rename=""
        Abfrage.hide() 
        return rename 

    def okFenster(self,chk):      
        
        msg=QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Information)
        msg.setWindowTitle('Info')
        msg.setText(self.rBtn.setText("{}".format(0)))
        msg.setInformativeText(self.rBtn.setText("{}".format(0)))
        msg.exec_()
    
        

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)   )
    Abfrage = QtWidgets.QDialog()
    fname=("bla1","bla2","bl3","bla4","bla5","bl6","bla7","bla8","bl9")
    ui = Ui_Abfrage(fname)
    ui.setupUi(Abfrage)
    Abfrage.show()
    sys.exit(app.exec_())
hier der Code:
jetzt hab ich anstatt DialogbuttonBox 2 PushButtons.
nur wie kann ich anhand des names "self.rBtn.setObjectName("rBtn_{}".format(i))" checken welcher RadioButton is checked ?
ich kenne mich nicht so sehr aus mit den Befehlen wie und was wo hinkommt, bei mir ist es eher ausprobieren und ob Visual Studio Codes was unterstreicht als Fehler
Rest hole ich mir aus dem netz, aber dazu habe ich nichts gefunden
die GUI erstelle ich mit QT Designer und wandle sie in py um
ich habe ein hauptfenster von daaus gehe ich ins Fenster "Abfrage"
return soll mir der Wert ausgeben den ich in RadioButton gewählt habe
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ernie1412: Die *.ui-Datei in Python-Quelltext umwandeln macht man schon nicht, und dann den Kommentar der konvertierten Datei steht das man an dem Code nix ändern sollte entfernen und dann genau das machen ist noch weniger eine gute Idee. Statt Quelltext zu generieren lädt man die *.ui-Datei zur Laufzeit mit Hilfe des `PyQt5.uic`-Moduls.

Was auch so gar keine gute Idee ist: mit `setGeometry()` absolute Positionen und Grössen setzen. Um Widgets anzuordnen verwendet man Layouts.

`setObjectName()` habe ich bei handgeschriebenen Code noch nie verwendet, wozu auch‽ Wenn man die Objekte später noch mal braucht dann merkt man sich die in einer passenden Datenstruktur. Was dagegen keinen Sinn macht ist jeden Checkbutton nacheinander an das gleiche Attribut zu binden, denn so kann man am Ende ja nur auf das letzte Checkbutton-Objekt zugreifen.

Namen schreibt man in Python klein_mit_unterstrichen. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Keine kryptischen Abkürzungen oder Pre- und Suffixe in Namen. Wenn man `filename` meint, sollte man nicht `fname` schreiben und bei `rBtn` ist wohl `radio_button` gemeint. `rBtn` wird auch doppelt verwendet, so das man auf das erste Radiobutton-Objekt was nicht in einer Schleife erzeugt wird, danach gar nicht mehr über das Attribut zugreifen kann.

Bei `closeFenster()` macht ein Rückgabewert keinen Sinn weil diese Methode als Rückruffunktion bei einem Klick auf „Abbruch“ von der GUI-Hauptschleife aufgerufen wird. Die erwartet aber keinen Rückgabewert an der Stelle. Was sollte die Hauptschleife an der Stelle auch mit so einem Wert anfangen‽
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Ernie1412
User
Beiträge: 160
Registriert: Freitag 10. Januar 2020, 20:38

meine Frage wurde immernoch nicht beantwortet
Nur weil ich nicht so skripte wie es die elitäre Gesellschaft will ?
entweder man beantwortet meine Frage oder lässt es
sowas wie man macht das nciht
ich kann für filename auch scheisse schreiben, ist doch mein programm, versteh das ganze nicht.
Es soll nur laufen
ich hab hier 12 beiträge gepostet
und nur kritik an mein code erhalten.
ist das Sinn von Hilfe oder nur um zu zeigen wie elitär man doch skripten kann ?
wer schreibt mir vor wie ich filename schreiben soll ?
wo steht das ?
sagt der Interpreter dann hey das muss filename heissen und nciht scheisse, ansonsten lass ich das Programm nicht laufen ?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast jetzt doch gar keine connect mehr zu accept bzw. reject. exec_ benutzt Du bei Deinem Dialog auch nicht.
Die Frage nach den Radio-Buttons wurde Dir beantwortet. Ich finde es sehr schwer, den Code zu lesen, wo ich mich fragen muß, was fname denn ist, und plötzlich merke, dass das eine Liste sein soll. Wenn Du also Hilfe willst, solltest Du Dich ein bißchen zusammenreißen, statt hier rumzupöbeln.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dem Python Interpreter ist das egal. Den Leuten, die dir hier umsonst helfen sollen, zuzumuten, knietief durch die Scheisse zu waten, die du zusammengekloppt hast, macht es hingegen was aus.

Wenn du willst, das sich wer das antut, Zahl Schmerzensgeld. Oder arbeite an deiner undankbaren Attitüde.
Ernie1412
User
Beiträge: 160
Registriert: Freitag 10. Januar 2020, 20:38

Mich hat das nur geärgert, das man mich nur kitisiert anstatt mir zu helfen.
das mit dem ui datei laden ist eh einfacher zu handhaben, wusste nicht das man das macht, weil nach dem compilen man ja auf die .ui Datei zugreifen könnte.
Wenn es hilft kommentiere ich auch meine Codes, evtl macht es das einfacher.
manch Variablen kürze ich halt ab. Man muss ja so schon viel schreiben.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@Ernie1412: Entschuldige meine Direktheit, aber: Du gehst falsch mit Kritik um.
Sei froh, dass du sie bekommst. Wie willst du dich sonst verbessern? Hier sind Leute im Forum unterwegs, die nicht wenig Energie darauf verwenden gebetsmühlenartig die Grundlagen guter Programmierung in Python zu vermitteln. Die tun das, weil sie jahrelang Erfahrung haben und wissen, welches der einfachste Weg ist.
Am Ende liegt es natürlich an dir. Du kannst dich durch Kritik an deinem Code persönlich angegriffen fühlen. Oder du kannst sie als Werkzeug sehen, dich zu verbessern.

Abgekürzte oder nicht sprechende Variablen sind halt Mist. Weil auch du sie in zwei Wochen nicht mehr verstehst. Jetzt jammer und sei stur - oder werde halt besser.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ernie1412: Welche Frage wurde nicht beantwortet? Die danach wie man anhand des Qt-`objectName` prüft ob ein Checkbutton gesetzt ist habe ich beantwortet. Gerne noch mal: Das macht man so nicht, sondern man speichert die Checkbutton-Objekte in einer passenden Datenstruktur in einem Attribut auf das man später zugreifen kann. Eine `QButtonGroup` würde sich hier geradezu aufdrängen weil man da den Buttons numerische IDs geben kann und abfragen kann welcher Button oder welche von diesen IDs gerade ausgeählt ist.

Beim Erstellen der `QRadioButton`-Objekte sollte man vielleicht noch darauf achten das "&" eine besondere Bedeutung im Beschriftungstext hat und das man entsprechend dieses Zeichen escapen muss wenn es regulär in den Texten vorkommen kann.

Konstruktive Kritik ist in der Tat Sinn von Hilfe. Ohne wüsstest Du ja nicht was Du falsch machst. Theoretisch ist die Namensgebung egal wenn das Dein Programm ist. Nur ist das a) nicht mehr nur Dein Problem wenn Du dazu öffentlich Fragen stellst, und b) hat die Praxis gezeigt das es auch für Dich nicht egal ist, denn Namen tragen zum Verständnis oder eben zum nicht oder falsch verstehen von Code bei. Auch für denjenigen der den Code schreibt. Und das nicht nur wenn der Autor selbst nach ein paar Wochen wieder in den Quelltext schaut und nicht mehr frisch im Kopf hat was welcher kryptische Name eigentlich bedeutet, sondern auch schon beim schreiben vom Code. Beispielsweise wenn man als Autor Probleme hat für einen Wert einen passenden Namen zu finden, ist das oft ein Zeichen das man das Problem oder die Lösung nicht ganz verstanden hat, oder das man bei zusammengesetzten Werten Dinge zusammengefasst hat, die so nicht zusammen gehören. Wenn man einen guten Namen sucht, muss man über das Problem und die Lösung nachdenken — was im Grunde programmieren an sich ausmacht.

Das hat auch nichts mit ”elitär” zu tun. Gute Namensgebung ist eine wichtige Grundlage beim Programmieren. Für jeden. Wenn nicht für Anfänger sogar noch mehr als für Leute die mehr Erfahrung haben.

Formal steht im Style Guide for Python Code wie man Namen in Python schreibt und im offiziellen Tutorial wird relativ weit vorne im Abschnitt „Intermezzo: Coding Style“ auf das Thema eingegangen (und auch auf den Style Guide verwiesen).

Was das Inhaltliche angeht, also sprechende, klare Bezeichner bei denen der Leser keine kryptischen Abkürzungen raten muss, und das man sich an die Konventionen halten sollte, steht das so ziemlich überall in Literatur die etwas taugt. Sowohl in allgemeinen, nicht auf eine bestimmte Programmiersprache bezogenen Büchern, wie „Weniger schlecht Programmieren“ von Kathrin Passig, was sich an Anfänger/Hobbyprogrammierer richtet, als auch in Büchern wie „Good Code“ von Pete Goodliffe. Und auch in Büchern für konkrete Programmiersprachen, wie beispielsweise „Modern C“ von Jens Gustedt.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Ernie1412
User
Beiträge: 160
Registriert: Freitag 10. Januar 2020, 20:38

so habe nun einiges umstruktuiert !
bin nun hin zum ui = ... anstatt den Code zu generieren und copy paste
variablennamen hab ich auch soweit geändert.
nun habe ich 1 kleines Problem, aber wahrscheinlich mit QButtonGroup lösen lässt.
Wo kann man da was zu lesen am besten Beispiele.
pyqt5: --> https://doc.qt.io/qt-5/ ist ja sehr allgemein gehalten.
Einige Python Beispiele wären nicht schlecht.
funktioniert QButtonGroup mit jeglicher Art von Buttons ?(Radio oder Combo oder Push?

weil ich das so nun geregelt habe:
filename ist ein Tuple mit max 10 zeilen
pfad ist global
und beinhaltet den Pfad meines Programmes (__file__)

Code: Alles auswählen

  
    """
        2a. Abfrage:ein Dateiname wird anhand einer Analyse nach Wunsch abgefragt.
                    Vorgeschlagen werden max. 10 Dateinamen                
    """
    def Abfrage(self,filename):
        self.AbfrageW=uic.loadUi(os.path.join(pfad+ r'\\ui\\Abfrage.ui'))
        for i in range(len(filename)):
            if i==0:
                self.AbfrageW.rBtn_1.setText(filename[i]) 
                self.AbfrageW.rBtn_1.wahl = i
                #self.AbfrageW.rBtn_1.clicked.connect(self.onClicked)
                 
            if i==1:
                self.AbfrageW.rBtn_2.setText(filename[i])
                self.AbfrageW.rBtn_2.wahl = i
                #self.AbfrageW.rBtn_2.clicked.connect(self.onClicked)                
            if i==2:
                self.AbfrageW.rBtn_3.setText(filename[i])
                self.AbfrageW.rBtn_3.wahl = i
                #self.AbfrageW.rBtn_3.clicked.connect(self.onClicked)                
            if i==3:
                self.AbfrageW.rBtn_4.setText(filename[i])
                self.AbfrageW.rBtn_4.wahl = i
                #self.AbfrageW.rBtn_4.clicked.connect(self.onClicked)                
            if i==4:
                self.AbfrageW.rBtn_5.setText(filename[i])
                self.AbfrageW.rBtn_5.wahl = i
                #self.AbfrageW.rBtn_5.clicked.connect(self.onClicked)                
            if i==5:
                self.AbfrageW.rBtn_6.setText(filename[i])
                self.AbfrageW.rBtn_6.wahl = i
                #self.AbfrageW.rBtn_6.clicked.connect(self.onClicked)                
            if i==6:
                self.AbfrageW.rBtn_7.setText(filename[i])
                self.AbfrageW.rBtn_7.wahl = i
                #self.AbfrageW.rBtn_7.clicked.connect(self.onClicked)                
            if i==7:
                self.AbfrageW.rBtn_8.setText(filename[i])
                self.AbfrageW.rBtn_8.wahl = i                               
            if i==8:
                self.AbfrageW.rBtn_9.setText(filename[i])
                self.AbfrageW.rBtn_9.wahl = i                                
            if i==9:
                self.AbfrageW.rBtn_10.setText(filename[i])
                self.AbfrageW.rBtn_10.wahl = i                                
                self.AbfrageW.OK_Button.clicked.connect(self.onClicked())
        self.AbfrageW.exec_()

            
    def onClicked(self):
        if self.AbfrageW.rBtn_1.isChecked():auswahl=0            
        if self.AbfrageW.rBtn_2.isChecked():auswahl=1
        if self.AbfrageW.rBtn_3.isChecked():auswahl=2            
        if self.AbfrageW.rBtn_4.isChecked():auswahl=3
        if self.AbfrageW.rBtn_5.isChecked():auswahl=4            
        if self.AbfrageW.rBtn_6.isChecked():auswahl=5
        if self.AbfrageW.rBtn_7.isChecked():auswahl=6            
        if self.AbfrageW.rBtn_8.isChecked():auswahl=7
        if self.AbfrageW.rBtn_9.isChecked():auswahl=8            
        if self.AbfrageW.rBtn_10.isChecked():auswahl=9
                
        self.AbfrageW.hide()
        return auswahl      
return Rückgabe funktioniert so aber nicht, weil ich ja nicht in "def Abfrage" drin bin.
wie gebe ich die return Abfrage denn richtig weiter ?
übrigens: rBtn = 10 RadioButtons
darunter hab ich dann ein OK Button, wenn ich den clicke soll er mir die Auswahl zurückgeben.
Ich hoffe jetzt ist mein Code verständlicher
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ernie1412: Die Qt-Dokumentation ist doch nicht allgemein gehalten? Da gibt's auch tonnenweise Beispielcode. Halt in C++. Das muss man soweit lesen lernen das man es nach Python übersetzen kann.

`QButtonGroup`-Objekten kann man alles hinzufügen was von `QAbstractButton` abgeleitet ist.

Der Code ist zu lang und zu umständlich. Das mit den ganzen ``if``\s und nummerierten Namen sollte man wie gesagt durch eine Datenstruktur ersetzen. Zum Beispiel durch eine im Designer angelegte `QButtonGroup`. Oder man erstellt die `QCheckButton`-Objekte im Code und fügt sie einer im Code erzeugten `QButtonGroup` hinzu.

Oder man lässt das mit den Checkbuttons sein und nimmt eine sinnvollere Darstellung. Beispielsweise ein `QListView` oder ein `QListWidget`.

Die Auswahl muss dann halt Zustand sein und als Attribut auf einem Objekt gesetzt werden.

Ich hoffe `AbfrageW` (entspricht nicht den Konventionen) wird in der `__init__()` der Klasse zum Beispiel an `None` gebunden. Man könnte das *dort* auch bereits laden und dann nur aktualisieren/anzeigen/verstecken.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Ernie1412
User
Beiträge: 160
Registriert: Freitag 10. Januar 2020, 20:38

ich habe das nun mit QbuttonBox geändert
QT Designer hat wohl kein QbuttonBox mehr, musste ich mir selber zusammenfrickeln.
durch immerwiederkehrendes Ausprobieren habe ich endlich geschaft.

Code: Alles auswählen

    def Abfrage(self,filename):
        self.AbfrageW=uic.loadUi(os.path.join(pfad+ r'\\ui\\Abfrage.ui'))        
        self.AbfrageW.buttongroup = QtWidgets.QButtonGroup()
        #self.AbfrageW.buttongroup.buttonClicked[int].connect(self.onClicked)
        for i in range(len(filename)):
            radiobutton = QtWidgets.QRadioButton(filename[i])            
            self.AbfrageW.buttongroup.addButton(radiobutton, i+1)            
            self.AbfrageW.vLayout.addWidget(radiobutton)
            self.setLayout(self.AbfrageW.vLayout)
        self.AbfrageW.okButton.clicked.connect(self.onClicked)
        self.AbfrageW.exec_()
        
            
    def onClicked(self):
        i=0;wahl=0
        for button in self.AbfrageW.buttongroup.buttons():           
            i+=1
            #print(button.ID)
            if button.isChecked() is True:
                self.AbfrageW.Info.setText(str(i) + " Was Clicked ")
                wahl=i               
        self.AbfrageW.hide()
        print(wahl)
        return wahl
return schmeisst der mir sowas raus:
QWidget::setLayout: Attempting to set QLayout "vLayout" on Haupt_Fenster "", which already has a layout

der soll mir die Zahl übergeben. Bei print(wahl) war sie noch eine zahl von 1-10
nach return irgendein Objectname von pyqt5

ich will das ja wohl verstehen, aber wo genau ? und das man es auch verstehen kann :)
wie kriege ich die button ID raus, evtl kann ich die dann an return übergeben ?
.addButton(radiobutton, i+1) <--- i+1: die ID
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Du benutzt os.path.join falsch, `pfad` kommt aus dem nichts. Wenn man über eine Liste iterieren will und zusätzlich einen Zähler braucht, benutzt man `enumerate`, dass dann auch gleich bei 1 anfangen kann. Du hast doch einen eigenen Dialog, warum willst Du dann auf dem Hauptfenster layout aufrufen? AbfrageW sollte nach Konvention abfrage_window heißen, was aber eine Mischung aus Deutsch und Englisch in einem Wort ist. In onClick brauchst Du wieder enumerate.
Wohin soll den `wahl` zurückgeliefert werden? In der Ereignischleife reagiert ja niemand auf den Rückgabewert.
Antworten