PyQt事件机制及其应用

一、实例前置

一个小闹钟应用

创建主窗口类

首先我们创建了一个名为AlarmClock的类,它继承自QMainWindow。这个类将包含我们的GUI组件和逻辑。

python 复制代码
from Alarm_clock import Ui_MainWindow

class AlarmClock(QMainWindow):
    def __init__(self):
        super().__init__()

        # 初始化 UI
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

二、创建UI界面

预先设计好的UI文件Alarm_clock.ui

这里,我们使用pyside6-uic把一个预先设计好的UI文件Alarm_clock.ui转成py格式,然后通过from import导入,这个文件定义了我们的界面布局

三、QtWidgets

在 PyQt 中,QtWidgets是一个非常重要的模块,它提供了大量用于构建图形用户界面(GUI)的部件(Widgets)类。这些部件包括但不限于按钮(QPushButton)、标签(QLabel)、文本框(QLineEdit)、布局管理器(如QVBoxLayoutQHBoxLayout)等,是创建交互式 GUI 应用程序的基础构建块。

①QApplication

QApplication是整个应用程序的核心管理类。它负责管理应用程序的生命周期,包括初始化、事件循环处理、资源管理等诸多关键事务。一个 PyQt 应用程序通常需要创建一个QApplication对象作为起点来启动整个应用程序的运行。

python 复制代码
     import sys
     from PyQt6.QtWidgets import QApplication

     app = QApplication(sys.argv)
     # 在这里可以通过sys.argv来获取命令行参数,并根据参数进行应用程序的初始化设置

②QMainWindow

在 PyQt 中,QMainWindow是一个用于创建主窗口类型应用程序的关键类。它提供了一个完整的框架来构建包含菜单栏、工具栏、状态栏和中心部件等典型布局的主窗口应用程序,为复杂的图形用户界面(GUI)应用程序提供了一种标准的组织结构。

python 复制代码
     from PyQt6.QtWidgets import QMainWindow, QApplication
     import sys

     app = QApplication(sys.argv)
     main_window = QMainWindow()
     main_window.show()
     sys.exit(app.exec())

四、PyQt时间事件处理

①QTimer

在 PyQt 中,QTimer是一个用于实现定时器功能的类。它允许你在指定的时间间隔后触发一个信号,这个信号可以连接到一个槽函数,从而实现周期性的操作或者在延迟一段时间后执行某个操作。这在很多场景下非常有用,比如实现动画效果、定期更新数据显示、自动保存功能等。

例:创建用于检查闹钟的定时器

python 复制代码
self.timer = QTimer(self)
self.timer.timeout.connect(self.check_alarm)
self.alarm_time = None  # 初始化闹钟时间

例:创建滚动动画的定时器

python 复制代码
self.scroll_timer = QTimer(self)
self.scroll_timer.timeout.connect(self.scroll_footer_label)

②QTime

在 PyQt 中,QTime类主要用于表示时间。它提供了一种方便的方式来处理时间相关的操作,如获取当前时间、设置特定时间、比较时间大小、进行时间的加减运算等。这在很多需要涉及时间处理的应用场景中非常有用,例如日程安排应用、闹钟应用、时间记录工具等。

例:设置初始时间显示

python 复制代码
self.ui.timeLabel.setText(QTime.currentTime().toString("HH:mm:ss"))

例: 判断用户输入的时间格式

python 复制代码
self.alarm_time = QTime.fromString(input_time, "HH:mm:ss")
if not self.alarm_time.isValid():
    self.alarm_time = QTime.fromString(input_time, "H:m:s")
if not self.alarm_time.isValid():
    self.alarm_time = QTime.fromString(input_time, "HH:mm:ss")
if not self.alarm_time.isValid():
    self.alarm_time = QTime.fromString(input_time, "H:m:s")
if not self.alarm_time.isValid():
    self.ui.Alarm_display.setText("时间格式无效!")
        return

五、PyQt事件机制思维导图

PyQt事件机制思维导图

六、完整代码

