Python Qt.scrollbarasneed在显示';实际上需要什么
我正在使用PyQt5实现一个python应用程序,在使用QScrollara时遇到了一些问题。这是我的应用程序的布局: 它由2个Python Qt.scrollbarasneed在显示';实际上需要什么,python,qt,python-3.x,pyqt5,qscrollarea,Python,Qt,Python 3.x,Pyqt5,Qscrollarea,我正在使用PyQt5实现一个python应用程序,在使用QScrollara时遇到了一些问题。这是我的应用程序的布局: 它由2个QScrollArea(左窗格和右窗格)和一个QMdiArea(中心小部件)组成,它们排列成QHBoxLayout。当我通过单击控件展开左窗格上的小部件时,QScrollArea的QWidget的高度大于QScrollArea本身的高度,会出现滚动条(如预期的那样),但它与QScrollArea的内容重叠。为了解决这个问题,我重新实现了resizeEvent,为滚动条
QScrollArea
(左窗格和右窗格)和一个QMdiArea
(中心小部件)组成,它们排列成QHBoxLayout
。当我通过单击控件展开左窗格上的小部件时,QScrollArea
的QWidget
的高度大于QScrollArea
本身的高度,会出现滚动条(如预期的那样),但它与QScrollArea
的内容重叠。为了解决这个问题,我重新实现了resizeEvent
,为滚动条添加了必要的空间(直到现在一切正常)
现在,当我手动调整主窗口的大小时,左窗格将获得更多的空间,滚动条将消失(但不会消失),并与窗格的小部件重叠:
我还尝试手动切换滚动条的可见性(当收到resizeEvent时):当我这样做时,我可以成功隐藏滚动条,但之后我无法再次显示它(无论我是否在滚动条上调用setVisible(True)
)。这将导致添加滚动条的空间,但滚动条丢失,窗格的内容不可滚动:
以下是窗格小部件的实现:
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)
这导致我的应用程序崩溃。
我希望有人已经面对这个问题,能够帮助我
编辑:我使用的是根据OSX Yosemite 10.10.4下的Qt5.5使用clang编译的PyQt5.5。对于我来说,一切似乎都像预期的那样工作,不需要任何变通方法。但是,我强烈怀疑您的真实代码中有其他约束,您在问题中没有透露 更新 下面是显示/隐藏滚动条时调整滚动区域大小的简单示例:
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_())
首先尝试将ScrollArea的
SetWidgetResizeable
设置为true。它已经设置为true,所以我想问题出在其他地方。我尝试了你的代码,但问题仍然存在:。你在哪个平台上尝试了代码?可能这只是OSX的问题。@DanielePantaleone。是的,我怀疑还有其他因素。我在Linux上,而且我无法在OSX上进行测试。您可能应该编辑您的问题,以明确您正在使用的OSX和Qt的特定版本。如果您添加了在OSX上重现问题的最简单示例,也会有很大帮助:即,可能只是一个包含一个小部件的qscrolrea
。我修改了您的代码,添加了1每个窗格的小部件(大于滚动区域)问题仍然存在。我将在未来几天在Linux下尝试。在Windows 8.1和Linux Ubuntu14.04上测试,问题仍然存在。@DanielePantaleone。测试什么?我刚刚在Windows上尝试了我的脚本,效果很好。具体来说,当垂直调整窗口大小时,小部件水平调整大小以适应为滚动条添加日期,并相应地重新包装它们的文本。
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_())