当前位置: 首页 > news >正文

PyQt5桌面应用开发(11):摸鱼也要讲基本法之桌面精灵

本文目录

  • PyQt5桌面应用系列
  • 鼠标不要钱,手腕还不要钱吗?
  • PyQt5源程序
    • python文件
    • 资源定义
    • 界面定义文件
  • 技术要素
    • 资源文件
    • StyleSheets
    • QMainWindow设置
    • 窗体几何
  • 结论

PyQt5桌面应用系列

  • PyQt5桌面应用开发(1):需求分析
  • PyQt5桌面应用开发(2):事件循环
  • PyQt5桌面应用开发(3):并行设计
  • PyQt5桌面应用开发(4):界面设计
  • PyQt5桌面应用开发(5):对话框
  • PyQt5桌面应用开发(6):文件对话框
  • PyQt5桌面应用开发(7):文本编辑+语法高亮与行号
  • PyQt5桌面应用开发(8):从QInputDialog转进到函数参数传递
  • PyQt5桌面应用开发(9):经典布局QMainWindow
  • PyQt5桌面应用开发(10):界面布局基本支持
  • PyQt5桌面应用开发(11):摸鱼也要讲基本法之桌面精灵

鼠标不要钱,手腕还不要钱吗?

每当打工人开始摸鱼的时候,打工人就会摸鱼。反正老板买的鼠标不要钱,我们来摸一个鼠标点击游戏的大鱼。我们要做个按钮精灵在屏幕上跑来跑去,鼠标点一下,另外一个数字精灵就显示点击次数。这样我们就可以开心的测试自己准确操作鼠标的能力,可以采取计时点击也可以采取点击FF次的时间。

游戏界面大概就是这样,由于录屏软件的功能和保密的原因,除了两个跑来跑去的烦人精之外的地方都被录成黑色,实际运行中,这两玩意就在当前显示屏的最上层跑来跑去。

在这里插入图片描述

当时鼠标不要钱 and 手腕也不要钱的时候,就可以玩出来这样的场景。程序键盘控制参见:1

在这里插入图片描述

这个程序有几个要点:

  1. 报表:点击次数显示在QLCDNumber中,当然我们都认识16进制,那就显示16进制,显得更酷!
  2. 数据:点击次数的数据就记录在QLCDNumber的值中。
  3. 交互要求:没有窗口,点击按钮在窗口范围内随机跑,计数控件追着点击按钮跑。

PyQt5源程序

这里首先就把代码发出来。

python文件

