seltsames Verhalten eines dynamischen button

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

ich hab ein Hauptprogramm, von da aus öffne ich ein Dialog. Wenn ich beim 1. mal auf den button klicke, schliesst er auch. baue ich ein wieder ein fenster auf, muss ich 2 mal drauf klicken bis er schliesst. es werden wohl irgendwie 2 Instanzen aufgemacht, wieso weiss ich nicht.Je öffters ich die Klasse aufrufe, desto öffters muss ich auf den button klicken, bis er schliesst. Ich versteh aber nicht warum, mit self.reject() oder self.close() müsste die Klasse doch weg sein. Hat einer eine Idee ?
Hier der Dialog:

Code: Alles auswählen

from PyQt6.QtWidgets import QDialog, QGroupBox, QPushButton, QSplitter, QLabel, QGridLayout, QHBoxLayout, QSpacerItem, QSizePolicy
from PyQt6.QtCore import Qt, QRect, QSize
from PyQt6.QtGui import QFont, QFontMetrics

import time

from gui.custom_wordwrap_button import QWordWarpButton

class PerformMaskSelection(QDialog):
    def __init__(self, parent, type): # von wo es kommt
        super(PerformMaskSelection,self).__init__(parent) 
        self.Main = parent 
        self.type = type
        self.instance_id = time.time()
        self.setupUi() 
        
    def setupUi(self):        
        self.resize(240, 120)
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.splitter = QSplitter(parent=self)
        self.splitter.setOrientation(Qt.Orientation.Horizontal)
        self.splitter.setObjectName("splitter")
        self.label = QLabel(parent=self.splitter)
        self.label.setText("")
        self.label.setObjectName("label")
        self.Btn_close = QPushButton(parent=self.splitter)
        self.Btn_close.setMinimumSize(QSize(20, 20))
        self.Btn_close.setMaximumSize(QSize(20, 20))
        self.Btn_close.setAutoFillBackground(False)
        self.Btn_close.setStyleSheet("background-image: url(:/labels/_labels/fenster-schliessen.png);")
        self.Btn_close.setText("")
        self.Btn_close.setFlat(True)
        self.Btn_close.setObjectName("Btn_close")
        self.Btn_close.setToolTip("Fenster schliessen")
        self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
        widget_count= self.set_group_button()
        standard_grey = self.Main.palette().color(self.Main.backgroundRole()).name()
        self.setStyleSheet(f""" QDialog {{border: 2px solid black; background-color: {standard_grey};}}""")                
        self.setWindowFlags(Qt.WindowType.FramelessWindowHint)        
        self.Btn_close.clicked.connect(self.close) 

    def set_group_button(self):
        font = QFont("MS Shell Dlg", 8)
        metrics = QFontMetrics(font)        
        self.sources = getattr(self.Main,self.type).toolTip().split("<br>", 1)
        sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)        
        for idx, group_name_and_button_text in enumerate(self.sources):
            group_name, button_text = group_name_and_button_text.split(": ",1)            
            rect = metrics.boundingRect(button_text)  
            rounded_width = max(220, round(rect.width() / 10) * 10)
            rounded_height = max(40, round(rect.height() / 10) * 10 + 10)           
            self.set_button_in_groupbox(group_name, button_text, sizePolicy, idx, rounded_width, rounded_height)
        return len(self.sources)           
    
    def set_button_in_groupbox(self, group_name, button_text, sizePolicy, idx, rect_width, rounded_height):
        groupbox = QGroupBox(parent=self) 
        groupbox.setGeometry(QRect(0, 10, rect_width, rounded_height))       
        groupbox.setMinimumSize(QSize(rect_width, rounded_height))
        groupbox.setMaximumSize(QSize(rect_width, rounded_height))
        groupbox.setTitle(group_name) 
        sizePolicy.setHeightForWidth(groupbox.sizePolicy().hasHeightForWidth())
        setattr(self,f"gBox_selection_{idx}", groupbox)       
        button = QWordWarpButton(parent=groupbox)        
        button.setGeometry(QRect(-8, 12, rect_width+18, rounded_height-2)) 
        button.setSizePolicy(sizePolicy)
        button.setMinimumSize(QSize(rect_width-2, rounded_height-2))
        button.setMaximumSize(QSize(rect_width-2, rounded_height-2))
        button.setStyleSheet(self.button_stylesheet())
        button.setText(button_text)         
        button.clicked.connect(self.selected_button)
        button.setObjectName(f"Btn_selection_{idx}")
        setattr(self,f"Btn_selection_{idx}", button)
        self.gridLayout.addWidget(getattr(self,f"gBox_selection_{idx}"), idx+1, 0, 1, 1)

    def selected_button(self):            
        sender = self.sender()
        for idx in range(len(self.sources)):
            if sender == getattr(self,f"Btn_selection_{idx}"):
                getattr(self.Main,self.type).setText(sender.text())
                break
        print(f"{sender.objectName()} klickt bei: {self.instance_id}")
        self.reject()        
       
    def button_stylesheet(self):
        return """QPushButton {background-color: #FFFDD5;}
            QLabel {background-color: transparent;}
            QLabel:hover {border: 2px solid rgb(49, 50, 62);}"""




if __name__ == '__main__':
    PerformMaskSelection(QDialog)
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ernie1412: Das ist nicht lauffähig weil da beim erstellen vom `PerformMaskSelection`-Objekt ein Argument zu wenig übergeben wird.

`Main` ist als Attribut falsch geschrieben und es ist auch überflüssig, weil man den Wert auch über `parent()` abfragen kann, was jedes `QObject` hat.

`getattr()` und `setattr()` sollte da dringend verschwinden. Statt auf dem Objekt berechnete Attribute zu setzen und abzufragen die aus einem Präfix und einem Index zusammengesetzt sind, sollten das normale Datenstrukturen sein, also je nachdem was der Index ist Listen oder Wörterbücher, statt den Namensraum des Objekts da umständlich und undurchsichtig für zu missbrauchen.

Eine Methode die einfach nur statisch eine Zeichenkette zurück liefert macht keinen Sinn. Diese Zeichenkette wäre einfach nur eine Konstante auf der Klasse.

`sender()` benutzt man eher nicht. Python kennt so etwas wie `functools.partial()`. Da muss man dann nicht den Sender eines Signals identifizieren und linear in dynamisch abgefragten Attributen nach einem passenden Wert suchen.

Wobei das auch schräg ist, dass diese Klasse auf `Main` also eigentlich auf `parent` herumoperiert. Klassen die höher in der Objekthierarchie sind, sollte man eigentlich nicht so imtim kennen müssen. Dafür sind Signale und Slots da, das man Ereignisse nach oben melden kann, und *dort* dann etwas damit gemacht werden kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten