限制子部件在父部件中的移动范围
Limit child widget move range in parent widget
我正在做拖放小部件功能。复制了网上的一段代码,重写了三个类 mousePressEvent, mouseReleaseEvent, mouseMoveEvent
当子控件移动到父控件的边框时,它将覆盖父控件的边框。我不希望它变成这样。我想保留父小部件的边框。有没有办法让子widget只在父widget的内容区域移动
我尝试了几种方法,但都失败了
第一:设置父控件布局的setContentsMargins属性
其二:设置父控件的padding
第三:设置子控件的边距
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()
父 QWidget 始终绘制在子 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_()
我正在做拖放小部件功能。复制了网上的一段代码,重写了三个类 mousePressEvent, mouseReleaseEvent, mouseMoveEvent
当子控件移动到父控件的边框时,它将覆盖父控件的边框。我不希望它变成这样。我想保留父小部件的边框。有没有办法让子widget只在父widget的内容区域移动
我尝试了几种方法,但都失败了
第一:设置父控件布局的setContentsMargins属性
其二:设置父控件的padding
第三:设置子控件的边距
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()
父 QWidget 始终绘制在子 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_()