【问题标题】:How to resize a window from the edges after adding the property QtCore.Qt.FramelessWindowHint添加属性 QtCore.Qt.FramelessWindowHint 后如何从边缘调整窗口大小
【发布时间】:2020-07-09 04:12:47
【问题描述】:

晚安。 我已经看到一些具有新的无边框设计的程序,但您仍然可以使用调整大小。 目前我知道要删除我们使用的 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_()

【问题讨论】:

    标签: python-3.x pyqt pyqt5


    【解决方案1】:

    如果您使用 QMainWindow,您可以通过调用 statusBar() 来添加 QStatusBar(它会自动添加 QSizeGrip):

    如果状态栏不存在,此函数会创建并返回一个空的状态栏。

    否则,您可以手动添加夹点,它们的交互会根据它们的位置自动完成。在下面的示例中,我添加了 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)
    

    更新

    基于 cmets,还需要调整大小。为此,一个好的解决方案是创建一个行为类似于 QSizeGrip 的自定义小部件,但仅用于垂直/水平调整大小。

    为了更好地实现,我更改了上面的代码,使用gripSize 构造一个“内部”矩形,并基于它更改所有小部件的几何形状,包括角和边。

    在这里您可以看到用于几何计算的“外部”矩形和“内部”矩形:

    然后您可以为 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_()
    

    【讨论】:

    • 那么,难道程序的所有边框都可以调整大小,而不仅仅是角落?
    • 很棒的工作!如果要删除边框,只需将夹点小部件向前移动,以便它们高于所有其他小部件。这可以通过在 def updateGrips(self) --- [grip.raise_(​​) for grip in self.sideGrips + self._cornerGrips] 的末尾设置此代码来完成 --- 然后您可以删除 self.setContentsMargins(*[ self.gripSize] * 4) 从该函数开始。
    • 你用什么软件来绘制可视化这些窗口?
    • @MansoorAhmedMemon 你用三张图片来显示边缘吗?我真的不记得了,但我可能用过inkscape
    猜你喜欢
    • 2020-12-10
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 2014-11-29
    • 1970-01-01
    • 2013-07-12
    相关资源
    最近更新 更多