import importlib
import subprocess
import sys
from random import randintfrom PyQt5 import uic
from PyQt5.QtCore import QSize, Qt, QFile, QIODevice, QRect
from PyQt5.QtGui import QIcon, QKeyEvent, QKeySequence
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QLCDNumber, QStyleFactory# pyinstaller counting.py -w -y --add-data "countingmainwindow.ui;." --add-data "resources_rc.py;."
# produce distributed version in windows, run it first to get resouces_rc.py# workaround with qrc
def make_rc(fn: str):if fn.endswith(".qrc"):name, _ = fn.split(".")with subprocess.Popen(["pyrcc5", fn, "-o", f"{name}_rc.py"], stdout=subprocess.PIPE) as proc:msg = proc.stdout.read()if len(msg) > 0:raise IOError(f"error compile qrc file: {msg}")# load it or compile and load it
try:importlib.import_module(f"resources_rc")
except:make_rc("resources.qrc")importlib.import_module(f"resources_rc")class CountingMainWindow(QMainWindow):def __init__(self):super(CountingMainWindow, self).__init__()uic.loadUi("countingmainwindow.ui", self)self.pushButton: QPushButtonself.lcdNumber: QLCDNumberself.pushButton.setObjectName("btn")self.pushButton.setIconSize(QSize(48, 48))self.pushButton.setIcon(QIcon(":imgs/click.png"))self.pushButton.setText("")self.pushButton.setFixedSize(100, 100)self.lcdNumber.setFixedSize(100, 100)self.lcdNumber.setDigitCount(2)self.lcdNumber.setHexMode()self.pushButton.clicked.connect(self.move_widgets_like_crazy)self.pushButton.clicked.connect(lambda check: self.lcdNumber.display(self.lcdNumber.intValue() + 1))self.lcdNumber.overflow.connect(lambda: self.lcdNumber.display(0))self.setMenuBar(None)self.setStatusBar(None)self.setAttribute(Qt.WA_TranslucentBackground)self.setWindowFlags(Qt.FramelessWindowHint)self.setWindowState(Qt.WindowFullScreen)def move_widgets_like_crazy(self, check: bool):self.pushButton: QPushButtonself.lcdNumber: QLCDNumber# geometry return position related to its parent# relocated pushbuttonrect_window: QRect = self.geometry()rect_button: QRect = self.pushButton.geometry()x = randint(10, rect_window.width() - rect_button.width() - 10)y = randint(10, rect_window.height() - rect_button.height() - 10)rect_button.setX(x)rect_button.setY(y)self.pushButton.setGeometry(rect_button)# lcdnumber moving toward pushbuttonrect_lcd: QRect = self.lcdNumber.geometry()dx = rect_button.x() - rect_lcd.x()rect_lcd.setX(rect_lcd.x() + dx // 3)dy = rect_button.y() - rect_lcd.y()rect_lcd.setY(rect_lcd.y() + dy // 3)self.lcdNumber.setGeometry(rect_lcd)def keyPressEvent(self, event: QKeyEvent) -> None:if event.matches(QKeySequence.Cancel):self.close()if event.key() == Qt.Key_C:self.pushButton.clicked.emit(False)if event.key() == Qt.Key_R:self.lcdNumber.display(0)super(CountingMainWindow, self).keyPressEvent(event)def read_qss_file(filename: str) -> str:file = QFile(filename)if not file.open(QIODevice.ReadOnly | QIODevice.Text):raise IOError(f"Cannot open file: {filename}")qss = str(file.readAll(), encoding="utf-8")return qssif __name__ == '__main__':app = QApplication([])app.setStyle(QStyleFactory.create("Fusion"))app.setStyleSheet(read_qss_file(":stylesheets/style.qss"))mw = CountingMainWindow()mw.show()sys.exit(app.exec_())

资源定义

程序还包括了一个资源文件(附带一个png的图标,一个qss文件)和一个界面的ui文件。


<RCC><qresource><file>imgs/click.png</file><file>stylesheets/style.qss</file></qresource>
</RCC>

图标放于imgs/目录,qss文件放于stylesheets/目录。

在这里插入图片描述

QPushButton#btn {background-color: "cyan";border-radius: 15px;border: 1px solid black;padding: 5px;
}QPushButton#btn:hover {background-color: "cyan";border-radius: 15px;border: 1px solid red;padding: 5px;padding-bottom: 1px;
}QPushButton#btn:pressed {background-color: "#8E0000";border-radius: 15px;border: 1px solid red;padding: 5px;padding-bottom: 3px;
}QLCDNumber {background-color: "lightgray";color: #FE5F01;border-radius: 15px;border: 1px solid black;padding: 5px;
}

程序运行时,如果pyrcc5在目录,那么很简单,只要上面的三个文件按照qrc中的目录放置,就能自动产生resource_rc.py,并且自动导入。

pyrcc5 resouces.qrc -o resources_rc.py

界面定义文件

designer生成的ui文件最简单,就随便拉一个QMainWindow,上面丢一个按钮QPushButton,一个LCDNumber,保存就行。

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>my_ui::CountingMainWindow</class><widget class="QMainWindow" name="my_ui::CountingMainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>803</width><height>402</height></rect></property><property name="windowTitle"><string>CountingMainWindow</string></property><widget class="QWidget" name="centralwidget"><widget class="QPushButton" name="pushButton"><property name="geometry"><rect><x>10</x><y>10</y><width>136</width><height>41</height></rect></property><property name="sizePolicy"><sizepolicy hsizetype="Minimum" vsizetype="Expanding"><horstretch>0</horstretch><verstretch>0</verstretch></sizepolicy></property><property name="font"><font><pointsize>24</pointsize></font></property><property name="text"><string>Clicked:</string></property></widget><widget class="QLCDNumber" name="lcdNumber"><property name="geometry"><rect><x>410</x><y>180</y><width>64</width><height>23</height></rect></property><property name="sizePolicy"><sizepolicy hsizetype="Minimum" vsizetype="Expanding"><horstretch>0</horstretch><verstretch>0</verstretch></sizepolicy></property><property name="font"><font><pointsize>24</pointsize></font></property><property name="smallDecimalPoint"><bool>false</bool></property><property name="mode"><enum>QLCDNumber::Hex</enum></property></widget></widget><widget class="QStatusBar" name="statusbar"/></widget><resources/><connections/>
</ui>

