Ограничить диапазон перемещения дочернего виджета в родительском виджете - PullRequest
1 голос
/ 28 марта 2020

enter image description here

Я выполняю функцию перетаскивания виджетов. Я скопировал фрагмент кода в Inte rnet и переписал три класса mousePressEvent, mouseReleaseEvent и mouseMoveEvent.

Когда дочерний виджет перемещается к границе родительского виджета, он перезаписывает границу родительского виджета. Я не хочу, чтобы это было так. Я хочу сохранить границу родительского виджета. Есть ли способ сделать дочерний виджет только в области содержимого родительского виджета? Переместить

Я пробовал несколько способов, но все не удалось

Первый: установить свойство setContentsMargins макета родительского элемента управления

Второе: установить отступ родительского элемента управления

Третье: установить поле дочернего элемента управления

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt, QMimeData, QDataStream, QIODevice, QByteArray, QPoint, QSize
from PyQt4.QtGui import QLabel, QWidget, QHBoxLayout, QStyleOption, QPainter, QStyle, QDrag, QListWidgetItem, QIcon, \
    QFontMetricsF, QColor


class Label(QWidget):
    def __init__(self):
        super(Label, self).__init__()

        self.setStyleSheet("""
            *{             border-width: 1px;
             border-style: solid;
             border-color: #cdcdcd;
             background-color:blue
             }
        """)
        self.setFixedSize(300, 300)

    def paintEvent(self, event):
        super(Label, self).paintEvent(event)
        opt = QStyleOption()
        opt.initFrom(self)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)

    def mousePressEvent(self, event):
        self.__mousePressPos = None
        self.__mouseMovePos = None
        if event.button() == QtCore.Qt.LeftButton:
            self.__mousePressPos = event.globalPos()
            self.__mouseMovePos = event.globalPos()

        super(Label, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton:
            # adjust offset from clicked point to origin of widget
            currPos = self.mapToGlobal(self.pos())
            globalPos = event.globalPos()
            diff = globalPos - self.__mouseMovePos
            newPos = self.mapFromGlobal(currPos + diff)
            self.move(newPos)

            self.__mouseMovePos = globalPos

        super(Label, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__mousePressPos is not None:
            moved = event.globalPos() - self.__mousePressPos
            if moved.manhattanLength() > 3:
                event.ignore()
                return

        super(Label, self).mouseReleaseEvent(event)


class Widget(QWidget):
    def __init__(self):
        super(Widget, self).__init__()
        box = QHBoxLayout()
        box.setContentsMargins(20, 20, 20, 20)
        self.setLayout(box)
        box.addWidget(Label())
        self.setFixedSize(500, 500)

        self.setStyleSheet("""
            *{             border-width: 10px;
             border-style: solid;
             border-color: red;}
        """)

    def paintEvent(self, event):
        super(Widget, self).paintEvent(event)
        opt = QStyleOption()
        opt.initFrom(self)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)


class Example(QtGui.QWidget):

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

        self.initUI()

    def initUI(self):
        h = QtGui.QHBoxLayout()
        h.addWidget(Widget())
        self.setLayout(h)
        self.setGeometry(100, 100, 900, 000)
        self.setWindowTitle("PyQt")
        self.show()


def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

1 Ответ

1 голос
/ 28 марта 2020

Родительский QWidget всегда рисуется под дочерним, так что вы видите этот эффект. Решение состоит в том, чтобы создать другого дочернего элемента, который находится поверх синего дочернего элемента, который содержит красную рамку, который имеет тот же размер, что и родительский элемент (это достигается с помощью макета), и который не блокирует события мыши (поскольку по умолчанию улучшенный виджет привязывает мышь к нижним виджетам, но это можно отключить с помощью флага Qt :: WA_TransparentForMouseEvents).

class Widget(QWidget):
    def __init__(self):
        super(Widget, self).__init__()
        self.setFixedSize(500, 500)

        container = QWidget()
        container.setAttribute(Qt.WA_TransparentForMouseEvents)
        container.setStyleSheet(
            """
            *{             border-width: 10px;
             border-style: solid;
             border-color: red;}
        """
        )

        box = QHBoxLayout(self)
        box.setContentsMargins(0, 0, 0, 0)
        box.addWidget(container)

        label = Label()
        label.setParent(self)

        container.raise_()

enter image description here

...