Переместите QLabel в абсолютное положение движением мыши - PullRequest
0 голосов
/ 22 апреля 2019

Я хочу переместить QLabel движением мыши (не как Drag & drop, «объект» исчезает при движении).Нажал - переместил - отпустил.Я сделал это до некоторой степени, но столкнулся с проблемой.QLabel уменьшается при перемещении или даже исчезает (например, уменьшается до 0 ширины).Как это исправить или какой более правильный подход сделать это?

(self.label_pos необходим для сохранения относительного положения мыши внутри self.label)

Или проблема с частотой обновления только на мониторе?Но в редакторе градиентов фотошопа, эта небольшая остановка цвета не шрикнс.Это нестабильно из-за частоты обновления, но всегда одинакового размера.

Это то, что я хочу увидеть, записанное с помощью программы захвата экрана.То же самое, что я вижу в Photoshop

Это то, что я вижу, записанное на моем телефоне.Качество плохое, но разница все равно хорошо видна.

Этот фотошоп также снимается на моем телефоне, здесь «объект» остается того же размера, что и впример, сделанный с использованием снимка экрана

Вот код из ответа eyllanesc, «объект» все еще сжимается: (

self.label = QLabel(self)
self.label.move(100, 100)
self.label.mousePressEvent = self.mouse_on
self.label.mouseReleaseEvent = self.mouse_off
    def mouse_on(self, event):
        self.bool = True
        self.label_pos = event.pos()

    def mouse_off(self, event):
        self.bool = False

    def mouseMoveEvent(self, event):
        if self.bool:
            self.label.move(event.x()-self.label_pos.x(), event.y()-self.label_pos.y())

1 Ответ

1 голос
/ 22 апреля 2019

Вместо использования QLabel я рекомендую использовать QGraphicsRectItem с QGraphicsView, поскольку он специализируется на задачах этого типа:

from PyQt5 import QtCore, QtGui, QtWidgets


class Widget(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.setScene(QtWidgets.QGraphicsScene(self))
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        brush = QtWidgets.QApplication.palette().brush(QtGui.QPalette.Window)
        self.setBackgroundBrush(brush)

        rect_item = self.scene().addRect(
            QtCore.QRectF(QtCore.QPointF(), QtCore.QSizeF(40, 80))
        )
        rect_item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
        rect_item.setBrush(QtGui.QBrush(QtGui.QColor("red")))


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.setFixedSize(640, 480)
    w.show()
    sys.exit(app.exec_())

Если вы хотите просто прокрутить горизонтально, перезапишите метод itemChange класса QGraphicsItem:

from PyQt5 import QtCore, QtGui, QtWidgets


class HorizontalItem(QtWidgets.QGraphicsRectItem):
    def __init__(self, rect, parent=None):
        super(HorizontalItem, self).__init__(rect, parent)
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)

    def itemChange(self, change, value):
        if (
            change == QtWidgets.QGraphicsItem.ItemPositionChange
            and self.scene()
        ):
            return QtCore.QPointF(value.x(), self.pos().y())
        return super(HorizontalItem, self).itemChange(change, value)


class Widget(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.setScene(QtWidgets.QGraphicsScene(self))
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        brush = QtWidgets.QApplication.palette().brush(QtGui.QPalette.Window)
        self.setBackgroundBrush(brush)

        rect_item = HorizontalItem(
            QtCore.QRectF(QtCore.QPointF(), QtCore.QSizeF(40, 80))
        )
        rect_item.setBrush(QtGui.QBrush(QtGui.QColor("red")))
        self.scene().addItem(rect_item)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.setFixedSize(640, 480)
    w.show()
    sys.exit(app.exec_())

В следующем коде есть пример, аналогичный тому, что вы хотите:

from PyQt5 import QtCore, QtGui, QtWidgets


class HorizontalItem(QtWidgets.QGraphicsRectItem):
    def __init__(self, rect, parent=None):
        super(HorizontalItem, self).__init__(rect, parent)
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)

    def itemChange(self, change, value):
        if (
            change == QtWidgets.QGraphicsItem.ItemPositionChange
            and self.scene()
        ):
            return QtCore.QPointF(value.x(), self.pos().y())
        return super(HorizontalItem, self).itemChange(change, value)


class Widget(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.setScene(QtWidgets.QGraphicsScene(self))
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        brush = QtWidgets.QApplication.palette().brush(QtGui.QPalette.Window)
        self.setBackgroundBrush(brush)
        self.setFixedSize(640, 480)

        size = self.mapToScene(self.viewport().rect()).boundingRect().size()
        r = QtCore.QRectF(QtCore.QPointF(), size)
        self.setSceneRect(r)

        rect = QtCore.QRectF(
            QtCore.QPointF(), QtCore.QSizeF(0.8 * r.width(), 80)
        )
        rect.moveCenter(r.center())
        rect_item = self.scene().addRect(rect)
        rect_item.setBrush(QtGui.QBrush(QtGui.QColor("salmon")))
        item = HorizontalItem(
            QtCore.QRectF(
                rect.bottomLeft() + QtCore.QPointF(0, 20), QtCore.QSizeF(20, 40)
            )
        )
        item.setBrush(QtGui.QBrush(QtGui.QColor("red")))
        self.scene().addItem(item)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...