在这里插入图片描述

技术要素

这个游戏中展示了大量好玩的东西。

资源文件

资源文件的定义和访问是一个很好的方式,pyrcc5命令把图形文件、数据文件编译成二进制的形式,在程序中就能够以:imgs/click.png:stylesheets/style.qss
这样的形式访问。在打包文件或者提供程序的时候,只需要提供pyrcc5生成的py文件就行。

这里值得注意的时读入qss文件的那个函数。

    with open(":stylesheets/style.qss") as fid:print(fid.read())

经过测试是不行的,QFile才行。但是QFile读出来的是QByteArray,要用str来转换成字符串。

def read_qss_file(filename: str) -> str:file = QFile(filename)if not file.open(QIODevice.ReadOnly | QIODevice.Text):raise IOError(f"Cannot open file: {filename}")qss = str(file.readAll(), encoding="utf-8")return qss

图形文件用QIcon(":imgs/click.png")可以访问。

StyleSheets

这个程序里面采用了setStyleSheet的方式来设置控件的显示方式,也是一个很有意思的话题。因为这个话题很大,就不再这里详细讲述。

QMainWindow设置

为了设置成背景透明,全屏疯跑,对QMainWindow进行了设置。

self.setAttribute(Qt.WA_TranslucentBackground)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setWindowState(Qt.WindowFullScreen)

第一个函数是属性,WindowAttribute,这组枚举类型用WA开头,背景透明就是其中之一。这个Attribute列表那么长,我就不列了:Attribute。

setWindowFlags是设置窗口的特性。枚举列表在窗体特性。

setWindowState是设置窗口的状态。

  • Qt::WindowNoState 常规状态
  • Qt::WindowMinimized 最小化状态
  • Qt::WindowMaximized 最大化状态
  • Qt::WindowFullScreen 全屏状态
  • Qt::WindowActive 活动状态(例如键盘输入焦点)

这三个状态一设,就有了我们的按钮精灵可以到处跑。

窗体几何

这段让按钮到处跑的代码中使用geometrysetGeometry这一对函数来实现。这一对函数获得的是一个QRect,包括x,y,w,h,位置坐标(左上角)和长宽。这些尺寸都是相对于夫控件来定义的。

def move_widgets_like_crazy(self, check: bool):self.pushButton: QPushButtonself.lcdNumber: QLCDNumber# geometry return position related to its parent# relocated pushbuttonrect_window: QRect = self.geometry()rect_button: QRect = self.pushButton.geometry()x = randint(10, rect_window.width() - rect_button.width() - 10)y = randint(10, rect_window.height() - rect_button.height() - 10)rect_button.setX(x)rect_button.setY(y)self.pushButton.setGeometry(rect_button)# lcdnumber moving toward pushbuttonrect_lcd: QRect = self.lcdNumber.geometry()dx = rect_button.x() - rect_lcd.x()rect_lcd.setX(rect_lcd.x() + dx // 3)dy = rect_button.y() - rect_lcd.y()rect_lcd.setY(rect_lcd.y() + dy // 3)self.lcdNumber.setGeometry(rect_lcd)

结论

  1. 实现桌面精灵在PyQt5里面很简单,设置窗口的属性就可以;
  2. PyQt5可以把资源文件整合到程序中,作为一个py文件,在Qt5中就直接编译到exe中;
  3. 控件的直接定位用geometrysetGoemetry完成,x,y的数值是相对于父节点的左上角定义的。

  1. 作弊码:按C,疯狂点击;按空格,相当于点击;按R重置技术;按ESC,退出。 ↩︎

相关文章:

