Qt.ScrollBarAsNeeded公司在实际需要时不显示滚动条

2024-04-19 22:52:14 发布

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

我正在使用PyQt5实现一个python应用程序,在使用QScrollArea时遇到了一些问题。这是我的应用程序的布局:

enter image description here

它由2QScrollArea(左右窗格)和一个QMdiArea(中间小部件)组成,QHBoxLayout。当我通过单击控件展开左窗格上的小部件时,QScrollArea的高度大于QScrollArea本身的高度,滚动条会出现(如预期),但它与QScrollArea的内容重叠。为了解决这个问题,我重新实现了resizeEvent,为滚动条添加了必要的空间(到目前为止一切正常)。在

enter image description here

现在,当我手动调整主窗口的大小时,左窗格会获得更多的空间,滚动条应该会消失(但不会消失),并与窗格的小部件重叠:

enter image description here

我还尝试手动切换滚动条的可见性(当收到resizeEvent时):当我这样做时,我可以成功地隐藏滚动条,但之后我就不能再显示它了(不管我是否在滚动条上调用setVisible(True))。这会导致添加滚动条的空间,但滚动条丢失,并且窗格的内容不可滚动:

enter image description here

以下是窗格小部件的实现:

class Pane(QScrollArea):

    MinWidth = 186

    def __init__(self, alignment=0, parent=None):
        super().__init__(parent)
        self.mainWidget = QWidget(self)
        self.mainLayout = QVBoxLayout(self.mainWidget)
        self.mainLayout.setAlignment(alignment)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.setContentsMargins(0, 0, 0, 0)
        self.setFrameStyle(QFrame.NoFrame)
        self.setFixedWidth(Pane.MinWidth)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Ignored)
        self.setWidgetResizable(True)
        self.setWidget(self.mainWidget)

    def resizeEvent(self, resizeEvent):
        if self.viewport().height() < self.widget().height():
            self.setFixedWidth(Pane.MinWidth + 18)
            # THIS DOESN'T WORK
            #self.verticalScrollBar().show()
        else:
            self.setFixedWidth(Pane.MinWidth)
            #self.verticalScrollBar().hide()

    def addWidget(self, widget):
        self.mainLayout.addWidget(widget)

    def removeWidget(self, widget):
        self.mainLayout.removeWidget(widget)

    def update(self, *__args):
        for item in itemsInLayout(self.mainLayout):
            item.widget().update()
        super().update(*__args)

我想要实现的是非常简单的(但实际上它似乎没有那么简单):我希望只在需要时在我的左/右窗格小部件上动态显示垂直滚动条,并为滚动条添加必要的空间,这样它就不会与QScrollArea中的小部件重叠。在

在有人问我之前,我已经试过这样做了:

^{pr2}$

结果我的应用程序崩溃了。 我希望有人已经面对这个问题,并能帮助我。在

编辑:我使用的是PyQt5.5,在osxyosemite 10.10.4下使用clang编译的Qt5.5。在


Tags: self应用程序部件def空间updatewidgetpane
1条回答
网友
1楼 · 发布于 2024-04-19 22:52:14

对我来说,一切似乎都像预期的那样工作,不需要任何变通办法。但是,我强烈怀疑在您的实际代码中还有一些您没有在您的问题中显示的约束。在

更新

下面是一个简单的示例,它在显示/隐藏滚动条时调整滚动区域的大小:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        widget = QtWidgets.QWidget(self)
        layout = QtWidgets.QHBoxLayout(widget)
        self.mdi = QtWidgets.QMdiArea(self)
        self.leftScroll = Pane(
            QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft, self)
        self.rightScroll = Pane(
            QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft, self)
        layout.addWidget(self.leftScroll)
        layout.addWidget(self.mdi)
        layout.addWidget(self.rightScroll)
        self.setCentralWidget(widget)
        for scroll in self.leftScroll, self.rightScroll:
            for index in range(4):
                widget = QtWidgets.QTextEdit()
                widget.setText('one two three four five')
                scroll.addWidget(widget)

class Pane(QtWidgets.QScrollArea):
    MinWidth = 186

    def __init__(self, alignment=0, parent=None):
        super().__init__(parent)
        self.mainWidget = QtWidgets.QWidget(self)
        self.mainLayout = QtWidgets.QVBoxLayout(self.mainWidget)
        self.mainLayout.setAlignment(alignment)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.setContentsMargins(0, 0, 0, 0)
        self.setFrameStyle(QtWidgets.QFrame.NoFrame)
        self.setFixedWidth(Pane.MinWidth)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.setSizePolicy(QtWidgets.QSizePolicy.Maximum,
                           QtWidgets.QSizePolicy.Ignored)
        self.setWidgetResizable(True)
        self.setWidget(self.mainWidget)
        self.verticalScrollBar().installEventFilter(self)

    def addWidget(self, widget):
        self.mainLayout.addWidget(widget)

    def removeWidget(self, widget):
        self.mainLayout.removeWidget(widget)

    def eventFilter(self, source, event):
        if isinstance(source, QtWidgets.QScrollBar):
            if event.type() == QtCore.QEvent.Show:
                self.setFixedWidth(Pane.MinWidth + source.width())
            elif event.type() == QtCore.QEvent.Hide:
                self.setFixedWidth(Pane.MinWidth)
        return super(Pane, self).eventFilter(source, event)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 800, 300)
    window.show()
    sys.exit(app.exec_())

相关问题 更多 >