python PyQt5学习笔记 事件和信号 有注释 p2

2024-03-26 11:50

本文主要是介绍python PyQt5学习笔记 事件和信号 有注释 p2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事件和信号

事件

所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的,当然也有其他的事件产生方式,比如网络的连接,窗口管理器或者定时器等。调用应用的exec_()方法时,应用会进入主循环,主循环会监听和分发事件。

在事件模型中,有三个角色:

  • 事件源

  • 事件

  • 事件目标

事件源就是发生了状态改变的对象。事件是这个对象状态改变的内容。事件目标是事件想作用的目标。事件源绑定事件处理函数,然后作用于事件目标身上。

PyQt5处理事件方面有个signal and slot机制。Signals and slots用于对象间的通讯。事件触发的时候,发生一个signal,slot是用来被Python调用的

Signals & slots

信号与触发

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 and slot')self.show()
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

显示了QtGui.QLCDNumber和QtGui.QSlider模块,我们能拖动滑块让数字跟着发生改变。
sld.valueChanged.connect(lcd.display)
这里是把滑块的变化和数字的变化绑定在一起。

sender是信号的发送者,receiver是信号的接收者,slot是对这个信号应该做出的反应。

重构事件处理器

在PyQt5中,事件处理器经常被重写(也就是用自己的覆盖库自带的)。

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplicationclass 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):print(e.key(),chr(e.key()))if e.key() == Qt.Key_Escape:self.close()if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())87 W
68 D
83 S
74 J
74 J
74 J

事件对象

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication, QGridLayout, QLabelclass Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):# grid = QGridLayout()# grid.setSpacing(10)x = 0y = 0self.text = "x: {0},  y: {1}".format(x, y)self.label = QLabel(self.text, self) #self.label 全局# grid.addWidget(self.label, 0, 0, Qt.AlignTop)self.setMouseTracking(True)self.label.resize(200,60)#宽 高# self.setLayout(grid)self.setGeometry(300, 300, 350, 200)self.setWindowTitle('Event object')self.show()def mouseMoveEvent(self, e):x = e.x()y = e.y()text = "x: {0},  y: {1}".format(x, y)self.label.setText(text)# print(text)self.label.move(x,y)if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

事件对象是用python来描述一系列的事件自身属性的对象。

这个示例中,我们在一个组件里显示鼠标的X和Y坐标。
self.text = "x: {0},  y: {1}".format(x, y)

self.label = QLabel(self.text, self)
X Y坐标显示在QLabel组件里
self.setMouseTracking(True)
事件追踪默认没有开启,当开启后才会追踪鼠标的点击事件。
def mouseMoveEvent(self, e):

    x = e.x()
    y = e.y()

    text = "x: {0},  y: {1}".format(x, y)
    self.label.setText(text)
e代表了事件对象。里面有我们触发事件(鼠标移动)的事件对象。x()和y()方法得到鼠标的x和y坐标点,然后拼成字符串输出到QLabel组件里。

事件发送

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.buttonClicked2)self.statusBar()self.setGeometry(300, 300, 290, 150)self.setWindowTitle('Event sender')self.show()def buttonClicked(self):sender = self.sender()print(sender.text())self.statusBar().showMessage(sender.text() + ' was pressed')def buttonClicked2(self):print(2)
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)
两个按钮都和同一个slot绑定。
def buttonClicked(self):

    sender = self.sender()
    self.statusBar().showMessage(sender.text() + ' was pressed')
我们用调用sender()方法的方式决定了事件源。状态栏显示了被点击的按钮。

 信号发送

import sys
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QMainWindow, QApplicationclass Communicate(QObject):closeApp = pyqtSignal()
class Example(QMainWindow):def __init__(self):super().__init__()self.initUI()def initUI(self):self.c = Communicate()#self.c.closeApp.connect(self.close)self.c.closeApp.connect(self.print6) #自定义函数self.setGeometry(300, 300, 290, 150)self.setWindowTitle('Emit signal')self.show()def mousePressEvent(self, event):self.c.closeApp.emit()#点击时运行def print6(self):print(666)
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

