本文转载自:http://code.py40.com/pyqt5/

一、PyQt5基本功能

简单的例子

PyQt5是一种高级的语言,下面只有几行代码就能显示一个小窗口。底层已经实现了窗口的基本功能。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40.com PyQt5 tutorial In this example, we create a simple
window in PyQt5. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" 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_())

上面的示例代码在屏幕上显示一个小窗口。

应用程序的图标

应用程序图标是一个小的图像,通常在标题栏的左上角显示。在下面的例子中我们将介绍如何做pyqt5的图标。同时我们也将介绍一些新方法。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
py40 PyQt5 tutorial This example shows an icon
in the titlebar of the window. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" 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_())

前面的例子是在程序风格。Python编程语言支持程序和面向对象编程风格。Pyqt5使用OOP编程。

class Example(QWidget):

    def __init__(self):
super().__init__()
...

面向对象编程有三个重要的方面:类、变量和方法。这里我们创建一个新的类为Examle。Example继承自QWidget类。

显示提示语

在下面的例子中我们显示一个提示语

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This example shows a tooltip on
a window and a button. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import (QWidget, QToolTip,
QPushButton, QApplication)
from PyQt5.QtGui import QFont class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self):
#这种静态的方法设置一个用于显示工具提示的字体。我们使用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) self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Tooltips')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

运行程序,显示一个窗口

关闭窗口

关闭一个窗口可以点击标题栏上的X。在下面的例子中,我们将展示我们如何通过编程来关闭窗口。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This program creates a quit
button. When we press the button,
the application terminates. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtCore import QCoreApplication class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): qbtn = QPushButton('Quit', self)
qbtn.clicked.connect(QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50) self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

消息框

默认情况下,如果我们单击x按钮窗口就关门了。有时我们想修改这个默认的行为。例如我们在编辑器中修改了一个文件,当关闭他的时候,我们显示一个消息框确认。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
ZetCode PyQt5 tutorial This program shows a confirmation
message box when we click on the close
button of the application window. author: Jan Bodnar
website: zetcode.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Message box')
self.show() 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() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

我们关闭窗口的时候,触发了QCloseEvent。我们需要重写closeEvent()事件处理程序。

reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)

我们显示一个消息框,两个按钮:“是”和“不是”。第一个字符串出现在titlebar。第二个字符串消息对话框中显示的文本。第三个参数指定按钮的组合出现在对话框中。最后一个参数是默认按钮,这个是默认的按钮焦点。

if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()

我们处理返回值,如果单击Yes按钮,关闭小部件并终止应用程序。否则我们忽略关闭事件。

窗口显示在屏幕的中间

下面的脚本显示了如何在屏幕中心显示窗口。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This program centers a window
on the screen. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QWidget, QDesktopWidget, QApplication class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): self.resize(250, 150)
self.center() self.setWindowTitle('Center')
self.show() #控制窗口显示在屏幕中心的方法
def center(self): #获得窗口
qr = self.frameGeometry()
#获得屏幕中心点
cp = QDesktopWidget().availableGeometry().center()
#显示到屏幕中心
qr.moveCenter(cp)
self.move(qr.topLeft()) if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

QtGui,QDesktopWidget类提供了用户的桌面信息,包括屏幕大小。

二、PyQt5布局管理

PyQt5布局有两种方式,绝对定位和布局类

绝对定位

程序指定每个控件的位置和大小(以像素为单位)。

绝对定位有以下限制:

  • 如果我们调整窗口,控件的大小和位置不会改变
  • 在各种平台上应用程序看起来会不一样
  • 如果改变字体,我们的应用程序的布局就会改变
  • 如果我们决定改变我们的布局,我们必须完全重做我们的布局

下面的例子显示了一个绝对定位

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This example shows three labels on a window
using absolute positioning. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): lbl1 = QLabel('Zetcode', self)
lbl1.move(15, 10) lbl2 = QLabel('tutorials', self)
lbl2.move(35, 40) lbl3 = QLabel('for programmers', self)
lbl3.move(55, 70) self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Absolute')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

我们使用move()方法来控制控件的位置。

框布局 Boxlayout

我们使用QHBoxLayout和QVBoxLayout,来分别创建横向布局和纵向布局。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial In this example, we position two push
buttons in the bottom-right corner
of the window. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
QHBoxLayout, QVBoxLayout, QApplication) class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel") hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton) vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox) self.setLayout(vbox) self.setGeometry(300, 300, 300, 150)
self.setWindowTitle('Buttons')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在这个例子中,我们使用HBoxLayout和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类创建一个网格布局。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial In this example, we create a skeleton
of a calculator using a QGridLayout. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import (QWidget, QGridLayout,
QPushButton, QApplication) class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): 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) self.move(300, 150)
self.setWindowTitle('Calculator')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在我们的示例中,我们创建一个网格的按钮。

grid = QGridLayout()
self.setLayout(grid)

QGridLayout的实例被创建并设置应用程序窗口的布局。

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)

创建按钮并使用addWidget()方法添加到布局中。

评论的例子

控件可以在网格中跨越多个行或列。在下一个示例中,我们说明了这一点。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial In this example, we create a bit
more complicated window layout using
the QGridLayout manager. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit,
QTextEdit, QGridLayout, QApplication) class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): title = QLabel('Title')
author = QLabel('Author')
review = QLabel('Review') titleEdit = QLineEdit()
authorEdit = QLineEdit()
reviewEdit = QTextEdit() grid = QGridLayout()
grid.setSpacing(10) grid.addWidget(title, 1, 0)
grid.addWidget(titleEdit, 1, 1) grid.addWidget(author, 2, 0)
grid.addWidget(authorEdit, 2, 1) grid.addWidget(review, 3, 0)
grid.addWidget(reviewEdit, 3, 1, 5, 1) self.setLayout(grid) self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('Review')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

我们创建一个窗口,其中有三个标签,两个行编辑和一个文本编辑窗口小控件。然后使用QGridLayout完成布局。

grid = QGridLayout()
grid.setSpacing(10)

创建一个网格布局和设置组件之间的间距。

grid.addWidget(reviewEdit, 3, 1, 5, 1)

在添加一个小的控件到网格的时候,我们可以提供小部件的行和列跨。在例子中,reviewEdit控件跨度5行。

三、PyQt5菜单和工具栏

主窗口

QMainWindow 类提供了一个主要的应用程序窗口。你用它可以让应用程序添加状态栏,工具栏和菜单栏。

状态栏