PyQt5桌面应用开发(11):摸鱼也要讲基本法之桌面精灵

本文目录 PyQt5桌面应用系列鼠标不要钱&#xff0c;手腕还不要钱吗&#xff1f;PyQt5源程序python文件资源定义界面定义文件 技术要素资源文件StyleSheetsQMainWindow设置窗体几何 结论 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQ…...

Talk预告 | 大连理工大学IIAU Lab在读博士生严彬:走向通用实例感知

本期为TechBeat人工智能社区第495期线上Talk&#xff01; 北京时间5月10日(周三)20:00&#xff0c;大连理工大学IIAU Lab在读博士生—严彬的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “走向通用实例感知”&#xff0c;届时将介绍和探讨通用实…...

2023-05-04 LeetCode每日一题(摘水果)

2023-05-04每日一题 一、题目编号 2106. 摘水果二、题目链接 点击跳转到题目位置 三、题目描述 在一个无限的 x 坐标轴上&#xff0c;有许多水果分布在其中某些位置。给你一个二维整数数组 fruits &#xff0c;其中 fruits[i] [positioni, amounti] 表示共有 amounti 个水…...

[工具]Pytorch-lightning的使用

Pytorch-lightning的使用 Pytorch-lightning介绍Pytorch-lightning与Pytorch的区别Pytorch-lightning框架的优势Pytorch-lightning框架 重要资源 Pytorch-lightning介绍 这里介绍Pytorch_lighting框架. Pytorch-lightning与Pytorch的区别 Pytorch-lightning可以简单的看作是…...

互联网摸鱼日报(2023-05-09)

互联网摸鱼日报&#xff08;2023-05-09&#xff09; InfoQ 热门话题 面向数字化提质提效的低代码架构设计 | 低代码技术内幕 提升字节规模化效能的平台化思路 &#xff5c; 极客有约 从微服务转为单体架构、成本降低 90%&#xff0c;亚马逊内部案例引发轰动&#xff01;CTO&…...

MySQL常见的存储引擎

InnoDB&#xff1a;InnoDB是一种兼顾高可靠性和高性能的通用存储引擎&#xff0c;在MySQL 5.5之后&#xff0c;InnoDB是默认的MySQL存储引擎。 特点&#xff1a;1、DML操作遵循ACID模型&#xff0c;支持事务; 2、行级锁&#xff0c;提高并发访问性能; 3、支持外键FOREIGN KEY约…...

迅为i.MX6ULL开发板生成 KEY 文件,并安装

使用“ssh-keygen” 生成个四个 key 文件“ssh_host_rsa_key” “ssh_host_dsa_key” “ssh_host_ecdsa_key” 和“ssh_host_ed25519_key” 。 1 在虚拟机 Ubuntu 控制台&#xff0c; “ /home/ssh/openssh-4.6p1” 目录下&#xff0c; 使用命 令“ssh-keygen -t rsa -f ssh…...

常见舆情监测系统的分类和特点

随着网络和社交媒体的发展&#xff0c;舆情监测系统逐渐成为企业和政府机构必备的工具之一。舆情监测系统可以帮助企业和政府机构全面了解公众对其品牌、产品、政策等的反应和态度&#xff0c;及时发现和解决问题&#xff0c;提高公信力和形象。本文将介绍常见的舆情监测系统的…...

联合群美叶彦文:坚持,只要有一口气,能坚持多久,就坚持多久

创业之路的成败得失就看有多坚持。 成功并不是终点&#xff0c;失败并不是终结&#xff0c;只有勇气才是永恒。 Success is not final,failure is not fatal,it is the courage to continue that counts. ——温斯顿丘吉尔 迪斯雷利曾经说过&#xff1a;“成功的奥秘在于目标…...

动态规划的学习

文章目录 动态规划的学习一、什么是动态规划&#xff1f;二、如何思考状态转移方程&#xff1f;三、动态规划的基本原理1.[509. 斐波那契数](https://leetcode.cn/problems/fibonacci-number/)1.1 暴力递归解法&#xff1a;1.1.1 递归算法的时间复杂度那为什么时间复杂度会这么…...

计算机网络:HTTPS

