python-3.x - 添加属性 QtCore.Qt.FramelessWindowHint 后如何从边缘调整窗口大小
问题描述
晚安。我已经看到一些具有新的无边框设计的程序,但您仍然可以使用调整大小。目前我知道要删除我们使用的pyqt程序的边框:QtCore.Qt.FramelessWindowHint
而改变窗口大小的方法是使用 QSizeGrip。但是我们怎样才能调整一个没有边框的窗口呢?
这是我用来删除窗口边框的代码,但之后我还没有找到有关如何在 pyqt5 中执行此操作的信息。我希望你能帮助我举例说明如何解决这个问题
from PyQt5.QtWidgets import QMainWindow,QApplication
from PyQt5 import QtCore
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
app = QApplication([])
m = Main()
m.show()
m.resize(800,600)
app.exec_()
解决方案
如果您使用 QMainWindow,您可以添加一个 QStatusBar(它会自动添加一个 QSizeGrip),只需调用statusBar()
:
如果状态栏不存在,此函数创建并返回一个空的状态栏。
否则,您可以手动添加夹点,它们的交互会根据它们的位置自动完成。在下面的示例中,我添加了 4 个夹点,每个角一个,然后在每次调整窗口大小时移动它们。
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.gripSize = 16
self.grips = []
for i in range(4):
grip = QSizeGrip(self)
grip.resize(self.gripSize, self.gripSize)
self.grips.append(grip)
def resizeEvent(self, event):
QMainWindow.resizeEvent(self, event)
rect = self.rect()
# top left grip doesn't need to be moved...
# top right
self.grips[1].move(rect.right() - self.gripSize, 0)
# bottom right
self.grips[2].move(
rect.right() - self.gripSize, rect.bottom() - self.gripSize)
# bottom left
self.grips[3].move(0, rect.bottom() - self.gripSize)
更新
根据评论,还需要调整侧面大小。为此,一个好的解决方案是创建一个行为类似于 QSizeGrip 的自定义小部件,但仅用于垂直/水平调整大小。
为了更好地实现,我更改了上面的代码,使用 agripSize
来构造一个“内部”矩形,并在此基础上更改所有小部件的几何形状,包括角和边。
在这里,您可以看到用于几何计算的“外部”矩形和“内部”矩形:
然后您可以为 QSizeGrip 小部件(浅蓝色)创建所有几何图形:
对于自定义侧面小部件:
from PyQt5 import QtCore, QtGui, QtWidgets
class SideGrip(QtWidgets.QWidget):
def __init__(self, parent, edge):
QtWidgets.QWidget.__init__(self, parent)
if edge == QtCore.Qt.LeftEdge:
self.setCursor(QtCore.Qt.SizeHorCursor)
self.resizeFunc = self.resizeLeft
elif edge == QtCore.Qt.TopEdge:
self.setCursor(QtCore.Qt.SizeVerCursor)
self.resizeFunc = self.resizeTop
elif edge == QtCore.Qt.RightEdge:
self.setCursor(QtCore.Qt.SizeHorCursor)
self.resizeFunc = self.resizeRight
else:
self.setCursor(QtCore.Qt.SizeVerCursor)
self.resizeFunc = self.resizeBottom
self.mousePos = None
def resizeLeft(self, delta):
window = self.window()
width = max(window.minimumWidth(), window.width() - delta.x())
geo = window.geometry()
geo.setLeft(geo.right() - width)
window.setGeometry(geo)
def resizeTop(self, delta):
window = self.window()
height = max(window.minimumHeight(), window.height() - delta.y())
geo = window.geometry()
geo.setTop(geo.bottom() - height)
window.setGeometry(geo)
def resizeRight(self, delta):
window = self.window()
width = max(window.minimumWidth(), window.width() + delta.x())
window.resize(width, window.height())
def resizeBottom(self, delta):
window = self.window()
height = max(window.minimumHeight(), window.height() + delta.y())
window.resize(window.width(), height)
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.mousePos = event.pos()
def mouseMoveEvent(self, event):
if self.mousePos is not None:
delta = event.pos() - self.mousePos
self.resizeFunc(delta)
def mouseReleaseEvent(self, event):
self.mousePos = None
class Main(QtWidgets.QMainWindow):
_gripSize = 8
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.sideGrips = [
SideGrip(self, QtCore.Qt.LeftEdge),
SideGrip(self, QtCore.Qt.TopEdge),
SideGrip(self, QtCore.Qt.RightEdge),
SideGrip(self, QtCore.Qt.BottomEdge),
]
# corner grips should be "on top" of everything, otherwise the side grips
# will take precedence on mouse events, so we are adding them *after*;
# alternatively, widget.raise_() can be used
self.cornerGrips = [QtWidgets.QSizeGrip(self) for i in range(4)]
@property
def gripSize(self):
return self._gripSize
def setGripSize(self, size):
if size == self._gripSize:
return
self._gripSize = max(2, size)
self.updateGrips()
def updateGrips(self):
self.setContentsMargins(*[self.gripSize] * 4)
outRect = self.rect()
# an "inner" rect used for reference to set the geometries of size grips
inRect = outRect.adjusted(self.gripSize, self.gripSize,
-self.gripSize, -self.gripSize)
# top left
self.cornerGrips[0].setGeometry(
QtCore.QRect(outRect.topLeft(), inRect.topLeft()))
# top right
self.cornerGrips[1].setGeometry(
QtCore.QRect(outRect.topRight(), inRect.topRight()).normalized())
# bottom right
self.cornerGrips[2].setGeometry(
QtCore.QRect(inRect.bottomRight(), outRect.bottomRight()))
# bottom left
self.cornerGrips[3].setGeometry(
QtCore.QRect(outRect.bottomLeft(), inRect.bottomLeft()).normalized())
# left edge
self.sideGrips[0].setGeometry(
0, inRect.top(), self.gripSize, inRect.height())
# top edge
self.sideGrips[1].setGeometry(
inRect.left(), 0, inRect.width(), self.gripSize)
# right edge
self.sideGrips[2].setGeometry(
inRect.left() + inRect.width(),
inRect.top(), self.gripSize, inRect.height())
# bottom edge
self.sideGrips[3].setGeometry(
self.gripSize, inRect.top() + inRect.height(),
inRect.width(), self.gripSize)
def resizeEvent(self, event):
QtWidgets.QMainWindow.resizeEvent(self, event)
self.updateGrips()
app = QtWidgets.QApplication([])
m = Main()
m.show()
m.resize(240, 160)
app.exec_()
推荐阅读
- java - 在 python 中将 base64 解码字符串转换为列表不会产生与 Java 数组输出相同的结果
- c++ - 如何编写以下问题 C++ 的 TMP 代码
- ios - 左上角问题中的 Swiftui Google Maps 用户标记
- branch.io - 首次安装应用时,Branch deeplink 不会将参数传递给 Android 应用
- javascript - 使用服务器端处理和页码显示列表
- javascript - HTML 文件输入 - 检测空文件夹
- reactjs - 在 youtube 嵌入视频上显示自动播放切换按钮
- android - 选中 RadioButton 时启用视图
- python - 如何在 Python 中以彩色二维直方图绘制二维数组?
- r - TwoSampleMR (R-package) 中的协调过程中出错