状态栏用于显示状态信息。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This program creates a statusbar. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QMainWindow, QApplication class Example(QMainWindow): def __init__(self):
super().__init__() self.initUI() def initUI(self): self.statusBar().showMessage('Ready') self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Statusbar')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

你用QMainWindow创建状态栏的小窗口。

self.statusBar().showMessage('Ready')

QMainWindow类第一次调用statusBar()方法创建一个状态栏。后续调用返回的状态栏对象。showMessage()状态栏上显示一条消息。

菜单栏

菜单栏是常见的窗口应用程序的一部分。(Mac OS将菜单条不同。得到类似的结果,我们可以添加以下行:menubar.setNativeMenuBar(假)。)

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This program creates a menubar. The
menubar has one menu with an exit action. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
from PyQt5.QtGui import QIcon class Example(QMainWindow): def __init__(self):
super().__init__() self.initUI() def initUI(self): 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) self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Menubar')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在上面的例子中,我们创建一个菜单栏和一个菜单。这个菜单将终止应用程序。Ctrl + Q的行动是可访问的快捷方式。

exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')

QAction可以操作菜单栏,工具栏,或自定义键盘快捷键。上面三行,我们创建一个事件和一个特定的图标和一个“退出”的标签。然后,在定义该操作的快捷键。
第三行创建一个鼠标指针悬停在该菜单项上时的提示。

exitAction.triggered.connect(qApp.quit)

当我们点击菜单的时候,调用qApp.quit,终止应用程序。

工具栏

工具栏提供了一个快速访问的入口。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This program creates a toolbar.
The toolbar has one action, which
terminates the application, if triggered. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
from PyQt5.QtGui import QIcon class Example(QMainWindow): def __init__(self):
super().__init__() self.initUI() def initUI(self): 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) self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Toolbar')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在上面的例子中,我们创建一个简单的工具栏。工具栏有有一个按钮,点击关闭窗口。

exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(qApp.quit)

类似于上面的菜单栏的例子,我们创建一个QAction事件。该事件有一个标签、图标和快捷键。退出窗口的方法

把他们放在一起

在本节的最后一个例子中,我们将创建一个菜单条,工具栏和状态栏的小窗口

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial This program creates a skeleton of
a classic GUI application with a menubar,
toolbar, statusbar, and a central widget. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtWidgets import QMainWindow, QTextEdit, QAction, QApplication
from PyQt5.QtGui import QIcon class Example(QMainWindow): def __init__(self):
super().__init__() self.initUI() def initUI(self): textEdit = QTextEdit()
self.setCentralWidget(textEdit) exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close) self.statusBar() menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction) toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction) self.setGeometry(300, 300, 350, 250)
self.setWindowTitle('Main window')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

创建了一个窗口

textEdit = QTextEdit()
self.setCentralWidget(textEdit)

我们创建了一个QTextEdit,并把他设置为窗口的布局

四、PyQt5事件和信号

事件 Event

所有的GUI程序都是事件驱动的。事件主要由用户触发,但也可能有其他触发方式:例如网络连接、window manager或定时器。当我们调用QApplication的exec_()方法时会使程序进入主循环。主循环会获取并分发事件。

在事件模型中,有三个参与者:

  • 事件源
  • 事件对象
  • 事件接收者

事件源是状态发生变化的对象。它会生成事件。事件(对象)封装了事件源中状态的变动。事件接收者是要通知的对象。事件源对象将事件处理的工作交给事件接收者。

PyQt5有一个独特的signal&slot(信号槽)机制来处理事件。信号槽用于对象间的通信。signal在某一特定事件发生时被触发,slot可以是任何callable对象。当signal触发时会调用与之相连的slot。

信号槽 Signals & slots

这是一个使用信号槽的PyQt5例子。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
Py40 PyQt5 tutorial In this example, we connect a signal
of a QSlider to a slot of a QLCDNumber. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication) class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self) vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld) self.setLayout(vbox)
sld.valueChanged.connect(lcd.display) self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

这个例子中展示了一个QtGui.QLCDNumber和QtGui.QSlider。lcd的值会随着滑块的拖动而改变。

sld.valueChanged.connect(lcd.display)

在这里我们将滚动条的valueChanged信号连接到lcd的display插槽。

sender是发出信号的对象。receiver是接收信号的对象。slot(插槽)是对信号做出反应的方法。

重新实现事件处理器

在PyQt5中常通过重新实现事件处理器来处理事件。

#!/usr/bin/python3
# -*- coding: utf-8 -*- """
pyu40 PyQt5 tutorial In this example, we reimplement an
event handler. author: Jan Bodnar
website: py40.com
last edited: January 2015
""" import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Event handler')
self.show() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape:
self.close() if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在示例中我们重新实现了keyPressEvent()事件处理器。

def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape:
self.close()

我们按下Escape键会使程序退出。

事件发送者

有时需要知道信号是由哪个控件发出的。对此PyQt5提供了sender()方法。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we determine the event sender
object. author: py40.com
last edited: 2017年3月
""" 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_())

我们创建了两个按钮。在buttonClicked()方法中通过调用sender()方法来判断当前按下的是哪个按钮。

btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)

两个按钮连接到了同一个插槽。

def buttonClicked(self):

    sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')

我们通过调用sender()方法来判断信号源, 并将其名称显示在窗体的状态栏中。

五、PyQt5对话框

对话框窗口或对话框是现代GUI应用程序最不可或缺的一部分。一个对话框被定义为两个或两个以上的人之间的谈话。在计算机应用程序对话框窗口用于“交谈”应用程序。一个对话框用于输入数据,修改数据,更改应用程序设置等。

QInputDialog