python 复制代码
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel
from PySide6.QtCore import QTimer, QTime, Qt
from PySide6.QtGui import QPainter, QLinearGradient, QColor, QFont, QMouseEvent, QIcon
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
from Alarm_clock import Ui_MainWindow

class GradientTextLabel(QLabel):
    def __init__(self, text="", parent=None):
        super().__init__(text, parent)
        self.setFont(QFont("Arial", 40, QFont.Weight.Bold))
        self.setStyleSheet("background-color: transparent;")  # 背景透明

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        # 创建一个线性渐变(红到紫,带透明度)
        gradient = QLinearGradient(0, 0, self.width(), 0)
        gradient.setColorAt(0.0, QColor(100, 0, 200, 200))  # 紫色,透明度78%
        gradient.setColorAt(1.0, QColor(255, 0, 0, 200))  # 红色,透明度78%

        # 设置文字渐变
        pen = painter.pen()
        pen.setBrush(gradient)  # 使用渐变作为笔刷
        pen.setWidth(2)  # 设置笔宽度
        painter.setPen(pen)

        # 绘制文字
        painter.drawText(self.rect(), Qt.AlignCenter, self.text())
        painter.end()


class AlarmClock(QMainWindow):
    def __init__(self):
        super().__init__()

        # 初始化 UI
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # 设置应用图标
        self.setWindowIcon(QIcon("G:\longz\人工智能作业\PythonQt\闹钟界面/蓝色风信子_爱给网_aigei_com.ico"))

        # 开始隐藏footerLabel
        self.ui.footerLabel.hide()

        # 设置时间标签为渐变文字标签
        self.gradient_label = GradientTextLabel(parent=self)
        self.gradient_label.setGeometry(self.ui.timeLabel.geometry())  # 保持位置一致
        self.ui.timeLabel.deleteLater()  # 删除原来的 timeLabel
        self.ui.timeLabel = self.gradient_label  # 替换为渐变标签

        # 设置初始时间
        self.ui.timeLabel.setText(QTime.currentTime().toString("HH:mm:ss"))

        # 固定窗口大小为 800x600
        self.setFixedSize(800, 600)

        # 启动时间更新定时器(始终更新)
        self.time_timer = QTimer(self)
        self.time_timer.timeout.connect(self.update_time_display)
        self.time_timer.start(1000)  # 每秒更新一次

        # 纯净窗口
        self.setWindowFlag(Qt.WindowType.FramelessWindowHint)

        # 定时器
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.check_alarm)
        self.alarm_time = None

        # 滚动动画
        self.scroll_timer = QTimer(self)
        self.scroll_timer.timeout.connect(self.scroll_footer_label)

        self.footer_label_start_pos = self.ui.footerLabel.geometry().x()  # 起始位置
        self.footer_label_end_pos = -self.ui.footerLabel.width() + 800  # 结束位置

        # 音乐播放器
        self.media_player = QMediaPlayer(self)
        self.audio_output = QAudioOutput(self)
        self.media_player.setAudioOutput(self.audio_output)
        self.media_player.setSource("G:/longz/人工智能作业/PythonQt/闹钟界面/Scott Lloyd Shelly - Terraria Soundtrack - 01 Overworld Day.mp3")

        # 连接按钮点击事件
        self.ui.pushButton.clicked.connect(self.handle_button_click)

    # 处理按钮点击事件
    def handle_button_click(self):
        if self.ui.pushButton.text() == "启动":
            self.start_alarm_timer()
        elif self.ui.pushButton.text() == "停止":
            self.stop_alarm()

    # 停止闹钟
    def stop_alarm(self):
        # 停止定时器、滚动动画和音乐播放
        self.timer.stop()
        self.scroll_timer.stop()
        self.media_player.stop()
        self.ui.footerLabel.hide()

        # 重置按钮和状态显示
        self.ui.Alarm_display.setText("闹钟已停止")
        self.ui.pushButton.setText("启动")

    # 启动闹钟
    def start_alarm_timer(self):
        input_time = self.ui.Alarm_input.text()
        if not input_time:
            self.ui.Alarm_display.setText("请输入时间!")
            return

        # 支持多种时间格式
        self.alarm_time = QTime.fromString(input_time, "HH:mm:ss")
        if not self.alarm_time.isValid():
            self.alarm_time = QTime.fromString(input_time, "H:m:s")
        if not self.alarm_time.isValid():
            self.alarm_time = QTime.fromString(input_time, "HH:mm:ss")
        if not self.alarm_time.isValid():
            self.alarm_time = QTime.fromString(input_time, "H:m:s")
        if not self.alarm_time.isValid():
            self.ui.Alarm_display.setText("时间格式无效!")
            return

        # 格式化时间并显示
        formatted_time = self.alarm_time.toString("HH:mm:ss")
        self.ui.Alarm_input.setText(formatted_time)

        # 启动定时器
        self.timer.start(1000)
        self.ui.Alarm_display.setText("闹钟已启动")
        self.ui.pushButton.setText("停止")

    # 更新时间显示
    def update_time_display(self):
        current_time = QTime.currentTime()
        self.ui.timeLabel.setText(current_time.toString("HH:mm:ss"))

    # 检查闹钟是否到达时间
    def check_alarm(self):
        current_time = QTime.currentTime()
        if self.alarm_time and current_time >= self.alarm_time and current_time <= self.alarm_time.addSecs(600):
            self.ui.Alarm_display.setText("闹钟响了!")
            self.ui.footerLabel.show()

            if not self.scroll_timer.isActive():
                self.scroll_timer.start(30)  # 滚动动画
            if self.media_player.mediaStatus() != QMediaPlayer.MediaStatus.LoadingMedia:
                self.media_player.play()
        else:
            # 停止定时器、滚动动画和音乐播放
            self.scroll_timer.stop()
            self.media_player.stop()
            self.ui.footerLabel.hide()
            # 状态显示
            self.ui.Alarm_display.setText("闹钟已结束")

    # 滚动 footerLabel
    def scroll_footer_label(self):
        current_geometry = self.ui.footerLabel.geometry()
        x = current_geometry.x() - 5  # 每次向左移动 5 像素

        # 如果超出左边界,将其重新设置到右边界
        if x < self.footer_label_end_pos:
            x = self.footer_label_start_pos

        self.ui.footerLabel.setGeometry(x, current_geometry.y(), current_geometry.width(), current_geometry.height())

    def mousePressEvent(self, event: QMouseEvent):
        self.px = event.pos().x()
        self.py = event.pos().y()

    def mouseMoveEvent(self, event: QMouseEvent):
        if event.buttons() == Qt.MouseButton.LeftButton:
            self.move(int(event.globalPosition().x()) - self.px, int(event.globalPosition().y()) - self.py)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = AlarmClock()
    window.setWindowFlag(Qt.WindowType.FramelessWindowHint)
    window.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
    window.show()
    sys.exit(app.exec())