我们创建了一个叫closeApp的信号,这个信号会在鼠标按下的时候触发,事件与QMainWindow绑定。


class Communicate(QObject):

    closeApp = pyqtSignal()
Communicate类创建了一个pyqtSignal()属性的信号


self.c = Communicate()
self.c.closeApp.connect(self.close)
closeApp信号QMainWindow的close()方法绑定。


def mousePressEvent(self, event):

    self.c.closeApp.emit()
点击窗口的时候,发送closeApp信号,程序终止

对话框

对话框用来输入数据,修改数据,修改应用设置等等

输入文字

QInputDialog提供了一个简单方便的对话框,可以输入字符串,数字或列表

from PyQt5.QtWidgets import (QWidget, QPushButton, QLineEdit,QInputDialog, QApplication)
import sys
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提供颜色的选择。

from PyQt5.QtWidgets import (QWidget, QPushButton, QFrame,QColorDialog, QApplication)
from PyQt5.QtGui import QColor
import sys
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()print("%s"% col.name())if col.isValid():# self.frm.setStyleSheet("%s"% col.name())#无效self.frm.setStyleSheet("QWidget { background-color: %s }"% col.name())
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

例子里有一个按钮和一个QFrame,默认的背景颜色为黑色,我们可以使用QColorDialog改变背景颜色。
col = QColor(0, 0, 0)
初始化QtGui.QFrame的背景颜色。

col = QColorDialog.getColor()
弹出一个QColorDialog对话框。

if col.isValid():
    self.frm.setStyleSheet("QWidget { background-color: %s }"
        % col.name()
)
我们可以预览颜色,如果点击取消按钮,没有颜色值返回,如果颜色是我们想要的,就从取色框里选择这个颜色。

选择字体

QFontDialog能做字体的选择。

from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QPushButton,QSizePolicy, QLabel, QFontDialog, QApplication)
import sysclass 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()print(font)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和其他两种。
if ok:
    self.label.setFont(font)
如果点击OK,标签的字体就会随之更改。

选择文件

QFileDialog给用户提供文件或者文件夹选择的功能。能打开和保存文件。

from PyQt5.QtWidgets import (QMainWindow, QTextEdit,QAction, QFileDialog, QApplication)
from PyQt5.QtGui import QIcon
import sys
class Example(QMainWindow):def __init__(self):super().__init__()self.initUI()def initUI(self):self.textEdit = QTextEdit()self.setCentralWidget(self.textEdit)self.statusBar()openFile = QAction('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')print(fname)if fname[0]:try:f = open(fname[0], 'r')with f:data = f.read()self.textEdit.setText(data)except:self.textEdit.setText('错误:'+fname[0])if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

本例中有一个菜单栏,一个置中的文本编辑框,一个状态栏。点击菜单栏选项会弹出一个QtGui.QFileDialog对话框,在这个对话框里,你能选择文件,然后文件的内容就会显示在文本编辑框里。

self.textEdit = QTextEdit()
self.setCentralWidget(self.textEdit)

这里设置了一个文本编辑框,文本编辑框是基于QMainWindow组件的
fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
弹出QFileDialog窗口
getOpenFileName()方法的第一个参数是说明文字,第二个参数是默认打开的文件夹路径。默认情况下显示所有类型的文件
if fname[0]:
    f = open(fname[0], 'r')

    with f:
        data = f.read()
        self.textEdit.setText(data)
读取选中的文件,并显示在文本编辑框内(但是打开HTML文件时,是渲染后的结果,汗)。

控件(1)

控件就像是应用这座房子的一块块砖。PyQt5有很多的控件,比如按钮,单选框,滑动条,复选框等等。在本章,我们将介绍一些很有用的控件:QCheckBoxToggleButtonQSliderQProgressBarQCalendarWidget。(复选框、切换按钮、滑块、进度条和日历)

