[PYTHON] Dessinez votre propre indicateur de chute avec PySide (réalisez QProxyStyle avec la magie noire)

Lors du changement de la couleur d'arrière-plan d'un widget avec PySide, l'indicateur de chute (affichage de l'endroit où déposer lors du glisser-déposer) peut être difficile à voir. Je veux dessiner le mien pour faire ressortir l'Indicateur.

Cependant, les choses ne sont pas faciles et StyleSheet n'a pas de paramètre d'indicateur de chute.

QProxyStyle est utilisé pour dessiner l'indicateur de chute indépendamment dans Qt, mais QProxyStyle n'existe pas dans PySide et PyQt.

Par conséquent, piratez PySide pour intercepter le dessin de Drop Indicator. De plus, cette méthode n'est pas une magie noire légitime, et nous ne pouvons garantir qu'elle sera efficace dans le futur PySide.

Tout d'abord, volons le dessin de manière légitime.

Façon légitime: créez votre propre style

Tout d'abord, pensons à une méthode légitime.

C'est un moyen d'étendre vous-même la classe QStyle et de remplacer la méthode QStyle :: drawPrimitive. Puisque mon environnement est Windows, j'hérite de 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)

Dans l'exemple ci-dessus, l'indicateur de chute est rouge et le cadre est épais. Définissez cette classe de style avec QApplication :: setStyle.

my_style = MyWindowsStyle(parent_widget)

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

Cela semble avoir fonctionné, mais dans l'ensemble, cela semble démodé.

Dans la version Windows de PySide (Qt), le style standard est QWindowsVistaStyle au lieu de QWindowStyle. Cependant, QWindowsVistaStyle est un style de plugin chargé dynamiquement, donc l'héritage de classe n'est pas possible. De plus, comme il hérite d'une classe de style spécifique, il aura le même aspect et la même sensation sur Mac et Linux. Si ces inconvénients ne vous dérangent pas, nous vous recommandons cette méthode.

Utilisons maintenant la magie noire pour voler le dessin de style QWindows Vista.

Q Générer une instance de Windows Vista Style

Commencez par créer une instance QWindowsVistaStyle. Utilisez la classe QStyleFactory pour générer des styles.

vista_style = QStyleFactory.create("windowsvista")

Vous venez de créer une instance QWindowsVistaStyle.

En passant, vérifiez la classe de style standard et le nom de la clé (chaîne de caractères transmise à QStyleFactory.create) de chaque environnement comme suit.

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

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

Créer une classe Proxy par exemple

Créez une classe Proxy contenant des instances de style.

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)

Comme vous pouvez le voir, la délégation se fait de manière forcée et boueuse. À propos, l'objet PySide ne peut pas utiliser l'astuce de délégation de getattr```. QProxyStyle est implémenté avec la magie noire de force brute.

Proxy dynamiquement les instances de style de cette classe et définissez-les comme styles dans QApplication.

proxy_style = ProxyStyle(vista_style)

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

Cela semble avoir fonctionné. Même si vous utilisez StyleSheet ensemble et rendez l'arrière-plan gris comme indiqué ci-dessous, cela fonctionne sans problème.

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

Résumé

Cette méthode n'est pas du tout élégante.

Il existe également une méthode pour remplacer le paintEvent de la vue et tout dessiner par vous-même, mais c'est très gênant car il est nécessaire de changer le dessin pour chaque type de vue. Si possible, j'aimerais survivre en définissant le style.

S'il y a un meilleur moyen, apprenez-moi s'il vous plaît.

Recommended Posts

Dessinez votre propre indicateur de chute avec PySide (réalisez QProxyStyle avec la magie noire)
Entraînez UGATIT avec votre propre jeu de données
Résolvez votre propre labyrinthe avec DQN