2015-08-31 94 views
8

我正在使用PyQt5實現一個python應用程序,並且在使用QScrollArea時遇到了一些問題。這是我的應用程序的佈局:Qt.ScrollBarAsNeeded在實際需要時不顯示滾動條

enter image description here

它是由2 QScrollArea(左和右窗格)和QMdiArea(中心部件)排列成QHBoxLayout。當我通過單擊控件來展開左窗格上的小部件時,QScrollAreaQWidget的高度大於QScrollArea本身的高度,滾動條顯示(如預期),但它與QScrollArea的內容重疊。要解決這個問題,我重新實現了resizeEvent添加必要的空間用於滾動條(直到此時一切正常。

enter image description here

現在,當我手動調整的主窗口,在左側窗格中得到更多的空間和滾動條應該消失(但事實並非如此),它重疊面板的部件:

enter image description here

我也試過手動切換滾動條的可見性(收到resizeEvent時):當我這樣做,我可以成功隱藏t他滾動條,但然後我不能再顯示它(無論我是否在滾動條上調用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中的小部件。

有人問之前,我已經嘗試做這樣的事情:

def resizeEvent(self, resizeEvent): 
    if self.viewport().height() < self.widget().height(): 
     self.setFixedWidth(Pane.MinWidth + 18) 
     scrollbar = self.verticalScrollbar() 
     scrollbar.setVisible(True) 
     self.setVerticalScrollBar(scrollbar) ## APP CRASH 
    else: 
     self.setFixedWidth(Pane.MinWidth) 
     #self.verticalScrollBar().hide() 

導致我的應用程序崩潰。 我希望有人已經面臨這個問題,並能夠幫助我。

編輯:我使用PyQt5.5編譯Qt5.5下OSX優勝美地10.10.4使用鐺。

+0

首先嚐試設置'setWidgetResizable'真爲你scrollArea –

+0

它已經被設置爲真,所以我想這個問題是其他地方 –

回答

3

對於我來說,一切似乎都按預期工作,而不需要任何解決方法。但是,我強烈懷疑您的真實代碼中還存在其他限制,您尚未在您的問題中發現這些限制。

UPDATE

下面是一個簡單的例子,調整其大小scrollareas時顯示滾動條/隱藏:

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_()) 
+0

謝謝,我會盡快嘗試 –

+0

我試過你的代碼,問題依然存在:http://i.imgur.com/O2o0iil.png 。你在哪個平臺上試過這個代碼?也許這是一個OSX唯一的問題。 –

+0

@DanielePantaleone。是的,我懷疑還有其他因素。我在Linux上,我無法在OSX上測試。你可能應該編輯你的問題,以清楚你正在使用哪些特定版本的OSX和Qt。如果你添加了一個最簡單的例子來爲你在OSX上重現問題,那麼它也會有很大幫助:也許只是一個包含一個小部件的'QScrollArea'。 – ekhumoro