QCheckBox

QCheckBox 组件有俩状态:开和关。通常跟标签一起使用,用在激活和关闭一些选项的场景。

from PyQt5.QtWidgets import QWidget, QCheckBox, QApplication
from PyQt5.QtCore import Qt
import sysclass 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):print(state, Qt.Checked)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信号关联起来。这样,changeTitle()就能切换窗口标题了。
def changeTitle(self, state):

    if state == Qt.Checked:
        self.setWindowTitle('QCheckBox')
    else:
        self.setWindowTitle('')
控件的状态是由changeTitle()方法控制的,如果空间被选中,我们就给窗口添加一个标题,如果没被选中,就清空标题。

切换按钮

切换按钮就是QPushButton的一种特殊模式。 它只有两种状态:按下和未按下。我们在点击的时候切换两种状态,有很多场景会使用到这个功能。

from PyQt5.QtWidgets import (QWidget, QPushButton,QFrame, QApplication)
from PyQt5.QtGui import QColor
import sys
class Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):self.col = QColor(0, 0, 0)self.col.setRgb(102,111,0)#设置rpg颜色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)jia=QPushButton('加1',self)jia.move(10,160)jia.clicked.connect(self.color_1)xianshi=QPushButton('显示',self)xianshi.move(160,160)xianshi.clicked.connect(self.color_xian)self.square = QFrame(self)self.square.setGeometry(150, 20, 100, 100)self.square.setStyleSheet("QWidget { background-color: %s }" %self.col.name())self.setGeometry(300, 400, 280, 200)#从屏幕上(300,400)位置开始(即为最左上角的点),显示一个280*200的界面(宽280,高200)self.setWindowTitle('Toggle button')self.show()def setColor(self, pressed):source = self.sender()if pressed:val = 255else: val = 0if source.text() == "Red":self.col.setRed(val)elif source.text() == "Green":self.col.setGreen(val)elif source.text() == "Blue":self.col.setBlue(val)self.square.setStyleSheet("QFrame { background-color: %s }" %self.col.name())def color_1(self):self.col.setRed(self.col.red()+1)self.col.setBlue(self.col.blue() + 1)self.col.setGreen(self.col.green() + 1)self.square.setStyleSheet("QFrame { background-color: %s }" %self.col.name())def color_xian(self):print(self.col.red(),self.col.green(),self.col.blue())
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

我们创建了一个切换按钮和一个QWidget,并把QWidget的背景设置为黑色。点击不同的切换按钮,背景色会在红、绿、蓝之间切换(而且能看到颜色合成的效果,而不是单纯的颜色覆盖)。


self.col = QColor(0, 0, 0)
设置颜色为黑色。

redb = QPushButton('Red', self)
redb.setCheckable(True)
redb.move(10, 10)
创建一个QPushButton,然后调用它的setCheckable()的方法就把这个按钮编程了切换按钮
redb.clicked[bool].connect(self.setColor)
把点击信号和我们定义好的函数关联起来,这里是把点击事件转换成布尔值


source = self.sender()
获取被点击的按钮。


if source.text() == "Red":
    self.col.setRed(val)
如果是标签为“red”的按钮被点击,就把颜色更改为预设好的对应颜色。


self.square.setStyleSheet("QFrame { background-color: %s }" %
    self.col.name())
使用样式表(就是CSS的SS)改变背景色

滑块

QSlider是个有一个小滑块的组件,这个小滑块能拖着前后滑动,这个经常用于修改一些具有范围的数值,比文本框或者点击增加减少的文本框(spin box)方便多了。

本例用一个滑块和一个标签展示。标签为一个图片,滑块控制标签(的值)。

先准备四个分别表示静音、小音量、中音量、大音量的图标,文件名分别叫mute.png, min.png, med.png, max.png

