2015-08-31 5 views
8

Я реализую приложение python с помощью PyQt5, и я столкнулся с некоторыми проблемами при использовании QScrollArea. Это расположение моего приложения:Qt.ScrollBarAsNeeded не показывает полосу прокрутки, когда это действительно необходимо

enter image description here

Он состоит из 2 QScrollArea (левая и правая панель) и QMdiArea (центр виджета), расположенный в QHBoxLayout. Когда я расширяю виджеты на левой панели, нажимая на элементы управления, а высота QWidget из QScrollArea больше, чем высота самого 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() 

что приводит в моем приложении к сбою. Надеюсь, что кто-то уже столкнулся с этой проблемой и может мне помочь.

EDIT: Я использую PyQt5.5, составленный против Qt5.5 под OSX Yosemite 10.10.4, используя clang.

+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

Смежные вопросы