25 设置窗口背景
《PyQt5快速开发与实战》学习笔记。
QWidget 类中比较重要的绘图函数如表所示。
- 实现不规则窗口的最简单方式就是图片素材既当遮罩层又当背景图片,通过重载
paintEvent()
函数绘制窗口背景。
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPixmap, QPainter, QBitmap
class Winform(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("不规则窗体的实现例子")
self.resize(600, 400)
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(0, 0, 280, 390, QPixmap(r"./images/dog.jpg"))
painter.drawPixmap(300, 0, 280, 390, QBitmap(r"./images/dog.jpg"))
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Winform()
form.show()
sys.exit(app.exec_())
效果如下:
- 使用一张遮罩层图片来控制窗口的大小,然后再利用 paintEvent() 函数重绘窗口的背景图等。本例使用的素材图片为 mask.png 和 screen1.jpg,效果如图。
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPixmap, QPainter, QBitmap
class Winform(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("不规则窗体的实现例子")
self.pix = QBitmap("./images/mask.png")
self.resize(self.pix.size())
self.setMask(self.pix)
def paintEvent(self, event):
painter = QPainter(self)
#在指定区域直接绘制窗口背景
painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(),
QPixmap("./images/screen1.jpg"))
#绘制窗口背景,平铺到整个窗口,随着窗口改变而改变
#painter.drawPixmap(0,0,self.width(),self.height(),QPixmap("./images/screen1.jpg"))
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Winform()
form.show()
sys.exit(app.exec_())
效果如下:
- 实现可以拖动的不规则窗口。
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPixmap, QPainter, QCursor, QBitmap
from PyQt5.QtCore import Qt
class ShapeWidget(QWidget):
def __init__(self, parent=None):
super(ShapeWidget, self).__init__(parent)
self.setWindowTitle("不规则的,可以拖动的窗体实现例子")
self.mypix()
# 显示不规则 pic
def mypix(self):
self.pix = QBitmap("./images/mask.png")
self.resize(self.pix.size())
self.setMask(self.pix)
print(self.pix.size())
self.dragPosition = None
# 重定义鼠标按下响应函数mousePressEvent(QMouseEvent)和鼠标移动响应函数mouseMoveEvent(QMouseEvent),使不规则窗体能响应鼠标事件,随意拖动。
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.m_drag = True
self.m_DragPosition = event.globalPos()-self.pos()
event.accept()
self.setCursor(QCursor(Qt.OpenHandCursor))
if event.button() == Qt.RightButton:
self.close()
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton and self.m_drag:
# 当左键移动窗体修改偏移值
self.move(QMouseEvent.globalPos() - self.m_DragPosition)
QMouseEvent.accept()
def mouseReleaseEvent(self, QMouseEvent):
self.m_drag = False
self.setCursor(QCursor(Qt.ArrowCursor))
#一般 paintEvent 在窗体首次绘制加载, 要重新加载paintEvent 需要重新加载窗口使用 self.update() or self.repaint()
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(0, 0, self.width(), self.height(),
QPixmap("./images/boy.png"))
if __name__ == '__main__':
app = QApplication(sys.argv)
form = ShapeWidget()
form.show()
app.exec_()
效果如下:
25.2 不规则窗口实现动画效果
还可以使用 PyQt5 设计不规则窗口的动画效果。在显示不规则图片时主要注意如下两点。
(1)pixmap.setMask() 函数的作用是为调用它的控件增加一个遮罩,遮住所选区域以外的部分,使控件看起来是透明的。它的参数可以是一个QBitmap对象或一个QRegion对象。本例中调用QPixmap实例的self.pix.mask()函数获得图片自身的遮罩,这个遮罩是一个QBitmap对象
self.pix=QPixmap(self.mypic ,"0",Qt.AvoidDither | Qt.ThresholdDither| Qt.ThresholdAlphaDither)
self.setMask(self.pix.mask())
(2)paintEvent()函数每次初始化窗口时只调用一次,所以每加载一次图片就要重新调用一次paintEvent()函数,即在更新窗口时调用这个函数。更新窗口的核心代码如下:
self.timer=QTimer()
self.timer.setInterval(500)
self.timer.timeout.connect(self.timeChange)
self.timer.start()
当定时器(timer)的时间到期后更新窗口代码。
self.update()
完整代码:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPixmap, QPainter, QCursor
from PyQt5.QtCore import Qt, QTimer
class ShapeWidget(QWidget):
def __init__(self, parent=None):
super(ShapeWidget, self).__init__(parent)
self.i = 1
self.mypix()
self.timer = QTimer()
self.timer.setInterval(500) # 500毫秒
self.timer.timeout.connect(self.timeChange)
self.timer.start()
# 显示不规则 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], "0", Qt.AvoidDither |
Qt.ThresholdDither | Qt.ThresholdAlphaDither)
self.resize(self.pix.size())
self.setMask(self.pix.mask())
self.dragPosition = None
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.m_drag = True
self.m_DragPosition = event.globalPos()-self.pos()
event.accept()
self.setCursor(QCursor(Qt.OpenHandCursor))
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton and self.m_drag:
self.move(QMouseEvent.globalPos() - self.m_DragPosition)
QMouseEvent.accept()
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)
# 鼠标双击事件
def mouseDoubleClickEvent(self, event):
if event.button() == 1:
self.i += 1
self.mypix()
# 每500毫秒修改paint
def timeChange(self):
self.i += 1
self.mypix()
if __name__ == '__main__':
app = QApplication(sys.argv)
form = ShapeWidget()
form.show()
sys.exit(app.exec_())
效果如下:
运行这个例子,会弹出一个窗口,显示不同方向的箭头,每 500 毫秒改变一次箭头方向,按照上、右、下和左的方向转动。
25.3 加载 GIF 动画效果
演示加载 GIF 动画效果。其完整代码如下:
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QMovie
class LoadingGifWin(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.label = QLabel('', self)
self.setFixedSize(128, 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)
loadingGitWin = LoadingGifWin()
loadingGitWin.show()
sys.exit(app.exec_())
效果如下: