[PYTHON] Zeichnen Sie mit PySide Ihren eigenen Drop Indicator (Realisieren Sie QProxyStyle mit schwarzer Magie)

Wenn Sie die Hintergrundfarbe eines Widgets mit PySide ändern, ist die Drop-Anzeige (Anzeige, wo beim Ziehen und Ablegen abgelegt werden soll) möglicherweise schwer zu erkennen. Ich möchte meine eigenen zeichnen, um den Indikator hervorzuheben.

Die Dinge sind jedoch nicht einfach und StyleSheet verfügt nicht über eine Drop Indicator-Einstellung.

QProxyStyle wird verwendet, um den Drop Indicator unabhängig in Qt zu zeichnen, QProxyStyle ist jedoch in PySide und PyQt nicht vorhanden.

Hacken Sie daher PySide, um die Zeichnung von Drop Indicator abzufangen. Darüber hinaus ist diese Methode keine legitime schwarze Magie, und wir können nicht garantieren, dass sie in Zukunft bei PySide wirksam sein wird.

Lassen Sie uns zunächst die Zeichnung auf legitime Weise stehlen.

Legitimer Weg: Kreieren Sie Ihren eigenen Stil

Stellen wir uns zunächst eine legitime Methode vor.

Auf diese Weise können Sie die QStyle-Klasse selbst erweitern und die QStyle :: drawPrimitive-Methode überschreiben. Da meine Umgebung Windows ist, erbe ich QWindowsStyle.

class MyWindowsStyle(QWindowsStyle):
    def drawPrimitive(self, element, option, painter, widget):
        if element == QStyle.PE_IndicatorItemViewItemDrop:
            pen = QPen(Qt.red)
            pen.setWidth(2)

            painter.setPen(pen)
            if not option.rect.isNull():
                painter.drawRect(option.rect)
            return

        super(MyWindowsStyle, self).drawPrimitive(element, option, painter, widget)

Im obigen Beispiel ist die Drop-Anzeige rot und der Rahmen dick. Legen Sie diese Stilklasse mit QApplication :: setStyle fest.

my_style = MyWindowsStyle(parent_widget)

QApplication.setStyle(my_style)
2016-12-28_23h35_29.png

Es scheint funktioniert zu haben, sieht aber insgesamt altmodisch aus.

In der Windows-Version von PySide (Qt) ist der Standardstil QWindowsVistaStyle anstelle von QWindowStyle. QWindowsVistaStyle ist jedoch ein dynamisch geladener Plugin-Stil, sodass eine Klassenvererbung nicht möglich ist. Da es eine bestimmte Stilklasse erbt, sieht es auf Mac und Linux genauso aus. Wenn Ihnen diese Nachteile nichts ausmachen, empfehlen wir diese Methode.

Verwenden wir nun schwarze Magie, um die Zeichnung im QWindows Vista-Stil zu stehlen.

F Generieren Sie eine Instanz von Windows Vista Style

Erstellen Sie zunächst eine QWindowsVistaStyle-Instanz. Verwenden Sie die QStyleFactory-Klasse, um Stile zu generieren.

vista_style = QStyleFactory.create("windowsvista")

Sie haben jetzt eine QWindowsVistaStyle-Instanz erstellt.

Überprüfen Sie übrigens die Standardstilklasse und den Schlüsselnamen (Zeichenfolge, die an QStyleFactory.create übergeben wird) jeder Umgebung wie folgt.

QApplication.style().metaObject().className()
>>> QWindowsVistaStyle

QApplication.style().objectName()
>>> windowsvista

Erstellen Sie beispielsweise eine Proxy-Klasse

Erstellen Sie eine Proxy-Klasse, die Stilinstanzen enthält.

class ProxyStyle(QCommonStyle):
    TranslateMethods = [
        'drawComplexControl', 'drawControl', 'drawItemText', 'generatedIconPixmap', 
        'hitTestComplexControl', 'pixelMetric', 'polish', 'sizeFromContents', 
        'sizeFromContents', 'standardPixmap', 'styleHint', 'styleHint',
        'subControlRect', 'subElementRect', 'unpolish'
    ]

    def __init__(self, style, parent=None):
        super(ProxyStyle, self).__init__(parent)
        self._style = style

        for method_name in self.TranslateMethods:
            setattr(self, method_name, getattr(self._style, method_name))

    def drawPrimitive(self, element, option, painter, widget):
        if element == QStyle.PE_IndicatorItemViewItemDrop:
            pen = QPen(Qt.red)
            pen.setWidth(2)

            painter.setPen(pen)
            if not option.rect.isNull():
                painter.drawRect(option.rect)
            return

        self._style.drawPrimitive(element, option, painter, widget)

Wie Sie sehen können, erfolgt die Delegation auf gewaltsame und schlammige Weise. Übrigens kann das PySide-Objekt den Delegierungstrick von `` `getattr``` nicht verwenden. QProxyStyle wird mit Brute Force Black Magic implementiert.

Dynamische Proxy-Stilinstanzen in dieser Klasse und definieren Sie sie als Stile in QApplication.

proxy_style = ProxyStyle(vista_style)

QApplication.setStyle(proxy_style)
2016-12-29_02h01_19.png

Es scheint funktioniert zu haben. Selbst wenn Sie StyleSheet zusammen verwenden und den Hintergrund wie unten gezeigt grau machen, funktioniert dies ohne Probleme.

tree_view.setStyleSheet("QTreeView { background-color: gray }")
2016-12-29_02h07_40.png

Zusammenfassung

Diese Methode ist überhaupt nicht elegant.

Es gibt auch eine Methode, um das paintEvent der Ansicht zu überschreiben und alles selbst zu zeichnen. Dies ist jedoch sehr mühsam, da die Zeichnung für jeden Ansichtstyp geändert werden muss. Wenn möglich, möchte ich überleben, indem ich den Stil festlege.

Wenn es einen besseren Weg gibt, lehre mich bitte.

Recommended Posts

Zeichnen Sie mit PySide Ihren eigenen Drop Indicator (Realisieren Sie QProxyStyle mit schwarzer Magie)
Trainiere UGATIT mit deinem eigenen Datensatz
Löse dein eigenes Labyrinth mit DQN