如何在运行时调整QSCrollBar的大小以更改其宽度?

2024-03-28 11:48:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在尝试用Qt(python)复制windows10开始菜单滚动条,但我不知道如何调整自定义QScrollBar的大小以在运行时更改其宽度

我尝试使用QScrollBar.resize方法(在enterEvent和leaveEvent中)调整它的大小,但它在“绘图区域”之外缩放小部件。 例如,我的滚动条设置为QScrollArea,当我尝试调整它的大小时,它不会占用更多的空间并移动小部件,相反,它只是在右侧缩放,我看不到它

目前我找到的唯一解决方案是使用样式表,但我无法将其设置为动画,以实现我所寻找的平滑调整大小

有一些代码可供您测试并查看错误:

from PySide2 import QtWidgets, QtCore
from functools import partial

class MyTE(QtWidgets.QPlainTextEdit):
    
    def __init__(self):
        super(MyTE, self).__init__()
        
        self.setVerticalScrollBar(MyScrollBar(self))
        self.setPlainText('mmmmmmmmmmmmmmmmmmmmmmmmmmmmm'*50)
        
class MyScrollBar(QtWidgets.QScrollBar):
    
    def __init__(self, parent=None):
        super(MyScrollBar, self).__init__(parent=parent)
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)        
        
    def enterEvent(self, event):
        super(MyScrollBar, self).enterEvent(event)
        
        self.resize(QtCore.QSize(4, self.height()))
        
    def leaveEvent(self, event):
        super(MyScrollBar, self).leaveEvent(event)
        
        self.resize(QtCore.QSize(10, self.height()))
        
wid = MyTE()
wid.show()

Tags: selfeventinit部件defparentsuperresize
2条回答

要使宽度更改更平滑,可以使用QVariantAnimation

from PySide2 import QtWidgets, QtCore


class MyTE(QtWidgets.QPlainTextEdit):
    def __init__(self):
        super(MyTE, self).__init__()

        self.setVerticalScrollBar(MyScrollBar(self))

        self.setPlainText("mmmmmmmmmmmmmmmmmmmmmmmmmmmmm" * 50)


class MyScrollBar(QtWidgets.QScrollBar):
    def __init__(self, parent=None):
        super(MyScrollBar, self).__init__(parent=parent)
        self._animation = QtCore.QVariantAnimation(
            startValue=10, endValue=25, duration=500
        )
        self._animation.valueChanged.connect(self.change_width)

    def enterEvent(self, event):
        super(MyScrollBar, self).enterEvent(event)
        self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
        self._animation.start()

    def leaveEvent(self, event):
        super(MyScrollBar, self).leaveEvent(event)
        self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
        self._animation.start()

    def change_width(self, width):
        self.setStyleSheet("""QScrollBar:vertical{ width: %dpx;}""" % (width,))


if __name__ == "__main__":

    app = QtWidgets.QApplication()
    wid = MyTE()
    wid.show()
    app.exec_()

.0我终于找到了不使用样式表的方法! 谢谢eyllanesc的回答,它给了我一个新的工作基础,我终于理解了Qt是如何处理大小调整的(我猜),我在一个叫做每次动画值改变的方法中使用setFixedSize

要工作,这需要有一个重写的sizeHint方法,该方法返回宽度的动画值。 此外,这也适用于Autodesk Maya(不幸的是,eyllanesc提供的解决方案由于未知原因无法在Maya中工作)

我的解决方案是:

from PySide2 import QtWidgets, QtCore, QtGui


class MyTE(QtWidgets.QPlainTextEdit):
    def __init__(self):
        super(MyTE, self).__init__()

        self.setVerticalScrollBar(MyScrollBar(self))

        self.setPlainText("mmmmmmmmmmmmmmmmmmmmmmmmmmmmm" * 50)
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)

    def resizeEvent(self, event):
        super(MyTE, self).resizeEvent(event)


class MyScrollBar(QtWidgets.QScrollBar):
    
    def __init__(self, parent=None):
        super(MyScrollBar, self).__init__(parent=parent)

        self._animation = QtCore.QVariantAnimation(
            startValue=10.0, endValue=25.0, duration=300
        )
        self._animation.valueChanged.connect(self.changeWidth)

        self._width = 10

    def enterEvent(self, event):
        super(MyScrollBar, self).enterEvent(event)
        self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
        self._animation.start()

    def leaveEvent(self, event):
        super(MyScrollBar, self).leaveEvent(event)
        self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
        self._animation.start()

    def sizeHint(self):
        """This must be overrided and return the width processed by the animation
        .. note:: In my final version I've replaced self.height() with 1 because it does not change 
        anything but self.height() was making my widget grow a bit each time.
        """
        return QtCore.QSize(self._width, self.height())

    def changeWidth(self, width):
        self._width = width  # This will allow us to return this value as the sizeHint width
        self.setFixedWidth(width) # This will ensure to scale the widget properly.


if __name__ == "__main__":

    app = QtWidgets.QApplication()
    wid = MyTE()
    wid.show()
    app.exec_()

注意:QVariantAnimation的起始值和结束值必须是浮点,如果它们是int类型,则动画将不起作用(适用于Qt 5.6.1(Maya 2018),但不适用于Qt 5.12.5(Maya 2020)

PS:如果有人询问我的最后一个小部件(窗口10开始菜单滚动条),请私下问我

相关问题 更多 >