相关推荐
鸡鸭扣1 小时前
Docker:3、在VSCode上安装并运行python程序或JavaScript程序
运维·vscode·python·docker·容器·js
paterWang2 小时前
基于 Python 和 OpenCV 的酒店客房入侵检测系统设计与实现
开发语言·python·opencv
东方佑2 小时前
使用Python和OpenCV实现图像像素压缩与解压
开发语言·python·opencv
饮长安千年月2 小时前
Linksys WRT54G路由器溢出漏洞分析–运行环境修复
网络·物联网·学习·安全·机器学习
红花与香菇2____2 小时前
【学习笔记】Cadence电子设计全流程(二)原理图库的创建与设计(上)
笔记·嵌入式硬件·学习·pcb设计·cadence·pcb工艺
神秘_博士2 小时前
自制AirTag,支持安卓/鸿蒙/PC/Home Assistant,无需拥有iPhone
arm开发·python·物联网·flutter·docker·gitee
Moutai码农4 小时前
机器学习-生命周期
人工智能·python·机器学习·数据挖掘
一天八小时4 小时前
Docker学习进阶
学习·docker·容器
前端没钱4 小时前
前端需要学习 Docker 吗?
前端·学习·docker
小白教程4 小时前
python学习笔记,python处理 Excel、Word、PPT 以及邮件自动化办公
python·python学习·python安装