我正在开发一个自定义小部件(继承自 QWidget)以用作控件。如何将小部件的纵横比固定为正方形,但在垂直和水平空间都允许的情况下仍允许布局管理器调整其大小?
我知道我可以设置 QPainter 的视口,使其仅在中央正方形区域中绘制,但这仍然允许用户单击绘制区域的任一侧。
似乎没有通用的方法可以在所有情况下保持小部件方形。您必须选择一项:
class MyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
policy.setHeightForWidth(True)
self.setSizePolicy(policy)
...
def heightForWidth(self, width):
return width
...
class MyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
...
def resizeEvent(self, e):
setMinimumWidth(height())
...
只要有这种可能性,这样的小部件就会保持正方形。
正如您所提到的,对于其他情况,您确实应该考虑更改视口。鼠标事件应该不是什么大问题,只需找到小部件的中心(将尺寸除以 2),找到min(width, height)
并从那里开始。您应该能够通过坐标验证鼠标事件。QMouseEvent.accept
仅当事件通过验证并且您使用了该事件时,才可以调用。
我会使用 BlaXpirit 的方法,但这是我以前使用过的替代方法。
如果您对自定义小部件进行子类化,resiseEvent()
您可以调整请求的大小以使其成为正方形,然后手动设置小部件的大小。
import sys
from PyQt4 import QtCore, QtGui
class CustomWidget(QtGui.QFrame):
def __init__(self, parent=None):
QtGui.QFrame.__init__(self, parent)
# Give the frame a border so that we can see it.
self.setFrameStyle(1)
layout = QtGui.QVBoxLayout()
self.label = QtGui.QLabel('Test')
layout.addWidget(self.label)
self.setLayout(layout)
def resizeEvent(self, event):
# Create a square base size of 10x10 and scale it to the new size
# maintaining aspect ratio.
new_size = QtCore.QSize(10, 10)
new_size.scale(event.size(), QtCore.Qt.KeepAspectRatio)
self.resize(new_size)
class MainWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
layout = QtGui.QVBoxLayout()
self.custom_widget = CustomWidget()
layout.addWidget(self.custom_widget)
self.setLayout(layout)
app = QtGui.QApplication(sys.argv)
window = MainWidget()
window.show()
sys.exit(app.exec_())