基本功能
第一个窗口
import sys
#这里我们提供必要的引用。基本控件位于pyqt5.qtwidgets模块中。
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == '__main__':
#每一pyqt5应用程序必须创建一个应用程序对象。sys.argv参数是一个列表,从命令行输入参数。
app = QApplication(sys.argv)
#QWidget部件是pyqt5所有用户界面对象的基类。他为QWidget提供默认构造函数。默认构造函数没有父类。
w = QWidget()
#resize()方法调整窗口的大小。这离是250px宽150px高
w.resize(250, 150)
#move()方法移动窗口在屏幕上的位置到x = 300,y = 300坐标。
w.move(300, 300)
#设置窗口的标题
w.setWindowTitle('Simple')
#显示在屏幕上
w.show()
#系统exit()方法确保应用程序干净的退出
#的exec_()方法有下划线。因为执行是一个Python关键词。因此,exec_()代替
sys.exit(app.exec_())
第二种创建方法
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI() #界面绘制交给InitUi方法
def initUI(self):
#设置窗口的位置和大小
self.setGeometry(300, 300, 300, 220)
#设置窗口的标题
self.setWindowTitle('Icon')
#设置窗口的图标,引用当前目录下的web.png图片
self.setWindowIcon(QIcon('web.png'))
#显示窗口
self.show()
if __name__ == '__main__':
#创建应用程序和对象
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
显示提示语
悬停显示
#前面需要包含
from PyQt5.QtWidgets import (QWidget, QToolTip,
QPushButton, QApplication)
from PyQt5.QtGui import QFont
#这种静态的方法设置一个用于显示工具提示的字体。我们使用10px滑体字体。
QToolTip.setFont(QFont('SansSerif', 10))
#创建一个提示,我们称之为settooltip()方法。我们可以使用丰富的文本格式
self.setToolTip('This is a <b>QWidget</b> widget')
#创建一个PushButton并为他设置一个tooltip
btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
#btn.sizeHint()显示默认尺寸
btn.resize(btn.sizeHint())
#移动窗口的位置
btn.move(50, 50)
关闭窗口
from PyQt5.QtCore import QCoreApplication
qbtn = QPushButton('Quit', self)
qbtn.clicked.connect(QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
消息框
关闭时,显示一个消息框确认
#加QMessageBox类
def closeEvent(self, event):
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
窗口显示在屏幕中间
#加QDesktopWidget类
#控制窗口显示在屏幕中心的方法
def center(self):
#获得窗口
qr = self.frameGeometry()
#获得屏幕中心点
cp = QDesktopWidget().availableGeometry().center()
#显示到屏幕中心
qr.moveCenter(cp)
self.move(qr.topLeft())
布局管理
框布局 Boxlayout
#加QHBoxLayout和QVBoxLayout
#创建一个水平布局
hbox = QHBoxLayout()
#添加伸展因子
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
表格布局 QGridLayout
#加QGridLayout
#创建网格
grid = QGridLayout()
self.setLayout(grid)
names = ['Cls', 'Bck', '', 'Close',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+']
positions = [(i,j) for i in range(5) for j in range(4)]
for position, name in zip(positions, names):
if name == '':
continue
button = QPushButton(name)
grid.addWidget(button, *position)
控件在网格中可以跨越多行
grid.addWidget(reviewEdit, 3, 1, 5, 1)
表示reviewEdit占了5行
菜单和工具栏
#继承的类为QMainWindow
from PyQt5.QtWidgets import QMainWindow, QApplication
class Example(QMainWindow):
状态栏
self.statusBar().showMessage('Ready')
菜单栏
from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
from PyQt5.QtGui import QIcon
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
#快捷方式
exitAction.setShortcut('Ctrl+Q')
#鼠标悬停提示
exitAction.setStatusTip('Exit application')
#终止程序
exitAction.triggered.connect(qApp.quit)
self.statusBar()
#创建一个菜单栏
menubar = self.menuBar()
#添加菜单
fileMenu = menubar.addMenu('&File')
#添加事件
fileMenu.addAction(exitAction)
工具栏
exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(qApp.quit)
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAction)
事件和信号
信号与槽
是Qt的核心机制,也是PyQt的核心机制
信号:是由对象或控件发射出去的消息。比如按钮的单击事件
槽:当单击按钮时,按钮就会向外部发送单击的消息,这些发送出去的信号需要一些代码来拦截,这些代码就是槽
槽本质上是一个函数或方法
信号可以理解为事件
槽可以理解为事件函数
import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn1 = QPushButton("Button 1", self)
btn1.move(30, 50)
btn2 = QPushButton("Button 2", self)
btn2.move(150, 50)
btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)
self.statusBar()
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Event sender')
self.show()
def buttonClicked(self):
sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
对话框
QInputDialog
from PyQt5.QtWidgets import (QWidget, QPushButton, QLineEdit,
QInputDialog, QApplication)
self.btn.clicked.connect(self.showDialog)
def showDialog(self):
text, ok = QInputDialog.getText(self, 'Input Dialog',
'Enter your name:')
if ok:
self.le.setText(str(text))
QFileDialog
打开文件
import sys
from PyQt5.QtWidgets import (QMainWindow, QTextEdit,
QAction, QFileDialog, QApplication)
from PyQt5.QtGui import QIcon
class Example(QMainWindow):
self.textEdit = QTextEdit()
self.setCentralWidget(self.textEdit)
self.statusBar()
openFile = QAction(QIcon('open.png'), 'Open', self)
openFile.setShortcut('Ctrl+O')
openFile.setStatusTip('Open new File')
openFile.triggered.connect(self.showDialog)
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(openFile)
def showDialog(self):
#第一个字符串参数是对话框的标题,第二个指定对话框的工作目录,
fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
#读取了选择的文件并将文件内容显示到了TextEdit控件
if fname[0]:
f = open(fname[0], 'r')
with f:
data = f.read()
self.textEdit.setText(data)
控件
QCheckBox
复选框
#创建复选框
cb = QCheckBox('Show title', self)
cb.move(20, 20)
cb.toggle()
cb.stateChanged.connect(self.changeTitle)
def changeTitle(self, state):
if state == Qt.Checked:
self.setWindowTitle('QCheckBox')
else:
self.setWindowTitle('')
Toggle button
开关按钮
#包含QPushButton
redb = QPushButton('Red', self)
redb.setCheckable(True)
redb.move(10, 10)
#通过clicked信号操作一个布尔值
redb.clicked[bool].connect(self.setColor)
def setColor(self, pressed):
source = self.sender()
if pressed:
val = 255
else: val = 0
if source.text() == "Red":
self.col.setRed(val)
elif source.text() == "Green":
self.col.setGreen(val)
else:
self.col.setBlue(val)
self.square.setStyleSheet("QFrame { background-color: %s }" %
self.col.name())
滑动条 QSlider
#含QSlider
sld = QSlider(Qt.Horizontal, self)
sld.setFocusPolicy(Qt.NoFocus)
sld.setGeometry(30, 40, 100, 30)
sld.valueChanged[int].connect(self.changeValue)
进度条QProgressBar
QProgressBar
from PyQt5.QtCore import QBasicTimer
#设置进度条
self.pbar = QProgressBar(self)
#设置时间
self.timer = QBasicTimer()
self.step = 0
#时间事件
def timerEvent(self, e):
if self.step >= 100:
self.timer.stop()
self.btn.setText('Finished')
return
self.step = self.step + 1
self.pbar.setValue(self.step)
def doAction(self):
if self.timer.isActive():
self.timer.stop()
self.btn.setText('Start')
else:
#两个参数:超时和对象将接收的事件
self.timer.start(100, self)
self.btn.setText('Stop')
日历控件 QCalendarWidget
cal = QCalendarWidget(self)
#如果我们从部件选择一个日期,点击[QDate]发出信号
cal.clicked[QDate].connect(self.showDate)
def showDate(self, date):
self.lbl.setText(date.toString())
QPixmap
是优化的显示图像在屏幕上
hbox = QHBoxLayout(self)
pixmap = QPixmap("icon.png")
lbl = QLabel(self)
lbl.setPixmap(pixmap)
hbox.addWidget(lbl)
self.setLayout(hbox)
文本框 QLineEdit
qle = QLineEdit(self)
qle.textChanged[str].connect(self.onChanged)
def onChanged(self, text):
self.lbl.setText(text)
self.lbl.adjustSize()
QSplitter
通过QSplitter,用户可以拖动子控件边界来调整子控件的尺寸
splitter1 = QSplitter(Qt.Horizontal)
splitter1.addWidget(topleft)
splitter1.addWidget(topright)
splitter2 = QSplitter(Qt.Vertical)
splitter2.addWidget(splitter1)
splitter2.addWidget(bottom)
hbox.addWidget(splitter2)
self.setLayout(hbox)
下拉列表 QComboBox
def initUI(self):
self.lbl = QLabel("Ubuntu", self)
combo = QComboBox(self)
combo.addItem("Ubuntu")
combo.addItem("Mandriva")
combo.addItem("Fedora")
combo.addItem("Arch")
combo.addItem("Gentoo")
combo.activated[str].connect(self.onActivated)
def onActivated(self, text):
self.lbl.setText(text)
self.lbl.adjustSize()
PyQt 拖拽
把一个文本从编辑框里拖到按钮上,更新按钮上的标签(文字)。
from PyQt5.QtWidgets import (QPushButton, QWidget,
QLineEdit, QApplication)
import sys
#在QPushButton上构造一个按钮实例
class Button(QPushButton):
def __init__(self, title, parent):
super().__init__(title, parent)
#激活组件的拖拽事件
self.setAcceptDrops(True)
#重构了dragEnterEvent()方法。设定好接受拖拽的数据类型(plain text)。
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()
#重构dropEvent()方法,更改按钮接受鼠标的释放事件的默认行为。
def dropEvent(self, e):
self.setText(e.mimeData().text())
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
#QLineEdit默认支持拖拽操作,所以我们只要调用setDragEnabled()方法使用就行了
edit = QLineEdit('', self)
edit.setDragEnabled(True)
edit.move(30, 65)
button = Button("Button", self)
button.move(190, 65)
self.setWindowTitle('Simple drag and drop')
self.setGeometry(300, 300, 300, 150)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
拖放按钮组件
from PyQt5.QtWidgets import QPushButton, QWidget, QApplication
from PyQt5.QtCore import Qt, QMimeData
from PyQt5.QtGui import QDrag
import sys
class Button(QPushButton):
def __init__(self, title, parent):
super().__init__(title, parent)
def mouseMoveEvent(self, e):
#劫持按钮的右键事件,左键的操作还是默认行为
if e.buttons() != Qt.RightButton:
return
#创建一个QDrag对象,用来传输MIME-based数据。
mimeData = QMimeData()
drag = QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
#拖放事件开始时,用到的处理函数式start().
dropAction = drag.exec_(Qt.MoveAction)
#左键点击按钮,会在控制台输出“press”。
def mousePressEvent(self, e):
super().mousePressEvent(e)
if e.button() == Qt.LeftButton:
print('press')
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setAcceptDrops(True)
self.button = Button('Button', self)
self.button.move(100, 65)
self.setWindowTitle('Click or Move')
self.setGeometry(300, 300, 280, 150)
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
position = e.pos()
self.button.move(position)
#在dropEvent()方法里,我们定义了按钮按下后和释放后的行为,获得鼠标移动的位置,然后把按钮放到这个地方。
e.setDropAction(Qt.MoveAction)
e.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
绘图
绘制文本
import sys
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor, QFont
from PyQt5.QtCore import Qt
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.text = u'\u041b\u0435\u0432 \u041d\u0438\u043a\u043e\u043b\u0430\
\u0435\u0432\u0438\u0447 \u0422\u043e\u043b\u0441\u0442\u043e\u0439: \n\
\u0410\u043d\u043d\u0430 \u041a\u0430\u0440\u0435\u043d\u0438\u043d\u0430'
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Draw text')
self.show()
#绘制工作在paintEvent的方法内部完成
def paintEvent(self, event):
qp = QPainter()
qp.begin(self)
self.drawText(event, qp)
qp.end()
def drawText(self, event, qp):
#定义一个画笔和一个字体用于绘制文本
qp.setPen(QColor(168, 34, 3))
qp.setFont(QFont('Decorative', 10))
#drawText()方法将文本绘制在窗体,显示在中心,rect()方法返回要更新的矩形区域。
qp.drawText(event.rect(), Qt.AlignCenter, self.text)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
画点
#每次改变窗口大小,重新得到一个绘图事件
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawPoints(qp)
qp.end()
def drawPoints(self, qp):
qp.setPen(Qt.red)
size = self.size()
for i in range(1000):
x = random.randint(1, size.width() - 1)
y = random.randint(1, size.height() - 1)
qp.drawPoint(x, y)
颜色
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawRectangles(qp)
qp.end()
def drawRectangles(self, qp):
col = QColor(0, 0, 0)
#定义一个使用十六进制符号颜色。
col.setNamedColor('#d4d4d4')
qp.setPen(col)
#设置了一个笔刷(Bursh)对象
qp.setBrush(QColor(200, 0, 0))
#drawRect()方法接受四个参数,前两个是起点的x,y坐标,后两个是矩形的宽和高。
qp.drawRect(10, 15, 90, 60)
QPen(画笔)
QPen是一个基本的图形对象。用于绘制线条、曲线和轮廓的矩形、椭圆、多边形或其他形状。
def drawLines(self, qp):
#创建一个QPen对象。颜色是黑色的。宽度设置为2像素,
pen = QPen(Qt.black, 2, Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(20, 40, 250, 40)
pen.setStyle(Qt.DashLine)
qp.setPen(pen)
qp.drawLine(20, 80, 250, 80)
pen.setStyle(Qt.CustomDashLine)
#定义了1像素的实线,4像素的空白,5像素实线,4像素空白
pen.setDashPattern([1, 4, 5, 4])
qp.setPen(pen)
qp.drawLine(20, 240, 250, 240)
QBrush(笔刷)
QBrush是一个基本的图形对象。它用于油漆的背景图形形状,如矩形、椭圆形或多边形
def drawBrushes(self, qp):
brush = QBrush(Qt.SolidPattern)
qp.setBrush(brush)
qp.drawRect(10, 15, 90, 60)
brush.setStyle(Qt.Dense1Pattern)
qp.setBrush(brush)
qp.drawRect(130, 15, 90, 60)