void QComboBox::activated ( int index ) [signal]
void QComboBox::activated ( const QString & text ) [signal]
import
sys
from
PyQt5.QtWidgets
import
*
from
PyQt5
import
QtCore
#
查看有哪些风格类型
#
print(QStyleFactory.keys()) # ['windowsvista', 'Windows', 'Fusion']
class
WindowStyle(QWidget):
def
__init__
(self):
super(WindowStyle, self).
__init__
()
self.setWindowTitle(
"
设置窗口风格
"
)
layout
=
QHBoxLayout()
self.styleLabel
= QLabel(
"
设置窗口风格:
"
)
self.styleComboBox
=
QComboBox()
self.styleComboBox.addItems(QStyleFactory.keys())
#
获取当前窗口的风格
print
(QApplication.style().objectName())
#
windowsvista
#
选择当前styleComboBox内的风格, 并返回风格索引
index =
self.styleComboBox.findText(QApplication.style().objectName(), QtCore.Qt.MatchFixedString)
#
根据风格索引来设置界面风格
self.styleComboBox.setCurrentIndex(index)
#
activated[str] Python没有C++所具有的强类型函数重载。因此,PyQt通过拥有一个可以连接的插槽字典来处理这个问题。这个字典的关键是句柄将接受的参数的type
self.styleComboBox.activated[str].connect(self.handleStyleChanged)
layout.addWidget(self.styleLabel)
layout.addWidget(self.styleComboBox)
self.setLayout(layout)
def
handleStyleChanged(self, style):
QApplication.setStyle(style)
if
__name__
==
"
__main__
"
:
app
=
QApplication(sys.argv)
form
=
WindowStyle()
form.show()
sys.exit(app.exec_())
1.2 设置窗口样式(setWindowFlags )
#!/usr/bin/python
# -*- coding:utf-8 -*-
设置窗口样式 (主要是窗口边框,标题栏以及窗口本身的 样式)
setWindowFlags
FrameWindowHint : 没有边框的窗口
WindowStaysOnTopHint : 总在最zhi上面的窗口
CustomizeWindowHint : 自定义窗口标题栏
WindowTitleHint : 显示窗口标题栏
WindowSystemMenuHint : 显示系统菜单
WindowMinimizeButtonHint : 显示最小化按钮
WindowMaximizeButtonHint : 显示最大化按钮
WindowMinMaxButtonsHint : 显示最小化按钮和最大化按钮
WindowCloseButtonHint : 显示关闭按钮
from PyQt5.QtCore import *
import sys
from PyQt5.QtWidgets import *
class WindowPattern(QMainWindow):
def __init__(self):
super(WindowPattern, self).__init__()
self.resize(500, 260)
self.setWindowTitle("设置窗口的样式")
# 设置最大按钮,或者最顶端(置顶)
self.setWindowFlags(Qt.WindowMaximizeButtonHint | Qt.WindowStaysOnTopHint)
# 设置窗口的名字
self.setObjectName("MainWindow")
# 背景图,设置语法类似CSS
self.setStyleSheet("#MainWindow{border-image:url(images/python.jpg);}")
if __name__ == "__main__":
app = QApplication(sys.argv)
form = WindowPattern()
form.show()
sys.exit(app.exec_())
1.3 用代码设置窗口的最大化和最小化
#!/usr/bin/python
# -*- coding:utf-8 -*-
用代码控制窗口的最大化和最小化
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class WindowMaxMin(QWidget):
### 构造函数
def __init__(self, parent=None):
'''构造函数'''
# 调用父类构造函数
super(WindowMaxMin, self).__init__(parent)
self.resize(300, 400)
self.setWindowTitle("用代码控制窗口的最大化和最小化")
self.setWindowFlags(Qt.WindowMaximizeButtonHint)
layout = QVBoxLayout()
maxButton1 = QPushButton()
maxButton1.setText('窗口最大化1')
maxButton1.clicked.connect(self.maximized1)
maxButton2 = QPushButton()
maxButton2.setText('窗口最大化2')
maxButton2.clicked.connect(self.showMaximized)
minButton = QPushButton()
minButton.setText('窗口最小化')
minButton.clicked.connect(self.showMinimized)
layout.addWidget(maxButton1)
layout.addWidget(maxButton2)
layout.addWidget(minButton)
self.setLayout(layout)
def maximized1(self):
desktop = QApplication.desktop()
# 获取桌面可用尺寸
rect = desktop.availableGeometry()
self.setGeometry(rect)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = WindowMaxMin()
window.show()
sys.exit(app.exec_())
1.4 创建透明和半透明窗口
#!/usr/bin/python
# -*- coding:utf-8 -*-
创建透明窗口
from PyQt5.Qt import *
import sys
if __name__ == '__main__':
app = QApplication(sys.argv)
win = QMainWindow()
win.setWindowTitle('窗口的透明度设置')
# 0到1,1表示不透明,0表示完全透明
win.setWindowOpacity(0.6)
button = QPushButton('我的按钮', win)
win.resize(400, 200)
win.show()
sys.exit(app.exec())
二、绘图(实现绘图应用)
#!/usr/bin/python
# -*- coding:utf-8 -*-
实现绘图应用
需要解决3个核心内容
1. 如何绘图: 在paintEvent方法中绘图,通过调用update方法触发painEvent的调用
2. 在哪里绘图: 在白色背景的QPixmap对象中绘图
3. 如何通过移动鼠标进行绘图
鼠标拥有3个事件:
(1)鼠标按下:mousePressEvent
(2)鼠标移动:mouseMoveEvent
(3)鼠标抬起:mouseReleaseEvent
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QPixmap
from PyQt5.QtCore import Qt, QPoint
class Drawing(QWidget):
def __init__(self, parent=None):
super(Drawing, self).__init__(parent)
self.setWindowTitle("绘图应用")
self.pix = QPixmap()
self.lastPoint = QPoint()
self.endPoint = QPoint()
self.initUi()
def initUi(self):
self.resize(600, 600)
# 画布大小为600*600,背景为白色
self.pix = QPixmap(600, 600)
self.pix.fill(Qt.white)
def paintEvent(self, event):
pp = QPainter(self.pix)
# 根据鼠标指针前后两个位置绘制直线
pp.drawLine(self.lastPoint, self.endPoint)
# 让前一个坐标值等于后一个坐标值,
# 这样就能实现画出连续的线
self.lastPoint = self.endPoint
painter = QPainter(self)
painter.drawPixmap(0, 0, self.pix)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
# 获取鼠标按下的点
self.lastPoint = event.pos()
def mouseMoveEvent(self, event):
if event.buttons() and Qt.LeftButton:
# 移动过程中,设置当前位置为结束位置,随时更新过
self.endPoint = event.pos()
# 会自动调用 paintEvent 方法
self.update()
def mouseReleaseEvent(self, event):
# 鼠标左键释放, 和鼠标移动的时候代码是一样的
if event.button() == Qt.LeftButton:
self.endPoint = event.pos()
# 进行重新绘制
self.update()
if __name__
== "__main__":
app = QApplication(sys.argv)
form = Drawing()
form.show()
sys.exit(app.exec_())
三、QSS
3.1 QSS基础(setStyleSheet)
#!/usr/bin/python
# -*- coding:utf-8 -*-
QSS基础
QSS(Qt Style Sheets)
Qt样式表
用于设置控件的样式
from PyQt5.QtWidgets import *
import sys
class BasicQSS(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QSS样式")
btn1 = QPushButton(self)
btn1.setText("按钮1")
btn2 = QPushButton(self)
btn2.setText("按钮2")
btn3 = QPushButton(self)
btn3.setText("按钮3")
vbox = QVBoxLayout()
vbox.addWidget(btn1)
vbox.addWidget(btn2)
vbox.addWidget(btn3)
self.setLayout(vbox)
if __name__ == '__main__':
app = QApplication(sys.argv)
form = BasicQSS()
# 选择器 类似CSS选择器
# 所有的QPushButton控件都设置为背景颜色为红色
qssStyle = """
QPushButton
background-color:red
form.setStyleSheet(qssStyle)
form.show()
sys.exit(app.exec_())
3.2 使用QSS选择器设置控件样式(setProperty)
#!/usr/bin/python
# -*- coding:utf-8 -*-
QSS基础
QSS(Qt Style Sheets)
Qt样式表
用于设置控件的样式
from PyQt5.QtWidgets import *
import sys
class QSSSelector(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QSS样式")
btn1 = QPushButton(self)
btn1.setText("按钮1")
btn2 = QPushButton(self)
# setProperty(key, value)
btn2.setProperty("name", "btn2")
btn2.setText("按钮2")
btn3 = QPushButton(self)
btn3.setProperty("name", "btn3")
btn3.setText("按钮3")
vbox = QVBoxLayout()
vbox.addWidget(btn1)
vbox.addWidget(btn2)
vbox.addWidget(btn3)
self.setLayout(vbox)
if __name__ == '__main__':
app = QApplication(sys.argv)
form = QSSSelector()
# 选择器
qssStyle = """
QPushButton[name="btn2"]
background-color:red;
color:yellow;
height:120;
font-size:60px;
QPushButton[name="btn3"]
background-color:blue;
color:yellow;
height:60;
font-size:30px;
form.setStyleSheet(qssStyle)
form.show()
sys.exit(app.exec_())
3.3 QSS子控件选择器
#!/usr/bin/python
# -*- coding:utf-8 -*-
QSS子控件选择器
from PyQt5.QtWidgets import *
import sys
class QSSSubControl(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QSS子控件选择器")
# 下拉框
combo = QComboBox(self)
combo.setObjectName("myComboBox")
combo.addItem("Window")
combo.addItem("Linux")
combo.addItem("Mac OS X")
combo.move(50, 50)
self.setGeometry(250, 200, 320, 150)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = QSSSubControl()
# #myComboBox 相当于 CSS 中的id ::drop-down 代表子控件 代表的是点击选择下拉列表那个点击下拉按钮
qssStyle = """
QComboBox#myComboBox::drop-down
image:url(./images/python.jpg)
form.setStyleSheet(qssStyle)
form.show()
sys.exit(app.exec_())
3.4 使用QSS为标签和按钮添加背景图
#!/usr/bin/python
# -*- coding:utf-8 -*-
使用QSS为标签和按钮添加背景图
from PyQt5.QtWidgets import *
import sys
class LabelButtonBackground(QWidget):
def __init__(self):
super(LabelButtonBackground, self).__init__()
label1 = QLabel(self)
label1.setToolTip('这是一个文本标签')
label1.setStyleSheet('QLabel{border-image:url(./images/python.jpg);}')
label1.setFixedWidth(476)
label1.setFixedHeight(259)
btn1 = QPushButton(self)
btn1.setObjectName('btn1')
btn1.setMaximumSize(48, 48)
btn1.setMinimumSize(48, 48)
style = '''
#btn1{
border-radius:4px;
background-image:url('./images/add.png');
#btn1:Pressed {
background-image:url('./images/addhover.png');
btn1.setStyleSheet(style)
vbox = QVBoxLayout()
vbox.addWidget(label1)
vbox.addStretch()
vbox.addWidget(btn1)
self.setLayout(vbox)
self.setWindowTitle('使用QSS为标签和按钮添加背景图')
if __name__ == "__main__":
app = QApplication(sys.argv)
form = LabelButtonBackground()
form.show()
sys.exit(app.exec_())
3.5 三种方式设置背景色和背景图片
3.5.1 方式一 QSS
#!/usr/bin/python
# -*- coding:utf-8 -*-
使用多种方式设置窗口背景色和背景图片
通过QSS动态修改窗口的背景颜色和背景图片
import sys
from PyQt5.QtWidgets import *
if __name__ == '__main__':
app = QApplication(sys.argv)
win = QMainWindow()
win.setWindowTitle("背景图片")
win.resize(350, 250)
win.setObjectName("MainWindow")
# 通过QSS动态修改窗口的背景颜色和背景图片
win.setStyleSheet("#MainWindow{border-image:url(./images/python.jpg);}")
# win.setStyleSheet("#MainWindow{background-color:yellow}")
win.show()
sys.exit(app.exec())
3.5.2 方式二 QPalette
#!/usr/bin/python
# -*- coding:utf-8 -*-
使用多种方式设置窗口背景色和背景图片
通过QPalette设置背景图片和背景颜色
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
if __name__ == '__main__':
app = QApplication(sys.argv)
win = QMainWindow()
win.setWindowTitle("背景图片")
win.resize(350, 250)
win.setObjectName(
"MainWindow")
# 通过QPalette设置背景图片和背景颜色
palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(QPixmap("./images/python.jpg")))
# palette.setColor(QPalette.Background, Qt.red)
win.setPalette(palette)
win.show()
sys.exit(app.exec())
3.5.3 方式三 直接绘制
3.5.3.1 QPainter + setBrush
#!/usr/bin/python
# -*- coding:utf-8 -*-
使用多种方式设置窗口背景色和背景图片
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Background(QWidget):
def __init__(self):
super(Background, self).__init__()
self.setWindowTitle("绘制背景颜色")
def paintEvent(self, event):
painter = QPainter(self)
painter.setBrush(Qt.yellow)
painter.drawRect(self.rect())
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Background()
form.show()
sys.exit(app.exec_())
3.5.3.2 QPainter + QPixmap
#!/usr/bin/python
# -*- coding:utf-8 -*-
使用多种方式设置窗口背景色和背景图片
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class Background(QWidget):
def __init__(self):
super(Background, self).__init__()
self.setWindowTitle("绘制背景颜色")
def paintEvent(self, event):
painter = QPainter(self)
pixmap = QPixmap('./images/screen1.jpg')
painter.drawPixmap(self.rect(), pixmap)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Background()
form.show()
sys.exit(app.exec_())
3.6 装载QSS文件
// style.qss
QMainWindow{
border-image:url(./images/python.jpg);
QToolTip {
border:1px solid rgb(45,45,45);
background:white;
color:red
# CommonHelper.py
class CommonHelper:
@staticmethod
def readQSS(style):
with open(style,'r') as f:
return f.read()
# !/usr/bin/python
# -*- coding:utf-8 -*-
装载QSS文件
import sys
from PyQt5.QtWidgets import *
from windows.CommonHelper import CommonHelper
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.resize(477, 258)
self.setWindowTitle("加载QSS文件")
btn = QPushButton()
btn.setText('装载QSS文件')
btn.setToolTip('提示文本')
vbox = QVBoxLayout()
vbox.addWidget(btn)
btn.clicked.connect(self.onClick)
self.setLayout(vbox)
widget = QWidget(self)
self.setCentralWidget(widget)
widget.setLayout(vbox)
def onClick(self):
styleFile = './style.qss'
qssStyle = CommonHelper.readQSS(styleFile)
win.setStyleSheet(qssStyle)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
四、异型窗口
4.1 实现不规则的异形窗口并移动窗口
#!/usr/bin/python
# -*- coding:utf-8 -*-
实现不规则的窗口(异形窗口)
通过mask实现异形窗口
需要一张透明的png图,透明部分被扣出,形成一个非矩形的区域
异型窗口可以理解为一个不规则的图相框, 然后填充图片覆盖背景,
异形窗口本身是不能移动的,需要自己操作函数移动和关闭不规则窗口(实时计算窗口坐标)
而且windows下窗口的标题栏也没了,所以问题会出现窗口栏关不掉了
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class AbnormityWindow(QWidget):
def __init__(self):
super(AbnormityWindow, self).__init__()
self.setWindowTitle("异形窗口")
# 创建一个异形窗口图片
self.pix = QBitmap('./images/mask.png')
self.resize(self.pix.size())
# 设置掩模
self.setMask(self.pix)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.m_drag = True
self.m_DragPosition = event.globalPos() - self.pos()
self.setCursor(QCursor(Qt.OpenHandCursor))
print(event.globalPos()) #
print(event.pos())
print(self.pos())
if event.button() == Qt.RightButton:
self.close()
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton and self.m_drag:
# 当左键移动窗体修改偏移值
# QPoint
# 实时计算窗口左上角坐标
self.move(QMouseEvent.globalPos() - self.m_DragPosition)
def mouseReleaseEvent(self, QMouseEvent):
self.m_drag = False
self.setCursor(QCursor(Qt.ArrowCursor))
def paintEvent(self, event):
painter = QPainter(self)
# 设置背景图片
painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(), QPixmap('./images/screen1.jpg'))
if __name__ == "__main__":
app = QApplication(sys.argv)
form = AbnormityWindow()
form.show()
sys.exit(app.exec_())
4.2 实现异形窗口动画效果
#!/usr/bin/python
# -*- coding:utf-8 -*-
不规则窗体的动画实现(Windows 下起作用)
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPixmap, QPainter, QCursor
from PyQt5.QtCore import Qt, QTimer
class AnimationWindows(QWidget):
def __init__(self, parent=None):
super(AnimationWindows, self).__init__(parent)
self.i = 1
self.mypix()
# 创建一个定时器,每隔 500ms 更换一次图片
self.timer = QTimer()
self.timer.setInterval(500) # 500毫秒
self.timer.timeout.connect(self.timeChange)
self.timer.start()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.m_drag = True
self.m_DragPosition = event.globalPos() - self.pos()
self.setCursor(QCursor(Qt.OpenHandCursor))
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton and self.m_drag:
self.move(QMouseEvent.globalPos() - self.m_DragPosition)
def mouseReleaseEvent(self, QMouseEvent):
self.m_drag = False
self.setCursor(QCursor(Qt.ArrowCursor))
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(), self.pix)
# 每500毫秒修改paint
def timeChange(self):
self.i += 1
self.mypix()
# 显示不规则 pic
def mypix(self):
self.update()
if self.i == 5:
self.i = 1
self.mypic = {1: './images/left.png', 2: "./images/up.png", 3: './images/right.png', 4: './images/down.png'}
self.pix = QPixmap(self.mypic[self.i])
self.resize(self.pix.size())
self.setMask(self.pix.mask())
self.dragPosition = None
if __name__ == '__main__':
app = QApplication(sys.argv)
form = AnimationWindows()
form.show()
sys.exit(app.exec_())
五、动画效果
5.1 装载 gif动画文件
#!/usr/bin/python
# -*- coding:utf-8 -*-
装载Gif动画
QMovie
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QMovie
class LoadingGif(QWidget):
def __init__(self):
super(LoadingGif, self).__init__()
self.label = QLabel("", self)
self.setFixedSize(120, 128)
self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint)
self.movie = QMovie('./images/loading.gif')
self.label.setMovie(self.movie)
self.movie.start()
if __name__ == "__main__":
app = QApplication(sys.argv)
form = LoadingGif()
form.show()
sys.exit(app.exec_())
5.2 缩放图片(QImage.scaled)
#!/usr/bin/python
# -*- coding:utf-8 -*-
QImage.scaled
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import Qt
import sys
class ScaleImage(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("图片大小缩放例子")
filename = './images/Cloudy_72px.png'
img = QImage(filename)
label1 = QLabel(self)
label1.setFixedWidth(200)
label1.setFixedHeight(200)
# 宽度, 高度, 忽略图片原本的比例, 图片平滑显示
result = img.scaled(label1.width(), label1.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
label1.setPixmap(QPixmap.fromImage(result))
vbox = QVBoxLayout()
vbox.addWidget(label1)
self.setLayout(vbox)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = ScaleImage()
win.show()
sys.exit(app.exec_())
5.3 用动画效果改变窗口尺寸(QPropertyAnimation)
#!/usr/bin/python
# -*- coding:utf-8 -*-
用动画效果改变窗口尺寸
QPropertyAnimation
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class AnimWindow(QWidget):
def __init__(self):
super(AnimWindow, self).__init__()
self.OrigHeight = 50
self.ChangeHeight = 150
self.setGeometry(QRect(500, 400, 150, self.OrigHeight))
self.btn = QPushButton('展开', self)
self.btn.setGeometry(10, 10, 60, 35)
self.btn.clicked.connect(self.change)
def change(self):
# 保存当前的高度
currentHeight = self.height()
if self.OrigHeight == currentHeight:
startHeight = self.OrigHeight
endHeight = self.ChangeHeight
self.btn.setText("收缩")
else:
startHeight = self.ChangeHeight
endHeight = self.OrigHeight
self.btn.setText("展开")
# geometry 动画效果
self.animation = QPropertyAnimation(self, b'geometry')
self.animation.setDuration(500)
self.animation.setStartValue(QRect(500, 400, 150, startHeight))
self.animation.setEndValue(QRect(500, 400, 150, endHeight))
self.animation.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = AnimWindow()
window.show()
sys.exit(app.exec_())
5.4 用动画效果——不同速度移动窗口
# !/usr/bin/python
# -*- coding:utf-8 -*-
用动画效果一不同速度移动窗口
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
if __name__ == '__main__':
app = QApplication(sys.argv)
window1 = QMainWindow()
window1.show()
window2 = QMainWindow()
window2.show()
animation1 = QPropertyAnimation(window1, b'geometry')
animation2 = QPropertyAnimation(window2, b'geometry')
# group = QParallelAnimationGroup() # 并行, 两个动画同时运行
group = QSequentialAnimationGroup() # 串行
group.addAnimation(animation1)
group.addAnimation(animation2)
# 持续时间 3s
animation1.setDuration(3000)
animation1.setStartValue(QRect(0, 0, 100, 30))
animation1.setEndValue(QRect(250, 250, 100, 30))
# QEasingCurve.OutBounce 动画特效
animation1.setEasingCurve(QEasingCurve.OutBounce)
animation2.setDuration(4000)
animation2.setStartValue(QRect(250, 150, 100, 30))
animation2.setEndValue(QRect(850, 250, 100, 30))
animation2.setEasingCurve(QEasingCurve.CosineCurve)
group.start()
sys.exit(app.exec())