0

I want to move the QLabel with the mouse movement (not like Drag&drop, 'object' disappears while moving). Clicked - moved - released. I did it to some extent, but I ran into a problem. QLabel shrinks as I move it or even disappears (like shrinks to 0 width). How to fix it or what more correct approach to do it?

(self.label_pos is needed to keep the mouse position relative inside self.label)

Or its just monitor's refresh rate issue? But in photoshop's gradient editor, that little color stop isn't shrikns. It's choppy because of refresh rate, but always the same size.

This is what I want to see, recorded using a screen capture program. The same thing I see in Photoshop

This is what I see, recorded on my phone. The quality is poor, but the difference is clearly visible anyway.

This Photoshop is also captured on my phone, here the “object” remains the same size, as in the example made using screen capture

Here is code from eyllanesc's answer, 'object' still shrinks :(

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
    Currently your question is not clear, maybe an MCVE help you understand your question, read How to Ask and improve your question. Commented Apr 22, 2019 at 1:38

1 Answer 1

1

Instead of using a QLabel I recommend using QGraphicsRectItem with a QGraphicsView since it is specialized in this type of tasks:

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_()) 

If you want to just scroll horizontally then overwrite the itemChange method of 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_()) 

In the following code there is an example similar to what you want:

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_()) 
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for so complex answer, but the problem remains. Do you have this problem with this code?
@ЕгорКоханов What problem persists ?, explain yourself better
I have tried your variant, but "red rectangle" still shrinks in width like in my variant. I will add a gif to my post later with your code

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.