from PyQt5.QtWidgets import (QWidget, QSlider,QLabel, QApplication)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
import sys
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.resize(200,20)self.label.move(80,100)# self.label.setPixmap(QPixmap('mute.png'))# 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.setText('mute:'+str(value))# self.label.setPixmap(QPixmap('mute.png'))elif value > 0 and value <= 30:self.label.setText('min:'+str(value))# self.label.setPixmap(QPixmap('min.png'))elif value > 30 and value < 80:self.label.setText('med:'+str(value))# self.label.setPixmap(QPixmap('med.png'))else:self.label.setText('max:'+str(value))# self.label.setPixmap(QPixmap('max.png'))
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

这里是模拟的音量控制器。拖动滑块,能改变标签位置的图片。
sld = QSlider(Qt.Horizontal, self)
创建一个水平的QSlider。


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,就把图片换成 mute.png。

进度条

进度条是用来展示任务进度的。它的滚动能让用户了解到任务的进度。QProgressBar组件提供了水平和垂直两种进度条,进度条可以设置最大值和最小值,默认情况是0~99。

from PyQt5.QtWidgets import (QWidget, QProgressBar,QPushButton, QApplication)
from PyQt5.QtCore import QBasicTimer
import sys
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 = 0self.setGeometry(300, 300, 280, 170)self.setWindowTitle('QProgressBar')self.show()def timerEvent(self, e):if self.step >= 200:self.timer.stop()self.btn.setText('Finished')returnself.step = self.step + 10print(self.step)self.pbar.setValue(self.step)def doAction(self):if self.timer.isActive():self.timer.stop()self.btn.setText('Start')else:self.timer.start(200, 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()
用时间控制进度条。

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提供了基于月份的日历插件,十分简易而且直观。

from PyQt5.QtWidgets import (QWidget, QCalendarWidget,QLabel, QApplication, QVBoxLayout)
from PyQt5.QtCore import QDate
import sysclass Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):vbox = QVBoxLayout(self)cal = QCalendarWidget(self)cal.setGridVisible(True)#设置网格可见cal.clicked[QDate].connect(self.showDate)vbox.addWidget(cal)self.lbl = QLabel(self)date = cal.selectedDate()self.lbl.setText(date.toString())vbox.addWidget(self.lbl)self.setLayout(vbox)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()方法获取选中的日期,然后把日期对象转成字符串,在标签里面显示出来

控件(2)

本章我们继续介绍PyQt5控件。这次的有QPixmapQLineEditQSplitter,和QComboBox

图片

QPixmap是处理图片的组件。本例中,我们使用QPixmap在窗口里显示一张图片。

from PyQt5.QtWidgets import (QWidget, QHBoxLayout,QLabel, QApplication)
from PyQt5.QtGui import QPixmap
import sys
class Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):hbox = QHBoxLayout(self)pixmap = QPixmap(r"C:\Users\user\Downloads\RE4wtd4.jpg")lbl = QLabel(self)lbl.setPixmap(pixmap)lbl.resize(300,200)hbox.addWidget(lbl)self.setLayout(hbox)self.setGeometry(100,100,300,200)self.setWindowTitle('Red Rock')self.show()
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

pixmap = QPixmap("redrock.png")
创建一个QPixmap对象,接收一个文件作为参数

lbl = QLabel(self)
lbl.setPixmap(pixmap)
把QPixmap实例放到QLabel组件里。

行编辑

QLineEdit组件提供了编辑文本的功能,自带了撤销、重做、剪切、粘贴、拖拽等功能。

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)self.lbl.move(60, 40)qle = QLineEdit(self)qle.move(60, 100)qle.textChanged[str].connect(self.onChanged)self.setGeometry(300, 300, 280, 170)self.setWindowTitle('QLineEdit')self.show()def onChanged(self, text): #每二十个字符换行if len(text) >20:ce=''for i in range(len(text)):ce=ce+text[i]if i%20==0 and i>10:ce = ce + '\n'self.lbl.setText(ce)else:self.lbl.setText(text)self.lbl.adjustSize()
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

 例子中展示了一个编辑组件和一个标签,我们在输入框里键入的文本,会立即在标签里显示出来。
