我正在尝试实现将放置在场景右侧的小部件(即席工具箱)。 它看起来应该像这样:
在移动和缩放视图时,存在将其正确放置在此处并保持相同大小和位置的问题。
小部件本身是QComboBox。我试图将其作为QGraphicsWidget放置在场景中,将ZValue设置为高数值并将其设置为QGraphicsLinearLayout。不幸的是,我无法将其对齐到左侧,并且我觉得我做错了方法。
这是草图:
from PySide2 import QtWidgets, QtCore, QtGui
import sys
def hex2QColor(color):
r = int(color[0:2], 16)
g = int(color[2:4], 16)
b = int(color[4:6], 16)
return QtGui.QColor(r, g, b)
class rotateGroupBox(QtWidgets.QGroupBox):
"""Create content to fill the widget"""
def __init__(self, parent=None):
super(rotateGroupBox, self).__init__(parent)
self.setTitle("Rotation")
self.l_rotate = QtWidgets.QSpinBox()
self.l_rotate.setRange(0, 360)
self.r_rotate = QtWidgets.QSpinBox()
self.r_rotate.setRange(0, 360)
self.l_label = QtWidgets.QLabel("Left: ")
self.r_label = QtWidgets.QLabel("Right: ")
layout = QtWidgets.QVBoxLayout()
l1 = QtWidgets.QHBoxLayout()
l1.setContentsMargins(0,0,0,0)
l1.addWidget(self.l_label)
l1.addWidget(self.l_rotate)
l2 = QtWidgets.QHBoxLayout()
l2.setContentsMargins(0, 0, 0, 0)
l2.addWidget(self.r_label)
l2.addWidget(self.r_rotate)
layout.addLayout(l1)
layout.addLayout(l2)
self.setLayout(layout)
class propertyBox(QtWidgets.QWidget):
def __init__(self, parent=None):
super(propertyBox, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.backgroundColor = hex2QColor("efefef")
self.foregroundColor = hex2QColor("333333")
self.borderRadius = 10
self.__mousePressPos = None
self.__mouseMovePos = None
self.draggable = True
self.dragging_threshould = 5
self.__mousePressPos = None
self.__mouseMovePos = None
gr1 = rotateGroupBox(self)
gr2 = rotateGroupBox(self)
gr3 = rotateGroupBox(self)
gr4 = rotateGroupBox(self)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(gr1)
layout.addWidget(gr2)
layout.addWidget(gr3)
layout.addWidget(gr4)
self.setLayout(layout)
def paintEvent(self, event):
# get current window size
s = self.size()
qp = QtGui.QPainter()
qp.begin(self)
#qp.setRenderHint(QtGui.QPainter.HighQualityAntialiasing, True)
qp.setPen(self.foregroundColor)
qp.setBrush(self.backgroundColor)
qp.drawRoundedRect(0, 0, s.width(), s.height(),
self.borderRadius, self.borderRadius)
qp.end()
class graphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(graphicsView, self).__init__(parent)
def wheelEvent(self, event):
factor = 1.41 ** (-event.delta() / 240)
self.scale(factor, factor)
global RAW
RAW = True
def mousePressEvent(self, event):
if event.button() & QtCore.Qt.RightButton:
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
else:
super(graphicsView, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
if event.button() & QtCore.Qt.RightButton:
self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag)
else:
super(graphicsView, self).mouseReleaseEvent(event)
app = QtWidgets.QApplication(sys.argv)
window = graphicsView()
window.resize(1000, 500)
scene = QtWidgets.QGraphicsScene()
window.setScene(scene)
box = scene.addWidget(propertyBox())
layout = QtWidgets.QGraphicsLinearLayout()
layout.setContentsMargins(0,0,0,0)
#layout.setAlignment(box, QtCore.Qt.AlignRight) # doesn't work
layout.addItem(box)
form = QtWidgets.QGraphicsWidget()
#form.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
form.setZValue(100000000)
form.setLayout(layout)
scene.addItem(form)
# Adding an item that should be overlapped by the property box
rect = QtWidgets.QGraphicsRectItem()
rect.setRect(0,0,200,200)
rect.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
scene.addItem(rect)
window.show()
sys.exit(app.exec_())
答案 0 :(得分:2)
一种可能的解决方案是使小部件成为viewport()的子级,而不是项的子级,因此场景的变换不会影响它。并在viewport()更改大小时调整位置:
from PySide2 import QtCore, QtGui, QtWidgets
class RotateGroupBox(QtWidgets.QGroupBox):
"""Create content to fill the widget"""
def __init__(self, parent=None):
super(RotateGroupBox, self).__init__(parent)
self.setTitle("Rotation")
self.l_rotate = QtWidgets.QSpinBox()
self.l_rotate.setRange(0, 360)
self.r_rotate = QtWidgets.QSpinBox()
self.r_rotate.setRange(0, 360)
self.l_label = QtWidgets.QLabel("Left: ")
self.r_label = QtWidgets.QLabel("Right: ")
layout = QtWidgets.QVBoxLayout(self)
l1 = QtWidgets.QHBoxLayout()
l1.setContentsMargins(0, 0, 0, 0)
l1.addWidget(self.l_label)
l1.addWidget(self.l_rotate)
l2 = QtWidgets.QHBoxLayout()
l2.setContentsMargins(0, 0, 0, 0)
l2.addWidget(self.r_label)
l2.addWidget(self.r_rotate)
layout.addLayout(l1)
layout.addLayout(l2)
class PropertyBox(QtWidgets.QWidget):
def __init__(self, parent=None):
super(PropertyBox, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.backgroundColor = QtGui.QColor("salmon")
self.foregroundColor = QtGui.QColor("red")
self.borderRadius = 10
gr1 = RotateGroupBox()
gr2 = RotateGroupBox()
gr3 = RotateGroupBox()
gr4 = RotateGroupBox()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(gr1)
layout.addWidget(gr2)
layout.addWidget(gr3)
layout.addWidget(gr4)
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(self.foregroundColor)
painter.setBrush(self.backgroundColor)
rect = QtCore.QRectF(
QtCore.QPoint(),
self.size() - 0.5 * painter.pen().width() * QtCore.QSize(1, 1),
)
painter.drawRoundedRect(rect, self.borderRadius, self.borderRadius)
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.m_widgets = dict()
def wheelEvent(self, event):
factor = 1.41 ** (-event.delta() / 240)
self.scale(factor, factor)
def mousePressEvent(self, event):
if event.button() & QtCore.Qt.RightButton:
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
else:
super(GraphicsView, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
if event.button() & QtCore.Qt.RightButton:
self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag)
else:
super(GraphicsView, self).mouseReleaseEvent(event)
def addFixedWidget(self, widget, alignment):
widget.setParent(self.viewport())
self.m_widgets[widget] = alignment
def showEvent(self, event):
self._update_fixed_widgets()
super(GraphicsView, self).showEvent(event)
def resizeEvent(self, event):
self._update_fixed_widgets()
super(GraphicsView, self).resizeEvent(event)
def _update_fixed_widgets(self):
r = self.viewport().rect()
for w, a in self.m_widgets.items():
p = QtCore.QPoint()
if a & QtCore.Qt.AlignHCenter:
p.setX((r.width() - w.width()) / 2)
elif a & QtCore.Qt.AlignRight:
p.setX(r.width() - w.width())
if a & QtCore.Qt.AlignVCenter:
p.setY((r.height() - w.height()) / 2)
elif a & QtCore.Qt.AlignBottom:
p.setY(r.height() - w.height())
w.move(p)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
scene = QtWidgets.QGraphicsScene()
window = GraphicsView()
window.resize(1000, 500)
window.setScene(scene)
window.addFixedWidget(
PropertyBox(), QtCore.Qt.AlignRight | QtCore.Qt.AlignTop
)
rect = QtWidgets.QGraphicsRectItem()
rect.setRect(0, 0, 200, 200)
rect.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
scene.addItem(rect)
window.show()
sys.exit(app.exec_())