QInputDialog提供了一种简单方便的对话框从用户得到一个值。输入值可以是字符串,一个数字,或一个项目从一个列表。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we determine the event sender
object. author: py40.com
last edited: 2017年3月
""" import sys
from PyQt5.QtWidgets import (QWidget, QPushButton, QLineEdit,
QInputDialog, QApplication) class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): self.btn = QPushButton('Dialog', self)
self.btn.move(20, 20)
self.btn.clicked.connect(self.showDialog) self.le = QLineEdit(self)
self.le.move(130, 22) self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Input dialog')
self.show() def showDialog(self): text, ok = QInputDialog.getText(self, 'Input Dialog',
'Enter your name:') if ok:
self.le.setText(str(text)) if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

这个例子显示一个按钮和一个文本框,用户点击按钮显示一个输入框,用户输入信息会显示在文本框中。

text, ok = QInputDialog.getText(self, 'Input Dialog',
'Enter your name:')

这行代码显示输入对话框。第一个字符串是一个对话框标题,第二个是对话框中的消息。对话框返回输入的文本和一个布尔值。点击Ok按钮,布尔值是True。

if ok:
self.le.setText(str(text))

对话框收到的文本消息会显示在文本框中

QColorDialog

QColorDialog显示一个用于选择颜色值的对话框。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we determine the event sender
object. author: py40.com
last edited: 2017年3月
""" import sys
from PyQt5.QtWidgets import (QWidget, QPushButton, QFrame,
QColorDialog, QApplication)
from PyQt5.QtGui import QColor class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): col = QColor(0, 0, 0) self.btn = QPushButton('Dialog', self)
self.btn.move(20, 20) self.btn.clicked.connect(self.showDialog) self.frm = QFrame(self)
self.frm.setStyleSheet("QWidget { background-color: %s }"
% col.name())
self.frm.setGeometry(130, 22, 100, 100) self.setGeometry(300, 300, 250, 180)
self.setWindowTitle('Color dialog')
self.show() def showDialog(self): col = QColorDialog.getColor() if col.isValid():
self.frm.setStyleSheet("QWidget { background-color: %s }"
% col.name()) if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

这个应用程序显示一个按钮和一个QFrame。QFrame的背景为黑色。通过QColorDialog,我们可以改变它的背景。

col = QColor(0, 0, 0) 

初始化QFrame的颜色为黑色

col = QColorDialog.getColor()

这一行代码弹出QColorDialog

if col.isValid():
self.frm.setStyleSheet("QWidget { background-color: %s }"
% col.name())

我们要先检查col的值。如果点击的是Cancel按钮,返回的颜色值是无效的。当颜色值有效时,我们通过样式表(style sheet)来改变背景颜色。

QFontDialog

QFontDialog对话框用以选择字体

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we determine the event sender
object. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QPushButton,
QSizePolicy, QLabel, QFontDialog, QApplication) class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): vbox = QVBoxLayout() btn = QPushButton('Dialog', self)
btn.setSizePolicy(QSizePolicy.Fixed,
QSizePolicy.Fixed) btn.move(20, 20) vbox.addWidget(btn) btn.clicked.connect(self.showDialog) self.lbl = QLabel('Knowledge only matters', self)
self.lbl.move(130, 20) vbox.addWidget(self.lbl)
self.setLayout(vbox) self.setGeometry(300, 300, 250, 180)
self.setWindowTitle('Font dialog')
self.show() def showDialog(self): font, ok = QFontDialog.getFont()
if ok:
self.lbl.setFont(font) if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在这个例子中,我们创建了一个按钮和一个标签,通过QFontDialog来改变标签的字体

font, ok = QFontDialog.getFont()

这一行代码弹出字体选择对话框,getFont()方法返回字体名称和ok参数,如果用户点击了ok他就是True,否则就是false

if ok:
self.label.setFont(font)

如果我们点击了ok,标签的字体就会被改变

QFileDialog

QFileDialog是一个让用户选择文件和目录的对话框,可用以选择打开或保存文件

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we determine the event sender
object. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QMainWindow, QTextEdit,
QAction, QFileDialog, QApplication)
from PyQt5.QtGui import QIcon class Example(QMainWindow): def __init__(self):
super().__init__() self.initUI() def initUI(self): 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) self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('File dialog')
self.show() def showDialog(self): fname = QFileDialog.getOpenFileName(self, 'Open file', '/home') if fname[0]:
f = open(fname[0], 'r') with f:
data = f.read()
self.textEdit.setText(data) if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

这个例子展示了一个菜单栏,中部TextEdit控件和一个状态栏。菜单项Open会显示用于选择文件的QtGui.QFileDialog对话框。选定文件的内容会加载到TextEdit控件中。

class Example(QMainWindow):

    def __init__(self):
super().__init__() self.initUI()

示例窗体继承自QMainWindow,因为我们要将TextEdit控件置于窗体中央。

fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')

弹出QFileDialog对话框,第一个字符串参数是对话框的标题,第二个指定对话框的工作目录,默认情况下文件筛选器会匹配所有类型的文件(*)

if fname[0]:
f = open(fname[0], 'r') with f:
data = f.read()
self.textEdit.setText(data)

读取了选择的文件并将文件内容显示到了TextEdit控件。

六、PyQt5控件

控件是构建应用程序的基本模块,PyQt5提供各种各样的控件,包括按钮、复选框、滑动条、列表框等。在这部分的教程中,我们将详细介绍几个常用的控件:QCheckBox,ToggleButton,QSlider,QProgressBar,QCalendarWidget。

QCheckBox

QCheckBox复选框控件,它有两个状态:打开和关闭,他是一个带有文本标签(Label)的控件。复选框常用于表示程序中可以启用或禁用的功能。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we determine the event sender
object. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import QWidget, QCheckBox, QApplication
from PyQt5.QtCore import Qt class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): cb = QCheckBox('Show title', self)
cb.move(20, 20)
cb.toggle()
cb.stateChanged.connect(self.changeTitle) self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('QCheckBox')
self.show() def changeTitle(self, state): if state == Qt.Checked:
self.setWindowTitle('QCheckBox')
else:
self.setWindowTitle('') if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在我们的示例中,我们将创建一个复选框,将切换窗口标题。

cb = QCheckBox('Show title', self)

这是QCheckBox的构造行数

cb.toggle()

我们有设置窗口标题,所以我们也必须检查复选框。默认情况下,没有设置窗口标题和也没有勾选复选框。

cb.stateChanged.connect(self.changeTitle)

我们将自定义的changeTitle()方法连接到stateChanged信号。这个方法会切换窗体的标题。

def changeTitle(self, state):

    if state == Qt.Checked:
self.setWindowTitle('QCheckBox')
else:
self.setWindowTitle('')

复选框的状态经由state参数传入changeTitle()方法。在勾选复选框时设置窗体标题,取消勾选时就将标题设为空字符串。

开关按钮 Toggle button

ToggleButton是QPushButton的一种特殊模式。它是一个有两种状态的按钮:按下与未按下。通过点击在这两种状态间来回切换。这种功能在某些场景会很实用。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we create three toggle buttons.
They will control the background color of a
QFrame. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
QFrame, QApplication)
from PyQt5.QtGui import QColor class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): self.col = QColor(0, 0, 0) redb = QPushButton('Red', self)
redb.setCheckable(True)
redb.move(10, 10) redb.clicked[bool].connect(self.setColor) greenb = QPushButton('Green', self)
greenb.setCheckable(True)
greenb.move(10, 60) greenb.clicked[bool].connect(self.setColor) blueb = QPushButton('Blue', self)
blueb.setCheckable(True)
blueb.move(10, 110) blueb.clicked[bool].connect(self.setColor) self.square = QFrame(self)
self.square.setGeometry(150, 20, 100, 100)
self.square.setStyleSheet("QWidget { background-color: %s }" %
self.col.name()) self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Toggle button')
self.show() 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()) if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

