1

Simplest case: How do you add a scrollbar to a tabbed GUI window of fixed size?

Full case: I'm working with a GUI with non-scaleable objects (scenes) in each tabbed frame, and would like the user to still be able to drag-scale the window down on itself (whereby the objects in the scene don't scale, but just get hidden as the window-drag moves over them) and a scroll bar appears. This is the minimal, working code that I've written to help exemplify:

import sys
from pyface.qt import QtGui, QtCore

class P1(QtGui.QWidget):
    def __init__(self, parent=None):
        super(P1, self).__init__(parent)
        layout = QtGui.QGridLayout(self)
        layout.setContentsMargins(20,20,20,20) #W,N,E,S
        layout.setSpacing(10)

        self.label_edge1 = QtGui.QLabel('')
        self.label_edge1.setMargin(5)
        self.label_edge1.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken)
        layout.addWidget(self.label_edge1, 0, 0, 10, 10)
        self.label_edge1.show()

        self.label_avgVol = QtGui.QLabel('Test')
        self.label_avgVol.setMargin(5)
        self.label_avgVol.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken)
        self.label_avgVol.setAlignment(QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter)
        layout.addWidget(self.label_avgVol, 0, 0, 1, 10)
        self.label_avgVol.show()

        self.button1 = QtGui.QPushButton("   Test   ", self)
        layout.addWidget(self.button1, 8, 8, 1, 1)
        self.button1.show()

class P2(QtGui.QWidget):    
    def __init__(self, parent=None):
        super(P2, self).__init__(parent)
        layout = QtGui.QGridLayout(self)
        layout.setContentsMargins(20,20,20,20)
        layout.setSpacing(10)

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setGeometry(50, 50, 500, 500) #(int x, int y, int w, int h)    

        tab1 = P1(self)
        tab2 = P2(self)

        self.tabs = QtGui.QTabWidget(self)
        self.tabs.resize(250,150)

        self.tabs.addTab(tab1, 'Page 1')
        self.tabs.addTab(tab2, 'Page 2')

        self.setWindowTitle('TABS + SCROLLBAR EXAMPLE')

        ### Section corrected to include accepted answer, in PyQt4:

        self.groupscroll = QtGui.QHBoxLayout()
        self.groupscrollbox = QtGui.QGroupBox()

        self.MVB = QtGui.QVBoxLayout()
        self.MVB.addWidget(self.tabs)

        scroll = QtGui.QScrollArea()
        widget = QtGui.QWidget(self)
        widget.setLayout(QtGui.QHBoxLayout())
        widget.layout().addWidget(self.groupscrollbox)
        scroll.setWidget(widget)
        scroll.setWidgetResizable(True)
        self.groupscrollbox.setLayout(self.MVB)
        self.groupscroll.addWidget(scroll)
        self.setCentralWidget(scroll)

        ###

        self.show()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    w = MainWindow()
    sys.exit(app.exec_())
ees
  • 327
  • 1
  • 17
  • Could you explain me better, what do you mean by scenes? – eyllanesc Mar 25 '18 at 05:04
  • @eyllanesc I'm talking about mayavi scenes, but could be anything that you don't want to scale down beyond its standard size. the answer by ymmx (below) got it exactly if you're still curious. – ees Mar 25 '18 at 13:48

1 Answers1

1

I tried something but I use pyqt5 so I modified a little your example. I'm not sure if it is what you wanted though:

import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class P1(QWidget):
    def __init__(self, parent=None):
        super(P1, self).__init__(parent)
        layout = QGridLayout(self)
        layout.setContentsMargins(20,20,20,20) #W,N,E,S
        layout.setSpacing(10)

        self.label_edge1 = QLabel('')
        self.label_edge1.setMargin(5)
        self.label_edge1.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        layout.addWidget(self.label_edge1, 0, 0, 10, 10)
        self.label_edge1.show()

        self.label_avgVol = QLabel('Test')
        self.label_avgVol.setFixedSize(600,600)

        self.label_avgVol.setMargin(5)
        self.label_avgVol.setFrameStyle(QFrame.Box | QFrame.Sunken)
        self.label_avgVol.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        layout.addWidget(self.label_avgVol, 0, 0, 1, 10)
        self.label_avgVol.show()

        self.button1 = QPushButton("   Test   ", self)
        layout.addWidget(self.button1, 8, 8, 1, 1)
        self.button1.show()

class P2(QWidget):
    def __init__(self, parent=None):
        super(P2, self).__init__(parent)
        layout = QGridLayout(self)
        layout.setContentsMargins(20,20,20,20)
        layout.setSpacing(10)

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setGeometry(50, 50, 500, 500) #(int x, int y, int w, int h)

        tab1 = P1(self)
        tab2 = P2(self)

        self.tabs = QTabWidget(self)
        self.tabs.resize(250,150)

        self.tabs.addTab(tab1, 'Page 1')
        self.tabs.addTab(tab2, 'Page 2')


        self.setWindowTitle('TABS + SCROLLBAR EXAMPLE')

        ### many trial and error attempts around this attempted setup:
        self.groupscroll = QHBoxLayout()
        self.groupscrollbox = QGroupBox()

        self.MVB = QVBoxLayout()
        self.MVB.addWidget(self.tabs)

        scroll = QScrollArea()
        widget = QWidget(self)
        widget.setLayout(QHBoxLayout())
        widget.layout().addWidget(self.groupscrollbox)
        scroll.setWidget(widget)
        scroll.setWidgetResizable(True)
        self.groupscrollbox.setLayout(self.MVB)
        self.groupscroll.addWidget(scroll)
        self.setCentralWidget(scroll)
        #self.sbar1 = QtGui.QScrollArea(tab1)
        #self.sbar1.setWidget(QtGui.QWidget())
        #self.sbar1.setEnabled(True)
        ###

        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    sys.exit(app.exec_())

it gives you the scroll bar (bottom and right) if the inner tab part is too big for the window size:

enter image description here

ymmx
  • 4,769
  • 5
  • 32
  • 64
  • I'm really digging your solution; this is exactly what I had in mind. I'll update my post above to include this for pyqt4 as well - thank you so much for your help – ees Mar 25 '18 at 13:45
  • I've run into a slight visual glitch with embedded scenes using you're code above. I've posted an example in a new topic at: https://stackoverflow.com/questions/49679827/pyqt4-scrollbar-interacts-incorrectly-with-embedded-scenes - any chance you know what's going on? – ees Apr 05 '18 at 19:14