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

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


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


我目前找到的唯一解决方案是使用 StyleSheet,但我无法为其设置动画以实现我正在寻找的平滑调整大小。


有一些代码供您测试并查看问题所在:


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()


慕妹3242003
浏览 243回答 2
2回答

天涯尽头无女友

.0我终于找到了如何在不使用样式表的情况下做到这一点!感谢 eyllanesc 的回答,它给了我一个新的工作基础,我终于明白了 Qt 如何处理调整大小(我猜),我在setFixedSize每次动画值发生变化时使用名为 的方法。为了工作,这需要有一个重写的sizeHint方法来返回动画的宽度值。此外,这适用于 Autodesk Maya(不幸的是,eyllanesc 提供的解决方案在 Maya 中不起作用,原因未知)。我的解决方案是:from PySide2 import QtWidgets, QtCore, QtGuiclass 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 的 startValue 和 endValue 必须是 float,如果它们是 int 类型,则动画将不起作用(适用于 Qt 5.6.1 (Maya 2018),但不适用于 Qt 5.12.5 (Maya 2020)PS:如果有人对我的最终小部件(Window 10 开始菜单滚动条)感兴趣,请私下询问我。

料青山看我应如是

为了使宽度变化更平滑,您可以使用QVariantAnimation:from PySide2 import QtWidgets, QtCoreclass 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_()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python