代码中我们创建了三个ToggleButton与一个QWidget。我们将QWidget的背景色设为黑色。ToggleButton会切换颜色值中的红色、绿色与蓝色部分。QWidget的背景颜色依赖于按下的按钮。

self.col = QColor(0, 0, 0)

这是初始黑颜色的值。

redb = QPushButton('Red', self)
redb.setCheckable(True)
redb.move(10, 10)

我们创建一个QPushButton并通过其setCheckable()方法来得到一个ToggleButton。

redb.clicked[bool].connect(self.setColor)

将clicked信号连接到用户自定义的方法。我们通过clicked信号操作一个布尔值。

if source.text() == "Red":
self.col.setRed(val)

我们得到了按下的按钮。

if source.text() == "Red":
self.col.setRed(val)

如果按下的是red按钮,我们要相应地更新颜色中的红包部分。

self.square.setStyleSheet("QFrame { background-color: %s }" %
self.col.name())

滑动条 QSlider

QSlider是一个带有简单滑块的控件。滑块可以前后拖动。我们可以通过拖动选择一个特定的值。有时使用滑动条比直接输入数字或使用旋转框更加自然。

在下面的例子中,我们会显示一个滑动条与一个标签,标签用于显示图片,并通过滑动条控件图片的显示 。

注意这里图片只能用ico格式的,png格式图片会显示不了。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example shows a QSlider widget. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QSlider,
QLabel, QApplication)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap class Example(QWidget): def __init__(self):
super().__init__() self.initUI() def initUI(self): sld = QSlider(Qt.Horizontal, self)
sld.setFocusPolicy(Qt.NoFocus)
sld.setGeometry(30, 40, 100, 30)
sld.valueChanged[int].connect(self.changeValue) self.label = QLabel(self)
self.label.setPixmap(QPixmap('audio.ico'))
self.label.setGeometry(160, 40, 80, 30) self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('QSlider')
self.show() def changeValue(self, value): if value == 0:
self.label.setPixmap(QPixmap('audio.ico'))
elif value > 0 and value <= 30:
self.label.setPixmap(QPixmap('min.ico'))
elif value > 30 and value < 80:
self.label.setPixmap(QPixmap('med.ico'))
else:
self.label.setPixmap(QPixmap('max.ico')) if __name__ == '__main__': app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

例子中我们模拟了一个音量控制。通过拖动滑块来改变标签上的图像。

sld = QSlider(Qt.Horizontal, self)

创建一个水平滑块

self.label = QLabel(self)
self.label.setPixmap(QPixmap('mute.png'))

创建了一个QLabel控件并为它设置了一个初始音量图像。

sld.valueChanged[int].connect(self.changeValue)

我们将valueChanged信号连接到自定义的changeValue()方法。

if value == 0:
self.label.setPixmap(QPixmap('mute.png'))
...

我们根据滑动条的值来设置标签的图像。在上面的代码中,当滑动条的值为0时我们为标签设置audio.ico图像。

进度条QProgressBar

一个进度条是一个显示任务进展的控件。QProgressBar控件提供了一个水平或垂直PyQt5工具包的进度条。程序员可以设置进度条的最小和最大值。默认值是0到99。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example shows a QProgressBar widget. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QProgressBar,
QPushButton, QApplication)
from PyQt5.QtCore import QBasicTimer class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self): self.pbar = QProgressBar(self)
self.pbar.setGeometry(30, 40, 200, 25) self.btn = QPushButton('Start', self)
self.btn.move(40, 80)
self.btn.clicked.connect(self.doAction) self.timer = QBasicTimer()
self.step = 0 self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('QProgressBar')
self.show() 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') if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

这个例子显示一个水平的进度条和一个按钮,用户通过点击按钮开始和停止进度条

self.pbar = QProgressBar(self)

QProgressBar的构造方法

self.timer = QtCore.QBasicTimer()

我们使用定时器timer来激活QProgressBar

self.timer.start(100, self)

我们调用start()方法启动一个计时器。这个方法有两个参数:超时和对象将接收的事件。

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)

每个QObject及其子类都有一个timerEvent()事件处理器。我们要重新实现这个事件处理器来响应定时器事件。

def doAction(self):

    if self.timer.isActive():
self.timer.stop()
self.btn.setText('Start') else:
self.timer.start(100, self)
self.btn.setText('Stop')

我们在doAction()方法中启动/停止定时器。

日历控件 QCalendarWidget

QCalendarWidget提供了一个基于月份的日历控件。它使用户以一种简单直观的方式来选择日期。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example shows a QCalendarWidget widget. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QCalendarWidget,
QLabel, QApplication)
from PyQt5.QtCore import QDate class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
cal = QCalendarWidget(self)
cal.setGridVisible(True)
cal.move(20, 20)
cal.clicked[QDate].connect(self.showDate) self.lbl = QLabel(self)
date = cal.selectedDate()
self.lbl.setText(date.toString())
self.lbl.move(130, 260) self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('Calendar')
self.show() def showDate(self, date):
self.lbl.setText(date.toString()) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

示例中创建了一个日历控件和一个标签控件。选择的日期会显示在标签控件中。

cal = QCalendarWidget(self)

QCalendarWidget被创建

cal.clicked[QDate].connect(self.showDate)

如果我们从部件选择一个日期,点击[QDate]发出信号。我们将这个信号连接到用户定义的showDate()方法。

def showDate(self, date):     

    self.lbl.setText(date.toString())

我们检索所选日期通过调用selectedDate()方法。然后我们将date对象转换为字符串,并将其设置为小部件的标签。

七、PyQt5控件2

在这里我们将继续介绍PyQt5控件。我们将介绍QPixmap、QLineEdit QSplitter,QComboBox。

QPixmap

QPixmap是用于处理图像的控件。是优化的显示图像在屏幕上。在我们的代码示例中,我们将使用QPixmap窗口显示一个图像。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we dispay an image
on the window. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QHBoxLayout,
QLabel, QApplication)
from PyQt5.QtGui import QPixmap class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
hbox = QHBoxLayout(self)
pixmap = QPixmap("icon.png") lbl = QLabel(self)
lbl.setPixmap(pixmap) hbox.addWidget(lbl)
self.setLayout(hbox) self.move(300, 200)
self.setWindowTitle('Red Rock')
self.show() if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在窗口上显示一个图片

