问题的提出
在GUI应用中,常常会遇到这样的问题,比如显示一幅大的图像,但显示区域有限,不能完整地显示整个图像,或者能展示界面的区域有限,但是界面中需要展现的控件、内容却很多,在限定的区域内无法全部展示。这个时候我们就需要区域是可以水平和(或)垂直方向可以滚动,以实现对整个图像或者所有控件的浏览。在PyQt中,提供滚动区控件QScrollArea来实现这个功能。
QScrollArea简介
QScrollArea滚动区域控件类提供了关于另一个窗口的滚动的视图,一个滚动区域通常用来显示一个子窗口。如果子窗口中的内容超过了显示窗口的大小,这时候QSrollArea就会自动提供滚动条,通过操作滚动条,用户就可以浏览整个图像或者是操控窗口中的所有控件。
QSrollArea可以给任何QWidget控件添加滚动条。
QScrollArea常用方法有:
- setWidget(): 设置控件为QScrollArea的子控件;
- takeWidget():删除QScrollArea的子控件;
- widget(): 返回QScrollArea的子控件;
- setWidgetResizable(): 设置为true,则滚动区域部件将自动调整,以避免可以不显示的滚动条,或者利用额外的空间;
- widgetResizable(): 获得区域里的控件是否自动可调的设置;
- ensureVisible(): 确保一定区域可见,必要时滚动;
- ensureWidgetVisible(): 确保指定的控件widget可见,必要时滚动;
QScrollArea类继承关系:

测试QScrollArea
创建文件qscrollarea.py, 水平设置两个滚动区域,分别演示图像滚动显示和控件滚动。完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | import sys,os from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtWidgets import (QApplication, QWidget, QSplitter, QVBoxLayout, QGroupBox, QScrollArea, QRadioButton, QCheckBox, QLabel) from PyQt5.QtGui import QPixmap,QPalette from PyQt5.QtCore import Qt class DemoScrollArea(QWidget): def __init__(self, parent=None): super(DemoScrollArea, self).__init__(parent) # 设置窗口标题 self.setWindowTitle('实战PyQt5: QScrollArea Demo!') # 设置窗口大小 self.resize(480, 360) self.initUi() def initUi(self): mainLayout = QVBoxLayout(self) hSplitter = QSplitter(Qt.Horizontal) saLeft = QScrollArea(self) disp_img = QLabel(self) disp_img.setPixmap(QPixmap(os.path.dirname(__file__) + '/trp.jpg')) saLeft.setBackgroundRole(QPalette.Dark) saLeft.setWidget(disp_img) saRight = QScrollArea(self) #滚动区域的Widget scrollAreaWidgetContents = QWidget() vLayout = QVBoxLayout(scrollAreaWidgetContents) vLayout.addWidget(self.createFirstExclusiveGroup()) vLayout.addWidget(self.createSecondExclusiveGroup()) vLayout.addWidget(self.createNonExclusiveGroup()) scrollAreaWidgetContents.setLayout(vLayout) saRight.setWidget(scrollAreaWidgetContents) hSplitter.addWidget(saLeft) hSplitter.addWidget(saRight) mainLayout.addWidget(hSplitter) self.setLayout(mainLayout) def createFirstExclusiveGroup(self): groupBox = QGroupBox('Exclusive Radio Buttons', self) radio1 = QRadioButton('&Radio Button 1', self) radio1.setChecked(True) radio2 = QRadioButton('R&adio button 2', self) radio3 = QRadioButton('Ra&dio button 3', self) vLayout = QVBoxLayout(groupBox) vLayout.addWidget(radio1) vLayout.addWidget(radio2) vLayout.addWidget(radio3) vLayout.addStretch(1) groupBox.setLayout(vLayout) return groupBox def createSecondExclusiveGroup(self): groupBox = QGroupBox('E&xclusive Radio Buttons', self) groupBox.setCheckable(True) groupBox.setChecked(True) radio1 = QRadioButton('Rad&io button1', self) radio1.setChecked(True) radio2 = QRadioButton('Radi&o button2', self) radio3 = QRadioButton('Radio &button3', self) chkBox = QCheckBox('Ind&ependent checkbox', self) vLayout = QVBoxLayout(groupBox) vLayout.addWidget(radio1) vLayout.addWidget(radio2) vLayout.addWidget(radio3) vLayout.addWidget(chkBox) vLayout.addStretch(1) groupBox.setLayout(vLayout) return groupBox def createNonExclusiveGroup(self): groupBox = QGroupBox('No-Exclusive Checkboxes', self) groupBox.setFlat(True) chBox1 = QCheckBox('&Checkbox 1') chBox2 = QCheckBox('C&heckbox 2') chBox2.setChecked(True) tristateBox = QCheckBox('Tri-&state buttton') tristateBox.setTristate(True) tristateBox.setCheckState(Qt.PartiallyChecked) vLayout = QVBoxLayout(groupBox) vLayout.addWidget(chBox1) vLayout.addWidget(chBox2) vLayout.addWidget(tristateBox) vLayout.addStretch(1) groupBox.setLayout(vLayout) return groupBox if __name__ == '__main__': app = QApplication(sys.argv) window = DemoScrollArea() window.show() sys.exit(app.exec()) |
运行结果如下图:

测试QScrollArea
本文知识点
- 使用滚动区域浏览较大的图像;
- 使用QSpliter 连调整两个区域的相对大小;
- 使用Qalette设置控件的背景颜色。
前一篇: 实战PyQt5: 048-工具箱控件QToolBox