目录 HTTP 与 HTTPS 有哪些区别&#xff1f;HTTPS 解决了 HTTP 的哪些问题HTTPS 是如何建立连接的&#xff1f;其间交互了什么TLS 协议建立的详细流程客户端校验数字证书的流程是怎样的&#xff1f; HTTPS 的应用数据是如何保证完整性的HTTPS 一定安全可靠吗参考资料 HTTP 与 H…...

数据库系列-什么是 JDBC?它的作用是什么?

JDBC&#xff08;Java Database Connectivity&#xff09;是 Java 语言提供的一种访问数据库的标准接口&#xff0c;它定义了一组 Java 接口和类&#xff0c;用于实现 Java 程序与各种关系型数据库的连接和交互。JDBC 的主要作用是提供了一种标准的、可靠的、跨平台的方式来访问…...

C++学习day--08 数组和字符串

1、什么是数组 数组&#xff0c;就是多个元素的有序“组合”。 C 和 C语言中的数组&#xff1a; 1 &#xff09;由多个大小相同的小柜子组成 > 相同大小的内存块组成&#xff0c;即相同类型的数据 2 &#xff09;这些小柜子&#xff0c;有自己对应的编号 > 编号从 …...

系统分析师之系统测试与维护(十六)

目录 一、 测试与评审 1.1 测试类型 1.2 测试阶段 1.3 面向对象的测试 1.4 测试自动化 1.5 软件调试 1.6 软件评审 1.7 验收与确认 二、软件质量管理 2.1 软件过程改进-CMMI 2.2 软件开发环境与工具 三、系统运行与评价 3.1 系统转换计划 3.1.1 遗留系统演化策略…...

板材激光切割机切割穿孔时注意的几个问题

激光切割设备广泛应用于钣金、五金制品、钢结构、汽车配件、广告、工艺品等行业&#xff0c;成为加工行业不可缺少的环节。在厚板加工中穿孔时间占很大比重&#xff0c;随着加工板材越来越厚&#xff0c;板材激光切割机切割穿孔也会相应地增加难度。 激光切割机两种常见的穿孔方…...

奶爸式Swagger教学

目录 一、导入依赖 二、SwaggerConfig基础编程 三、Swagger 常用说明注解 1.API 2.ApiOperation 3.ApiModel 4.ApiModelProperty 5.ApiParam 6.ApilmplicitParam 一、导入依赖 <!--开启Swagger --><!-- https://mvnrepository.com/artifact/io.springf…...

入门级的家用洗地机怎么样?入门级洗地机推荐

洗地机的功能有很多&#xff0c;比如除菌、洗地机清洁地面的确是一把好手。但是&#xff01;清洁完之后还要手动清洗洗地机&#xff0c;是一件麻烦事啊&#xff01;现在市面上大部分洗地机都有自清洁这个功能&#xff0c;但是很多洗地机的自清洁并不算真正的自清洁&#xff0c;…...

【面试】Java 反射机制(常见面试题)

文章目录 前言一、反射是什么&#xff1f;二、为什么要有反射三、反射 API3.1 获取 Class 对象的三种方式3.2 获取成员变量3.3 获取构造方法3.4.获取非构造方法 四、实践五、常见面试题5.1. 什么是反射&#xff1f;5.2. 哪里用到反射机制&#xff1f;5.3. 什么叫对象序列化&…...

JavaScript最佳实践

JavaScript最佳实践 2023.5.8版权声明&#xff1a;本文为博主chszs的原创文章&#xff0c;未经博主允许不得转载。 JavaScript 是一种动态编程语言&#xff0c;可让开发者创建动态和交互式 Web 应用程序。然而&#xff0c;编写 JavaScript 代码比较具有挑战性&#xff0c;尤其…...

景23转债,海能转债上市价格预测

景23转债 基本信息 转债名称&#xff1a;景23转债&#xff0c;评级&#xff1a;AA&#xff0c;发行规模&#xff1a;11.54亿元。 正股名称&#xff1a;景旺电子&#xff0c;今日收盘价&#xff1a;22.52元&#xff0c;转股价格&#xff1a;25.71元。 当前转股价值 转债面值 / …...