pixmap = QPixmap("icon.png")

创建一个QPixmap 对象,它将传入的文件名作为参数。

lbl = QLabel(self)
lbl.setPixmap(pixmap)

我们将这个pixmap放到QLabel控件中。

文本框 QLineEdit

QLineEdit是用于输入或编辑单行文本的控件。它还有撤销重做、剪切复制和拖拽功能。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example shows text which
is entered in a QLineEdit
in a QLabel widget. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QLabel,
QLineEdit, QApplication) class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
self.lbl = QLabel(self)
qle = QLineEdit(self) qle.move(60, 100)
self.lbl.move(60, 40) qle.textChanged[str].connect(self.onChanged) self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('QLineEdit')
self.show() def onChanged(self, text):
self.lbl.setText(text)
self.lbl.adjustSize() if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

示例中展示了一个QLineEdit与一个QLabel。我们在QLineEdit中输入的文字会实时显示在QLabel控件中。

qle = QLineEdit(self)

创建QLineEdit

qle.textChanged[str].connect(self.onChanged)

文本框的内容发生改变的时候,会调用onChanged方法

def onChanged(self, text):

    self.lbl.setText(text)
self.lbl.adjustSize()

在onChanged()方法中我们将QLabel控件的文本设置为输入的内容。通过调用adjustSize()方法将QLabel控件的尺寸调整为文本的长度。

QSplitter

通过QSplitter,用户可以拖动子控件边界来调整子控件的尺寸。在下面的示例中,我们展示了三个由两个QSplitter组织的QFrame控件。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example shows
how to use QSplitter widget. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QFrame,
QSplitter, QStyleFactory, QApplication)
from PyQt5.QtCore import Qt class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
hbox = QHBoxLayout(self) topleft = QFrame(self)
topleft.setFrameShape(QFrame.StyledPanel) topright = QFrame(self)
topright.setFrameShape(QFrame.StyledPanel) bottom = QFrame(self)
bottom.setFrameShape(QFrame.StyledPanel) 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) self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('QSplitter')
self.show() def onChanged(self, text):
self.lbl.setText(text)
self.lbl.adjustSize() if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

示例中我们创建了三个QFrame与两个QSplitter。注意在某些主题中这些QSplitter可能会不可见。

topleft = QFrame(self)
topleft.setFrameShape(QFrame.StyledPanel)

我们使用一个风格框架为了看到QFrame小部件之间的界限。

splitter1 = QSplitter(Qt.Horizontal)
splitter1.addWidget(topleft)
splitter1.addWidget(topright)

我们创建一个QSplitter小部件和添加两个帧。

splitter2 = QSplitter(Qt.Vertical)
splitter2.addWidget(splitter1)

我们也可以将QSplitter添加到另一个QSplitter控件中。

下拉列表 QComboBox

QComboBox是允许用户从下拉列表中进行选择的控件。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example shows how to use
a QComboBox widget. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QLabel,
QComboBox, QApplication) class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() 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.move(50, 50)
self.lbl.move(50, 150) combo.activated[str].connect(self.onActivated) self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('QComboBox')
self.show() def onActivated(self, text):
self.lbl.setText(text)
self.lbl.adjustSize() if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

示例中展示了一个QComboBox与一个QLabel,QComboBox控件中有5个选项(Linux系统的几个发行版名称)。QLabel控件会显示QComboBox中选中的某个选项。

combo = QComboBox(self)
combo.addItem("Ubuntu")
combo.addItem("Mandriva")
combo.addItem("Fedora")
combo.addItem("Arch")
combo.addItem("Gentoo")

创建了一个有五个选项的QComboBox

combo.activated[str].connect(self.onActivated) 

当选中某个条目时会调用onActivated()方法。

def onActivated(self, text):

    self.lbl.setText(text)
self.lbl.adjustSize()

在方法中我们将QLabel控件的内容设置为选中的条目,然后调整它的尺寸。

八、PyQt5拖拽

在这部分PyQt5教程中,我们将讨论拖拽相关操作。

在计算机图形用户界面中,拖放的操作(或支持的作用)点击虚拟对象和拖动到另一个位置或到另一个虚拟对象。一般来说,它可以用于调用多种行动,或创建各种类型的两个抽象对象之间的关联。
拖放是图形用户界面的一部分。拖拽操作让用户直观地做复杂的事情。
通常,我们可以拖放两件事:数据或一些图形对象。如果我们把一个图像从一个应用程序到另一个地方,我们拖拽二进制数据。如果我们把一个标签在Firefox中并将其移动到另一个地方,我们拖拽一个图形组件。

简单拖放

在第一个示例中,我们有一个QLineEdit QPushButton。我们拖着纯文本的行编辑窗口小部件,然后放到按钮部件。按钮的标签会改变。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This is a simple drag and
drop example. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QPushButton, QWidget,
QLineEdit, QApplication) class Button(QPushButton):
def __init__(self, title, parent):
super().__init__(title, parent) self.setAcceptDrops(True) def dragEnterEvent(self, e): if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore() def dropEvent(self, e): self.setText(e.mimeData().text()) class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
edit = QLineEdit('', self)
edit.setDragEnabled(True)
edit.move(30, 65) button = Button("Button", self)
button.move(190, 65) self.setWindowTitle('Simple drag & drop')
self.setGeometry(300, 300, 300, 150) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()

这个列子演示了一个简单的拖拽操作

class Button(QPushButton):

    def __init__(self, title, parent):
super().__init__(title, parent) self.setAcceptDrops(True)

我们需要重新实现某些方法才能使QPushButton接受拖放操作。因此我们创建了继承自QPushButton的Button类。

self.setAcceptDrops(True)

使该控件接受drop(放下)事件。

def dragEnterEvent(self, e):

    if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()

首先我们重新实现了dragEnterEvent()方法,并设置可接受的数据类型(在这里是普通文本)。

def dropEvent(self, e):

    self.setText(e.mimeData().text()) 

通过重新实现dropEvent()方法,我们定义了在drop事件发生时的行为。这里我们改变了按钮的文字。

edit = QLineEdit('', self)
edit.setDragEnabled(True)

QLineEdit内置了对drag(拖动)操作的支持。我们只需要调用setDragEnabled()方法就可以了。

拖放一个按钮