qle = QLineEdit(self)
创建一个QLineEdit对象。


qle.textChanged[str].connect(self.onChanged)
如果输入框的值有变化,就调用onChanged()方法


def onChanged(self, text):

    self.lbl.setText(text)
    self.lbl.adjustSize()
在onChanged()方法内部,我们把文本框里的值赋值给了标签组件,然后调用adjustSize()方法让标签自适应文本内容。

QSplitter

QSplitter组件能让用户通过拖拽分割线的方式改变子窗口大小的组件。本例中我们展示用两个分割线隔开的三个QFrame组件。

from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QFrame,QSplitter, QStyleFactory, QApplication)
from PyQt5.QtCore import Qt
import sys
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_())

三个窗口和两个分割线的布局创建完成了,但是要注意,有些主题下,分割线的显示效果不太好。

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


为了更清楚的看到分割线,我们使用了设置好的子窗口样式。

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


创建一个QSplitter组件,并在里面添加了两个框架。

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


也可以在分割线里面再进行分割。

下拉选框

QComboBox组件能让用户在多个选择项中选择一个。

from PyQt5.QtWidgets import (QWidget, QLabel,QComboBox, QApplication)
import sys
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")for i in range(10):combo.addItem("Gentoo"+str(i))combo.move(50, 50)self.lbl.move(50, 150)self.lbl2 = QLabel("记录", self)self.lbl2.move(50, 100)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()self.lbl2.setText(self.lbl2.text()+text)self.lbl2.adjustSize()#要设置长度,默认长度不显示后面的内容
if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

本例包含了一个QComboBox和一个QLabel。下拉选择框有五个选项,都是Linux的发行版名称,标签内容为选定的发行版名称。

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


在方法内部,设置标签内容为选定的字符串,然后设置自适应文本大小。

 

拖拽

在GUI里,拖放是指用户点击一个虚拟的对象,拖动,然后放置到另外一个对象上面的动作。一般情况下,需要调用很多动作和方法,创建很多变量。

拖放能让用户很直观的操作很复杂的逻辑。

一般情况下,我们可以拖放两种东西:数据和图形界面。把一个图像从一个应用拖放到另外一个应用上的实质是操作二进制数据。把一个表格从Firefox上拖放到另外一个位置 的实质是操作一个图形组。

简单的拖放

本例使用了QLineEditQPushButton。把一个文本从编辑框里拖到按钮上,更新按钮上的标签(文字)。

from PyQt5.QtWidgets import (QPushButton, QWidget,QLineEdit, QApplication, QLabel)
import sys
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):self.edit = QLineEdit('拖放文本到这里', self)self.edit.setDragEnabled(True)self.edit.move(30, 65)self.edit.textChanged[str].connect(self.change_)self.lbl =QLabel('显示文本',self)self.lbl.move(20,20)button = Button("Button", self)button.move(190, 65)self.setWindowTitle('Simple drag and drop')self.setGeometry(300, 300, 300, 150)def change_(self):self.lbl.setText(self.edit.text())self.lbl.adjustSize()print(self.edit.text())
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上构造一个按钮实例。

self.setAcceptDrops(True)

激活组件的拖拽事件。

def dragEnterEvent(self, e):if e.mimeData().hasFormat('text/plain'):e.accept()else:e.ignore()


首先,我们重构了dragEnterEvent()方法。设定好接受拖拽的数据类型(plain text)。

def dropEvent(self, e):self.setText(e.mimeData().text())


然后重构dropEvent()方法,更改按钮接受鼠标的释放事件的默认行为。

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