TDengine 部署与使用----时序数据库

官网 通过 Docker 快速体验 TDengine | TDengine 文档 | 涛思数据 docker安装 拉取最新docker镜像 docker pull tdengine/tdengine:latest 然后执行 docker run -d -p 6030:6030 -p 6041:6041 -p 6043-6049:6043-6049 -p 6043-6049:6043-6049/udp tdengine/tdengine 查看容器…...

ShardingSphere系列四(Sharding-JDBC内核原理及核心源码解析)

文章目录 1. ShardingSphere内核解析1.1 解析引擎1.2 路由引擎1.3 改写引擎1.4 执行引擎1.5 归并引擎 2. ShardingSphere的SPI扩展点2.1 SPI机制2.2 ShardingSphere中的SPI扩展点2.3 实现自定义主键生成策略 3. ShardingSphere源码 1. ShardingSphere内核解析 ShardingSphere虽…...

【2023】华为OD机试真题全语言-题目0234-字符串重新排列

题目0234-字符串重新排列 题目描述 给定一个字符串s,s包括以空格分隔的若干个单词,请对s进行如下处理后输出: 单词内部调整:对每个单词字母重新按字典序排序单词间顺序调整: 统计每个单词出现的次数,并按次数降序排列次数相同,按单词长度升序排列次数和单词长度均相同…...

Springboot +Flowable,三种常见网关的使用(排他、并行、包容网关)(一)

一.简介 Flowable 中常用的网关主要有三种类型&#xff0c;分别是&#xff1a; 排他网关并行网关包容网关 下面来说下这三种的网关的概念和用法。 二.排他网关 排他网关&#xff0c;也叫互斥网关&#xff0c;截图如下&#xff1a; 排他网关有一个入口&#xff0c;多个有效…...

软考高项(一)信息化发展 ★重点集萃★

1、信息是确定性的增加。信息不是物质&#xff0c;也不是能力。 2、信息的特征与质量&#xff0c;主要包括&#xff1a;客观性、普遍性、无限性、动态性、相对性、依附性、变换性、传递性、层次性、系统性和转化性等。 3、信息的质量属性&#xff0c;主要包括&#xff1a;精确…...

大项目准备(2)

目录 中国十大最具发展潜力城市 docker是什么&#xff1f;能介绍一下吗&#xff1f; 中国十大最具发展潜力城市 按照人随产业走、产业决定城市兴衰、规模经济和交通成本等区位因素决定产业布局的基本逻辑&#xff0c;我们在《中国城市发展潜力排名&#xff1a;2022》研究报告…...

计算机网络【2】 子网掩码

学习大佬记下的笔记 https://zhuanlan.zhihu.com/p/163119376 "子网"掩码&#xff0c;顾名思义&#xff0c;它就是拿来划分子网的&#xff0c;更准确的说&#xff0c;划分子网的同时&#xff0c;还能通过它知道主机在子网里面的具体ip的具体地址。 子网掩码只有一个…...

linux发行家族和发行版及安装软件方式

在Linux平台下&#xff0c;软件包的类型可以划分为两类&#xff1a;源码包、二进制包&#xff1b; 一个软件要在Linux上执行&#xff0c;必须是二进制文件&#xff1b; 源码包&#xff1a;即程序软件的源代码&#xff08;一般也叫Tarball&#xff0c;即将软件的源码以tar打包后…...

FE_Vue学习笔记 条件渲染[v-show v-if] 列表渲染[v-for] 列表过滤 列表排序

1 条件渲染 v-show v-if 使用template可以使其里面的内容在html的结构中不变。条件渲染&#xff1a; v-if 1&#xff09;v-if“表达式” 2&#xff09;v-else-if“表达式” 3&#xff09;v-else {} 适用于&#xff1a;切换频率较低的场景。特点&#xff1a;不展示的DOM元素直…...

基于C++实现旅行线路设计

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 系统根据风险评估&#xff0c;为旅客设计一条符合旅行策略的旅行线路并输出&#xff0c;系统能查询当前时刻旅客所处的地点和状态&#xff08;停留城市/所在交通工具&#xff09;。 实验内容和实验环境描述 1.1 实验内容 城…...