在下面的示例中我们将演示如何对一个按钮控件进行拖放。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This is a simple drag and
drop example. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QApplication
from PyQt5.QtCore import Qt, QMimeData
from PyQt5.QtGui import QDrag class Button(QPushButton):
def __init__(self, title, parent):
super().__init__(title, parent) def mouseMoveEvent(self, e): if e.buttons() != Qt.RightButton:
return mimeData = QMimeData() drag = QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft()) dropAction = drag.exec_(Qt.MoveAction) def mousePressEvent(self, e): QPushButton.mousePressEvent(self, 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) e.setDropAction(Qt.MoveAction)
e.accept() if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()

在这个例子中,在窗口显示一个QPushButton 。如果用鼠标左键点击这个按钮会在控制台中输出’press’消息。鼠标右击进行拖动。

class Button(QPushButton):

    def __init__(self, title, parent):
super().__init__(title, parent)

我们从QPushButton派生了一个Button类,并重新实现了mouseMoveEvent()与mousePressEvent()方法。mouseMoveEvent()方法是拖放操作产生的地方。

if e.buttons() != Qt.RightButton:
return

在这里我们设置只在鼠标右击时才执行拖放操作。鼠标左击用于按钮的点击事件。

mimeData = QMimeData()

drag = QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())

QDrag提供了对基于MIME的拖放的数据传输的支持。

dropAction = drag.exec_(Qt.MoveAction)

Drag对象的exec_()方法用于启动拖放操作。

def mousePressEvent(self, e):

    QPushButton.mousePressEvent(self, e)

    if e.button() == Qt.LeftButton:
print('press')

鼠标左击按钮时我们会在控制台打印‘press’。注意我们也调用了父按钮的mousePressEvent()方法。否则会看不到按钮的按下效果。

position = e.pos()
self.button.move(position)

释放右键后调用dropEvent()方法中,即找出鼠标指针的当前位置,并将按钮移动过去。

e.setDropAction(Qt.MoveAction)
e.accept()

我们可以对指定的类型放弃行动。在我们的例子中它是一个移动动作。

九、PyQt5绘图

PyQt5绘画系统能够呈现矢量图形,图像,和大纲font-based文本。我们也可以在程序中调用系统api自定义绘图控件。

绘图要在paintEvent()方法中实现。在QPainter对象的begin()与end()方法间编写绘图代码。它会在控件或其他图形设备上进行低级的图形绘制。

绘制文本

我们先以窗体内Unicode文本的绘制为例。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we draw text in Russian azbuka. author: py40.com
last edited: 2017年3月
"""
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() 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))
qp.drawText(event.rect(), Qt.AlignCenter, self.text) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在我们的示例中,我们绘制一些Cylliric文本。文本垂直和水平对齐。

def paintEvent(self, event):
...

绘制工作在paintEvent的方法内部完成。

qp = QPainter()
qp.begin(self)
self.drawText(event, qp)
qp.end()

QPainter类负责所有的初级绘制。之间的所有绘画方法去start()和end()方法。实际的绘画被委托给drawText()方法。

qp.setPen(QColor(168, 34, 3))
qp.setFont(QFont('Decorative', 10))

在这里,我们定义一个画笔和一个字体用于绘制文本。

qp.drawText(event.rect(), Qt.AlignCenter, self.text)

drawText()方法将文本绘制在窗体,显示在中心

画点

点是可以绘制的最简单的图形对象。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In the example, we draw randomly 1000 red points
on the window. author: py40.com
last edited: 2017年3月
"""
import sys, random
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Points')
self.show() 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) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在这例子中,我们在窗口上随机绘制了1000个红点

qp.setPen(Qt.red)

设置画笔为红色,我们使用了预定义的Qt.red常量

size = self.size()

每次我们改变窗口的大小,生成一个 paint event 事件。我们得到的当前窗口的大小size。我们使用窗口的大小来分配点在窗口的客户区。

qp.drawPoint(x, y)

通过drawpoint绘制圆点

颜色

颜色是一个对象代表红、绿、蓝(RGB)强度值。有效的RGB值的范围从0到255。我们可以用不同的方法定义了一个颜色。最常见的是RGB十进制或十六进制值的值。我们也可以使用一个RGBA值代表红色,绿色,蓝色,透明度。我们添加一些额外的信息透明度。透明度值255定义了完全不透明,0是完全透明的,例如颜色是无形的。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example draws three rectangles in three
#different colours. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor, QBrush class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
self.setGeometry(300, 300, 350, 100)
self.setWindowTitle('Colours')
self.show() 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) qp.setBrush(QColor(200, 0, 0))
qp.drawRect(10, 15, 90, 60) qp.setBrush(QColor(255, 80, 0, 160))
qp.drawRect(130, 15, 90, 60) qp.setBrush(QColor(25, 0, 90, 200))
qp.drawRect(250, 15, 90, 60) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

实例中我们绘制了3个不同颜色的矩形

color = QColor(0, 0, 0)
color.setNamedColor('#d4d4d4')

在这里,我们定义一个使用十六进制符号颜色。

qp.setBrush(QColor(200, 0, 0))
qp.drawRect(10, 15, 90, 60)

我们为QPainter设置了一个笔刷(Bursh)对象并用它绘制了一个矩形。笔刷是用于绘制形状背景的基本图形对象。drawRect()方法接受四个参数,前两个是起点的x,y坐标,后两个是矩形的宽和高。这个方法使用当前的画笔与笔刷对象进行绘制。

QPen(画笔)

QPen是一个基本的图形对象。用于绘制线条、曲线和轮廓的矩形、椭圆、多边形或其他形状。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example we draw 6 lines using
different pen styles. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
self.setGeometry(300, 300, 280, 270)
self.setWindowTitle('Pen styles')
self.show() def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawLines(qp)
qp.end() def drawLines(self, qp):
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.DashDotLine)
qp.setPen(pen)
qp.drawLine(20, 120, 250, 120) pen.setStyle(Qt.DotLine)
qp.setPen(pen)
qp.drawLine(20, 160, 250, 160) pen.setStyle(Qt.DashDotDotLine)
qp.setPen(pen)
qp.drawLine(20, 200, 250, 200) pen.setStyle(Qt.CustomDashLine)
pen.setDashPattern([1, 4, 5, 4])
qp.setPen(pen)
qp.drawLine(20, 240, 250, 240) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

示例中我们画六行。线条勾勒出了六个不同的笔风格。有五个预定义的钢笔样式。我们也可以创建自定义的钢笔样式。最后一行使用一个定制的钢笔绘制风格。

pen = QPen(Qt.black, 2, Qt.SolidLine)