QLineEdit默认支持拖拽操作,所以我们只要调用setDragEnabled()方法使用就行了。

 

拖放按钮组件

class Button(QPushButton):def __init__(self, title, parent):super().__init__(title, parent)


从QPushButton继承一个Button类,然后重构QPushButton的两个方法: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-based数据。

dropAction = drag.exec_(Qt.MoveAction)


拖放事件开始时,用到的处理函数式start().

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


指定放下的动作类型为moveAction。

绘图

PyQt5绘图系统能渲染矢量图像、位图图像和轮廓字体文本。一般会使用在修改或者提高现有组件的功能,或者创建自己的组件。使用PyQt5的绘图API进行操作。

绘图由paintEvent()方法完成,绘图的代码要放在QPainter对象的begin()end()方法之间。是低级接口。

文本涂鸦

#!/usr/bin/python3
# -*- coding: utf-8 -*-"""
ZetCode PyQt5 tutorial In this example, we draw text in Russian Cylliric.Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""import sys
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor, QFont
from PyQt5.QtCore import Qtclass Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):      self.text = "Лев Николаевич Толстой\nАнна Каренина"self.setGeometry(300, 300, 280, 170)self.setWindowTitle('Drawing 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):
...
在绘画事件内完成绘画动作。
qp = QPainter()
qp.begin(self)
self.drawText(event, qp)
qp.end()
QPainter是低级的绘画类。所有的绘画动作都在这个类的begin()和end()方法之间完成,绘画动作都封装在drawText()内部了。
qp.setPen(QColor(168, 34, 3))
qp.setFont(QFont('Decorative', 10))
为文字绘画定义了笔和字体。
qp.drawText(event.rect(), Qt.AlignCenter, self.text)
drawText()方法在窗口里绘制文本,rect()方法返回要更新的矩形区域。

点的绘画

#!/usr/bin/python3
# -*- coding: utf-8 -*-"""
ZetCode PyQt5 tutorial In the example, we draw randomly 1000 red points 
on the window.Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter
from PyQt5.QtCore import Qt
import sys, randomclass Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):      self.setGeometry(300, 300, 300, 190)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)
设置笔的颜色为红色,使用的是预定义好的颜色。
size = self.size()
每次更改窗口大小,都会产生绘画事件,从size()方法里获得当前窗口的大小,然后把产生的点随机的分配到窗口的所有位置上。
qp.drawPoint(x, y)
drawPoint()方法绘图。

颜色

颜色是一个物体显示的RGB的混合色。RBG值的范围是0255。我们有很多方式去定义一个颜色,最常见的方式就是RGB和16进制表示法,也可以使用RGBA,增加了一个透明度的选项,透明度值的范围是01,0代表完全透明。

#!/usr/bin/python3
# -*- coding: utf-8 -*-"""
ZetCode PyQt5 tutorial This example draws three rectangles in three
#different colours. Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor, QBrush
import sysclass 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_())

我们画出了三个颜色的矩形。
color = QColor(0, 0, 0)
color.setNamedColor('#d4d4d4')
使用16进制的方式定义一个颜色。
qp.setBrush(QColor(200, 0, 0))
qp.drawRect(10, 15, 90, 60)
定义了一个笔刷,并画出了一个矩形。笔刷是用来画一个物体的背景。drawRect()有四个参数,分别是矩形的x、y、w、h。 然后用笔刷和矩形进行绘画。

 QPen

QPen是基本的绘画对象,能用来画直线、曲线、矩形框、椭圆、多边形和其他形状。

from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtCore import Qt
import sys
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_())

在这个例子里,我们用不同的笔画了6条直线。PyQt5有五个预定义的笔,另外一个笔的样式使我们自定义的。

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也是图像的一个基本元素。是用来填充一些物体的背景图用的,比如矩形,椭圆,多边形等。有三种类型:预定义、渐变和纹理。

from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QBrush
from PyQt5.QtCore import Qt
import sys
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_())

