2015-08-31 8 views
8

Ich implementiere eine Python-Anwendung mit PyQt5 und ich stieß auf einige Probleme bei der Verwendung einer QScrollArea. Dies ist das Layout meiner Anwendung:Qt.ScrollBarAsNeeded Scrollbar nicht anzeigen, wenn es tatsächlich benötigt wird

enter image description here

aus 2 QScrollArea zusammengesetzt ist (linke und rechte Fensterbereich) und einem QMdiArea (Mitte widget) angeordnet in einem QHBoxLayout. Wenn ich die Widgets auf der linken Seite durch Klicken auf die Steuerelemente erweitern, und die Höhe der QWidget der QScrollArea ist größer als dann die Höhe der QScrollArea selbst, wird die Bildlaufleiste angezeigt (wie erwartet), aber es überlappt den Inhalt der QScrollArea . Um dieses Problem zu beheben ich das resizeEvent Hinzufügen der notwendigen Raum für die Scrollbar neu implementiert (bis zu diesem Punkt alles funktioniert.

enter image description here

Nun, wenn ich das Hauptfenster manuell Größe ändern, wird dem linken Bereich mehr Platz und die Scrollbar verschwinden sollten (aber es funktioniert nicht) und es überlappt die Widgets der Scheibe:

enter image description here

ich habe auch versucht, die Sichtbarkeit der Scrollbar manuell zu wechseln (wenn das resizeEvent empfangen wird): wenn ich dies tun Kann ich mich erfolgreich verstecken Die Bildlaufleiste kann ich dann aber nicht nochmal anzeigen (egal ob ich setVisible(True) auf der Bildlaufleiste anrufe). Daraus ergibt sich der Raum für die Scrollbar hinzugefügt wird, aber die Scrollbar fehlt und der Inhalt der Scheibe ist nicht scrollbaren:

enter image description here

Hier ist die Implementierung der Scheibe Widget ist:

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) 

Was ich ist ziemlich einfach erreichen wollen (aber praktisch scheint es nicht so einfach): ich möchte dynamisch die vertikale Bildlaufleiste am linken/rechten Bereich Widgets zeigen nur dann, wenn sie gebraucht wird, und fügen sie den erforderlichen Platz für die Scrollbar, so dass es überlappt nicht die Widgets in QScrollArea.

Bevor jemand fragt, ich schon versucht, so etwas zu tun:

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

, die in meiner Anwendung führt zum Absturz bringen. Ich hoffe, dass jemand dieses Problem bereits erkannt hat und mir helfen kann.

EDIT: Ich verwende PyQt5.5 kompiliert gegen Qt5.5 unter OSX Yosemite 10.10.4 mit Clang. für mich

+0

zuerst versuchen, für Ihre scrollArea 'setWidgetResizable' auf true zu setzen –

+0

ist es bereits festgelegt zu True, also denke ich, das Problem ist woanders –

Antwort

3

Alles scheint, ohne dass für Abhilfen wie erwartet zu funktionieren. Ich vermute jedoch stark, dass es zusätzliche Einschränkungen in Ihrem echten Code gibt, die Sie in Ihrer Frage nicht angegeben haben.

UPDATE

Es folgt ein einfaches Beispiel, das die scrollareas ändert die Größe, wenn die Bildlaufleisten sind/versteckt gezeigt:

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

danke, ich werde es versuchen, sobald ich kann –

+0

Ich habe Ihren Code versucht, und das Problem besteht: http://i.imgur.com/O2o0iil.png . Auf welcher Plattform hast du den Code ausprobiert? vielleicht ist es nur ein OSX-Problem. –

+0

@DanielePantaleone. Ja, ich vermutete, dass andere Faktoren eine Rolle spielten. Ich bin auf Linux und kann nicht auf OSX testen. Sie sollten Ihre Frage wahrscheinlich bearbeiten, um zu verdeutlichen, welche spezifischen Versionen von OSX und Qt Sie verwenden. Es würde auch sehr helfen, wenn Sie das einfachste mögliche Beispiel hinzufügen würden, das das Problem für Sie auf OSX reproduziert: d. H. Vielleicht nur eine einzige 'QScrollArea' mit einem Widget. – ekhumoro