我们创建一个QPen对象。颜色是黑色的。宽度设置为2像素,这样我们可以看到笔风格之间的差异。Qt.SolidLine是预定义的钢笔样式。

pen.setStyle(Qt.CustomDashLine)
pen.setDashPattern([1, 4, 5, 4])
qp.setPen(pen)

这里我们定义了一个画笔风格。我们设置了Qt.CustomDashLine并调用了setDashPattern()方法,它的参数(一个数字列表)定义了一种风格,必须有偶数个数字;其中奇数表示绘制实线,偶数表示留空。数值越大,直线或空白就越大。这里我们定义了1像素的实线,4像素的空白,5像素实线,4像素空白。。。

QBrush(笔刷)

QBrush是一个基本的图形对象。它用于油漆的背景图形形状,如矩形、椭圆形或多边形。三种不同类型的刷可以:一个预定义的刷,一个梯度,或纹理模式。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial This example draws 9 rectangles in different
brush styles. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QBrush
from PyQt5.QtCore import Qt class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
self.setGeometry(300, 300, 355, 280)
self.setWindowTitle('Brushes')
self.show() def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawBrushes(qp)
qp.end() 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) brush.setStyle(Qt.Dense2Pattern)
qp.setBrush(brush)
qp.drawRect(250, 15, 90, 60) brush.setStyle(Qt.DiagCrossPattern)
qp.setBrush(brush)
qp.drawRect(10, 105, 90, 60) brush.setStyle(Qt.Dense5Pattern)
qp.setBrush(brush)
qp.drawRect(130, 105, 90, 60) brush.setStyle(Qt.Dense6Pattern)
qp.setBrush(brush)
qp.drawRect(250, 105, 90, 60) brush.setStyle(Qt.HorPattern)
qp.setBrush(brush)
qp.drawRect(10, 195, 90, 60) brush.setStyle(Qt.VerPattern)
qp.setBrush(brush)
qp.drawRect(130, 195, 90, 60) brush.setStyle(Qt.BDiagPattern)
qp.setBrush(brush)
qp.drawRect(250, 195, 90, 60) if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

示例中绘制九个不同的矩形

brush = QBrush(Qt.SolidPattern)
qp.setBrush(brush)
qp.drawRect(10, 15, 90, 60)

我们定义了一个笔刷对象,然后将它设置给QPainter对象,并调用painter的drawRect()方法绘制矩形。

十、PyQt5自定义控件

PyQt5包含种类丰富的控件。但能满足所有需求的控件库是不存在的。通常控件库只提供了像按钮、文本控件、滑块等最常用的控件。但如果需要某种特殊的控件,我们只能自己动手来实现。 自定义控件需要使用工具库提供的绘图工具,可能有两种方式:在已有的控件上进行拓展或从头开始创建自定义控件。

Burning widget(烧录控件)

这个控件可能会在Nero,K3B或其他CD/DVD烧录软件中见到。

# -*- coding: utf-8 -*-

"""
PyQt5 tutorial In this example, we create a custom widget. author: py40.com
last edited: 2017年3月
"""
import sys
from PyQt5.QtWidgets import (QWidget, QSlider, QApplication,
QHBoxLayout, QVBoxLayout)
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QFont, QColor, QPen class Communicate(QObject):
updateBW = pyqtSignal(int) class BurningWidget(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self): self.setMinimumSize(1, 30)
self.value = 75
self.num = [75, 150, 225, 300, 375, 450, 525, 600, 675] def setValue(self, value): self.value = value def paintEvent(self, e): qp = QPainter()
qp.begin(self)
self.drawWidget(qp)
qp.end() def drawWidget(self, qp): font = QFont('Serif', 7, QFont.Light)
qp.setFont(font) size = self.size()
w = size.width()
h = size.height() step = int(round(w / 10.0)) till = int(((w / 750.0) * self.value))
full = int(((w / 750.0) * 700)) if self.value >= 700: qp.setPen(QColor(255, 255, 255))
qp.setBrush(QColor(255, 255, 184))
qp.drawRect(0, 0, full, h)
qp.setPen(QColor(255, 175, 175))
qp.setBrush(QColor(255, 175, 175))
qp.drawRect(full, 0, till - full, h) else: qp.setPen(QColor(255, 255, 255))
qp.setBrush(QColor(255, 255, 184))
qp.drawRect(0, 0, till, h) pen = QPen(QColor(20, 20, 20), 1,
Qt.SolidLine) qp.setPen(pen)
qp.setBrush(Qt.NoBrush)
qp.drawRect(0, 0, w - 1, h - 1) j = 0 for i in range(step, 10 * step, step):
qp.drawLine(i, 0, i, 5)
metrics = qp.fontMetrics()
fw = metrics.width(str(self.num[j]))
qp.drawText(i - fw / 2, h / 2, str(self.num[j]))
j = j + 1 class Example(QWidget):
def __init__(self):
super().__init__() self.initUI() def initUI(self):
sld = QSlider(Qt.Horizontal, self)
sld.setFocusPolicy(Qt.NoFocus)
sld.setRange(1, 750)
sld.setValue(75)
sld.setGeometry(30, 40, 150, 30) self.c = Communicate()
self.wid = BurningWidget()
self.c.updateBW[int].connect(self.wid.setValue) sld.valueChanged[int].connect(self.changeValue)
hbox = QHBoxLayout()
hbox.addWidget(self.wid)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox) self.setGeometry(300, 300, 390, 210)
self.setWindowTitle('Burning widget')
self.show() def changeValue(self, value):
self.c.updateBW.emit(value)
self.wid.repaint() if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在示例中我们使用了滑块与一个自定义控件。自定义控件受滑块控制。控件显示了媒体介质的容量和剩余空间。该控件的最小值为1,最大值为750。在值超过700时颜色变为红色。这通常意味着超刻(即实际写入光盘的容量超过刻录盘片官方标称容量的一种操作)。

BurningWidget控件通过QHBoxLayout与QVBoxLayout置于窗体的底部。

class BurningWidget(QWidget):

    def __init__(self):
super().__init__()

烧录的控件,它基于QWidget

self.setMinimumSize(1, 30)

我们改变了控件的最小大小(高度),默认值为有点小。

font = QFont('Serif', 7, QFont.Light)
qp.setFont(font)

我们使用一个比默认要小的字体。

size = self.size()
w = size.width()
h = size.height() step = int(round(w / 10.0)) till = int(((w / 750.0) * self.value))
full = int(((w / 750.0) * 700))

控件采用了动态绘制技术。窗体越大,控件也随之变大;反之亦然。这也是我们需要计算自定义控件的载体控件(即窗体)尺寸的原因。till参数定义了需要绘制的总尺寸,它根据slider控件计算得出,是整体区域的比例值。full参数定义了红色区域的绘制起点。注意在绘制时为取得较大精度而使用的浮点数运算。

实际的绘制分三个步骤。黄色或红黄矩形的绘制,然后是刻度线的绘制,最后是刻度值的绘制。

metrics = qp.fontMetrics()
fw = metrics.width(str(self.num[j]))
qp.drawText(i-fw/2, h/2, str(self.num[j]))

我们使用字体度量来绘制文本。我们必须知道文本的宽度,以中心垂直线。

def changeValue(self, value):

    self.c.updateBW.emit(value)
self.wid.repaint()

当滑块发生移动时,changeValue()方法会被调用。在方法内我们触发了一个自定义的updateBW信号,其参数是当前滚动条的值。该值被用于计算Burning widget的容量值。然后对控件进行重绘。

pyqt5中文教程的更多相关文章

  1. director.js:客户端的路由---简明中文教程

    1.引子 最近学用director.js,那是相当的简单易学易使用.不过开始学的时候,搜搜过后,却没有发现相关的中文教程.于是决定硬啃E文,翻译备用的同时也当是给自己上课并加深对它的理解. direc ...

  2. Groovy中文教程(链接收藏)

    学习Gradle前,需要有一个Groovy语言的基础,以免被Groovy的语法困扰,反而忽略了Gradle的知识.这里有一个Groovy的简明中文教程文档,可以快速学习Groovy的一些语法:http ...

  3. webstorm的中文教程和技巧分享

    webstorm是一款前端javascript开发编辑的神器,此文介绍webstorm的中文教程和技巧分享.webstorm8.0.3中文汉化版下载:百度网盘下载:http://pan.baidu.c ...

  4. 读w3c中文教程对键盘事件解释的感想 -遁地龙卷风

    写这篇博文源于w3c中文教程对键盘事件的解释, onkeydown 某个键盘按键被按下 onkeypress 某个键盘按键被按下并松开 onkeyup 某个键盘按键被松开 可在实践中发现 只注册key ...

  5. wxPython中文教程入门实例

    这篇文章主要为大家分享下python编程中有关wxPython的中文教程,分享一些wxPython入门实例,有需要的朋友参考下     wxPython中文教程入门实例 wx.Window 是一个基类 ...

  6. Google Analytics统计代码GA.JS中文教程

    2010-12-06 11:07:08|  分类: java编程 |  标签:google  analytics  ga  js  代码  |举报|字号 订阅     Google Analytics ...

  7. 学习Nim语言.rar(nim语言中文教程下载)

    学习Nim语言 nim 语法上类似python ,是一门静态编译型语言,nim 使用空格缩进标示语句块的开始和结束, 喜欢python风格的程序员应该也会很容易适应和喜欢nim的风格. nim语言官方 ...

  8. PhpStorm中文教程

    PhpStorm中文教程 | 浏览:15972 | 更新:2014-06-10 21:14 1 2 3 4 5 分步阅读 PhpStorm是一款强大的IDE,非常适合于PHP开发人员及前端工程师.提供 ...

  9. Julia中文教程资源.txt

    Julia中文教程资源.txt 2016年3月28日 05:18:32 codegay 本文更新在这里: https://github.com/FGFW/julia-science-and-techn ...

  10. PuTTY 中文教程

    PuTTY 中文教程 更新记录 2006-11-29初步完成想写的这些东西 2007-06-11PuTTY 的最新版本到了0.6:修改了一下 SSH 隧道:添加了 SSH 反向隧道:添加了用 SSH ...

随机推荐

  1. 都用过@Autowired,但你知道它是怎么实现的吗

    前言 在使用Spring开发的时候,配置的方式主要有两种,一种是xml的方式,另外一种是 java config的方式.在使用的过程中java config,我们难免会与注解进行各种打交道,其中,我们 ...

  2. ASCLL编码器-算术运算符_四则与取模运算

    ASCLL编码器 public static void main(String[] args) { //字符类型变量 char c = 'a'; int i = 1; //字符类型和int类型计算 S ...

  3. 六、python基础知识之变量常量、索引取值和PEP8规范

    目录 一.变量与常量 1.什么是变量? 2.什么是常量? 变量的基本使用 变量使用的语法结构与底层原理 变量名的命名规范和命名风格 变量的命名风格 常量的基本使用 二.索引取值 三.PEP8规范 1. ...

  4. 企业微信集成openai实现ChatGPT机器人

    背景: 现在网上查资料,痛点太多了,什么广告,什么重复的,对于程序员的我来说,简直是无语 最近接触到ChatGpt,问了些技术问题,答的比某度好,甚至可以写代码,真的太棒了 因此想写个专门的机器人,给 ...

  5. Vue17 手机表单数据

    1)v-model.trim trim修饰符是去掉前后空格 2)type="number" v-model.number type="number":只能输入数 ...

  6. Seal 0.4 发布:软件供应链安全洞察更上一层楼!

    今天,我们很高兴宣布 Seal 0.4 已正式发布!在上一个版本中,Seal 完成了从单一产品到全链路平台的转变,通过全局视图帮助用户掌握软件开发生命周期各个环节的安全状况. 在 Seal 0.4 中 ...

  7. C# Replace:一个熟悉而又陌生的替换

    前言 Replace 的作用就是,通过指定内容的替换,返回一个新字符串. 返回值中,已将当前字符串中的指定 Unicode 字符或 String 的 所有匹配项,替换为指定的新的 Unicode 字符 ...

  8. 什么是Http? http和https的区别

    一.HTTP HTTP (HyperText Transfer Protocol),即超文本运输协议,是实现网络通信的一种规范 在计算机和网络世界有,存在不同的协议,如广播协议.寻址协议.路由协议等等 ...

  9. 大规模 IoT 边缘容器集群管理的几种架构-2-HashiCorp 解决方案 Nomad

    前文回顾 大规模 IoT 边缘容器集群管理的几种架构-0-边缘容器及架构简介 大规模 IoT 边缘容器集群管理的几种架构-1-Rancher+K3s ️Reference: IoT 边缘计算系列文章 ...

  10. 钓鱼攻击之:Flash 网页钓鱼

    钓鱼攻击之:Flash 网页钓鱼 目录 钓鱼攻击之:Flash 网页钓鱼 1 准备资料 2 具体钓鱼流程 3 生成后门并捆绑flash的安装程序 4 处理WEB站点过程 1 准备资料 Flash网站克 ...