我们画了9个不同的矩形。

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


创建了一个笔刷对象,添加笔刷样式,然后调用drawRect()方法画图。

贝塞尔曲线

from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QPainterPath
from PyQt5.QtCore import Qt
import sys
class Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):self.setGeometry(300, 300, 380, 250)self.setWindowTitle('Bézier curve')self.show()def paintEvent(self, e):qp = QPainter()qp.begin(self)qp.setRenderHint(QPainter.Antialiasing)self.drawBezierCurve(qp)qp.end()def drawBezierCurve(self, qp):path = QPainterPath()path.moveTo(30, 30)path.cubicTo(30, 30, 200, 350, 350, 30)qp.drawPath(path)if __name__ == '__main__':app = QApplication(sys.argv)ex = Example()sys.exit(app.exec_())

这个示例中,我们画出了一个贝塞尔曲线。
path = QPainterPath()
path.moveTo(30, 30)
path.cubicTo(30, 30, 200, 350, 350, 30)
用QPainterPath路径创建贝塞尔曲线。使用cubicTo()方法生成,分别需要三个点:起始点,控制点和终止点。
qp.drawPath(path)
drawPath()绘制最后的图像。

自定义组件

PyQt5有丰富的组件,但是肯定满足不了所有开发者的所有需求,PyQt5只提供了基本的组件,像按钮,文本,滑块等。如果你还需要其他的模块,应该尝试自己去自定义一些。

自定义组件使用绘画工具创建,有两个基本方式:根据已有的创建或改进;通过自己绘图创建。

Burning widget

#!/usr/bin/python3
# -*- coding: utf-8 -*-"""
ZetCode PyQt5 tutorial In this example, we create a custom widget.Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""from PyQt5.QtWidgets import (QWidget, QSlider, QApplication, QHBoxLayout, QVBoxLayout)
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QFont, QColor, QPen
import sysclass Communicate(QObject):updateBW = pyqtSignal(int)class BurningWidget(QWidget):def __init__(self):      super().__init__()self.initUI()def initUI(self):self.setMinimumSize(1, 30)self.value = 75self.num = [75, 150, 225, 300, 375, 450, 525, 600, 675]def setValue(self, value):self.value = valuedef paintEvent(self, e):qp = QPainter()qp.begin(self)self.drawWidget(qp)qp.end()def drawWidget(self, qp):MAX_CAPACITY = 700OVER_CAPACITY = 750font = QFont('Serif', 7, QFont.Light)qp.setFont(font)size = self.size()w = size.width()h = size.height()step = int(round(w / 10))till = int(((w / OVER_CAPACITY) * self.value))full = int(((w / OVER_CAPACITY) * MAX_CAPACITY))if self.value >= MAX_CAPACITY: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 = 0for 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 + 1class Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):      OVER_CAPACITY = 750sld = QSlider(Qt.Horizontal, self)sld.setFocusPolicy(Qt.NoFocus)sld.setRange(1, OVER_CAPACITY)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_())

本例中,我们使用了QSlider和一个自定义组件,由进度条控制。显示的有物体(也就是CD/DVD)的总容量和剩余容量。进度条的范围是1~750。如果值达到了700(OVER_CAPACITY),就显示为红色,代表了烧毁了的意思。
烧录组件在窗口的底部,这个组件是用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))
动态的渲染组件,随着窗口的大小而变化,这就是我们计算窗口大小的原因。最后一个参数决定了组件的最大范围,进度条的值是由窗口大小按比例计算出来的。最大值的地方填充的是红色。注意这里使用的是浮点数,能提高计算和渲染的精度。
绘画由三部分组成,黄色或红色区域和黄色矩形,然后是分割线,最后是添上代表容量的数字。
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组件,然后重新渲染Burning组件。

俄罗斯方块游戏

这篇关于python PyQt5学习笔记 事件和信号 有注释 p2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/848415

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学