PyQt4 - 如何将滚动条添加到固定大小的选项卡式窗口中?

问题描述:

最简单的情况:如何向固定大小的选项卡式 GUI 窗口添加滚动条?

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

完整案例:我正在使用在每个选项卡式框架中具有不可缩放对象(场景)的 GUI,并且希望用户仍然能够向下拖动缩放窗口本身(其中场景中的对象不会缩放,而是在窗口拖动移动到它们时隐藏)并出现滚动条.这是我为帮助举例而编写的最小的工作代码:

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

我尝试了一些东西,但我使用的是 pyqt5,所以我修改了你的例子.我不确定这是否是您想要的:

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: