效果图


前言

我一直在用python 写一下有趣的东西,让编程不那么无聊,之前一直有写一个桌面宠物的想法,无奈这些都是依赖资源文件,没有图片资源没办法写里面的逻辑,直到我看见了 shimiji手机桌面宠物软件


这个软件提供了很多宠物的图片资源,这样就简单了,用 charles 对手机简单抓包,抓取到这些资源链接
http://pepeswap.com/mascot/78
另外示例图片链接
http://pepeswap.com/thumb/78
这里是78,其实号码从 3 到90 都是有资源的,就是没有1,2(1,2是软件内置的)
所以这里一共有 90-3+1=88个资源,这下子图片资源就解决了
然后编写代码

代码

先写一个管理这些资源的软件

  1. import sys
  2. from PyQt5.QtWidgets import *
  3. from PyQt5.QtGui import *
  4. from PyQt5.QtCore import *
  5. import requests
  6. import threading
  7. import os
  8. import zipfile
  9. from PIL import Image
  10. class Workchange(QThread):
  11. """docstring for WorkThread"""
  12. change_done = pyqtSignal()
  13. def __init__(self):
  14. super(Workchange, self).__init__()
  15. def run(self):
  16. url = self.url
  17. name = url.split('/')[-1] + '.zip'
  18. print('正在下载资源',name)
  19. data = requests.get(url).content
  20. with open(name,'wb') as f:
  21. f.write(data)
  22. print('下载完成!')
  23. path = os.environ['HOME']+'/shimeji/'
  24. if not os.path.exists(path):
  25. os.makedirs(path)
  26. print('正在解压资源...')
  27. z = zipfile.ZipFile(name, 'r')
  28. z.extractall(path=path)
  29. z.close()
  30. for i in range(1,47):
  31. os.rename(path + 'shime%s.png'% str(i),path+str(i)+'.png')
  32. pri_image = Image.open(path+'%s.png' %str(i))
  33. pri_image.transpose(Image.FLIP_LEFT_RIGHT).save(path+'-%s.png'%str(i))
  34. for i in os.listdir(path):
  35. os.system('convert %s %s'%(path+i,path+i))
  36. print('解压完成')
  37. os.remove(name)
  38. self.change_done.emit()
  39. class Workinit(QThread):
  40. """docstring for WorkThread"""
  41. init_done = pyqtSignal(dict)
  42. def __init__(self):
  43. super(Workinit, self).__init__()
  44. def run(self):
  45. for i in range(3,90):
  46. threading.Thread(target=self.load,args=(i,)).start()
  47. def load(self,i):
  48. url = ''' http://pepeswap.com/thumb/%s''' %str(i)
  49. data = requests.get(url).content
  50. name = str(i)
  51. dict_data = dict(data=data,name=name)
  52. self.init_done.emit(dict_data)
  53. class DQListWidget(QListWidget):
  54. def __init__(self):
  55. super(DQListWidget, self).__init__()
  56. self.workinit = Workinit()
  57. self.workchange = Workchange()
  58. self.workchange.change_done.connect(self.change_done)
  59. self.workinit.init_done.connect(self.load_picture)
  60. self.workinit.start()
  61. self.itemDoubleClicked.connect(self.change)
  62. def change_done(self):
  63. QMessageBox.about(self,'提示','更换完成!(*>﹏<*)')
  64. def change(self,item):
  65. self.workchange.url = 'http://pepeswap.com/mascot/' + item.text()
  66. self.workchange.start()
  67. def load_picture(self,dict_data):
  68. item = QListWidgetItem(dict_data['name'])
  69. item.setSizeHint(QSize(10, 128))
  70. self.addItem(item)
  71. pixmap = QPixmap()
  72. label = QLabel()
  73. pixmap.loadFromData(dict_data['data'])
  74. label.setPixmap(pixmap)
  75. self.setItemWidget(item,label)
  76. class Mywin(QWidget):
  77. def __init__(self):
  78. super(Mywin, self).__init__()
  79. list_ = DQListWidget()
  80. layout = QVBoxLayout(self)
  81. layout.addWidget(list_)
  82. self.setLayout(layout)
  83. app = QApplication(sys.argv)
  84. mywin = Mywin() # 实例化一个窗口小部件
  85. mywin.setWindowTitle('Hello world!') # 设置窗口标题
  86. mywin.show() #显示窗口
  87. sys.exit(app.exec())

这个程序双击列表中的条目即可下载并更换对应的宠物图片资源

主程序

  1. import sys
  2. from PyQt5.QtWidgets import *
  3. from PyQt5.QtGui import *
  4. from PyQt5.QtCore import *
  5. import time
  6. import random
  7. import os
  8. def random_probability(r):
  9. s = random.randint(1,100)
  10. if r >= s:
  11. return True
  12. else:
  13. return False
  14. class Donghua(QWidget):
  15. def __init__(self):
  16. super(Donghua, self).__init__()
  17. self.desktop = QApplication.desktop()
  18. self.screenRect = self.desktop.screenGeometry()
  19. self.HEIGHT = self.screenRect.height()
  20. self.WIDTH = self.screenRect.width()
  21. self.setWindowFlags(Qt.FramelessWindowHint)
  22. # self.setWindowFlags(Qt.SplashScreen)
  23. self.setAttribute(Qt.WA_TranslucentBackground)
  24. self.timer = QTimer()
  25. self.timer.timeout.connect(self.update)
  26. self.img_timer = QTimer()
  27. self.img_timer.timeout.connect(self.update_img)
  28. self.label = QLabel(self)
  29. self.label.setScaledContents(True)
  30. layout = QVBoxLayout(self)
  31. layout.addWidget(self.label)
  32. self.setLayout(layout)
  33. self.index = 0
  34. self.x = 0
  35. self.is_right = True
  36. self.m_flag = False
  37. self.action_dcit = {
  38. 'left_go':(1,3),
  39. 'right_go':(-3,-1),
  40. 'left_hold':(5,7),
  41. 'right_hold':(-7,-5),
  42. 'left_release':(4,4),
  43. 'right_release':(-4,-4),
  44. 'left_down':(18,19),
  45. 'right_down':(-19,-18),
  46. 'left_crawl':(12,14),
  47. 'right_crawl':(-14,-12),
  48. # 'left_rest':(15,17),
  49. # 'right_rest':(-17,-15),
  50. 'left_rest':(26,27),
  51. 'right_rest':(-27,-26),
  52. 'left_rest2':(27,29),
  53. 'right_rest2':(-29,-27),
  54. }
  55. self.action = 'right_release'
  56. self.pre_action = ''
  57. # 控制窗体移动及各种动作切换计时器
  58. self.timer.start(100)
  59. # 控制图片切换计时器
  60. self.img_timer.start(200)
  61. #监听鼠标动作
  62. def mousePressEvent(self, event):
  63. x = (event.globalPos()-self.pos()).x()
  64. y = (event.globalPos()-self.pos()).y()
  65. if event.button() == Qt.LeftButton and x < 128 and y < 128:
  66. self.m_flag = True
  67. self.m_Position = event.globalPos()-self.pos() # 获取鼠标相对窗口的位置
  68. event.accept()
  69. if self.is_right:
  70. self.action='right_hold'
  71. else:
  72. self.action='left_hold'
  73. self.setCursor(QCursor(Qt.OpenHandCursor))
  74. def mouseMoveEvent(self, QMouseEvent):
  75. if Qt.LeftButton and self.m_flag:
  76. self.move(QMouseEvent.globalPos()-self.m_Position) # 更改窗口位置
  77. QMouseEvent.accept()
  78. #鼠标左键释放
  79. def mouseReleaseEvent(self, QMouseEvent):
  80. self.m_flag = False
  81. if self.is_right:
  82. self.action = 'right_release'
  83. else:
  84. self.action = 'left_release'
  85. #手动将其放入屏幕边缘
  86. if self.x <= 0 and self.y > 0:
  87. self.action = 'left_crawl'
  88. elif self.x + self.width >= self.WIDTH and self.y > 0:
  89. self.action = 'right_crawl'
  90. self.setCursor(QCursor(Qt.ArrowCursor))
  91. #动作更新
  92. def update(self):
  93. self.width = self.geometry().width()
  94. self.height = self.geometry().height()
  95. self.x = self.geometry().x()
  96. self.y = self.geometry().y()
  97. # print(self.x,self.y)
  98. exec('self.%s()'% self.action)
  99. def right_crawl(self):
  100. if self.y > 0:
  101. self.y -= 10
  102. self.setGeometry(self.x,self.y,100,100)
  103. else:
  104. self.action = 'right_release'
  105. def left_crawl(self):
  106. if self.y > 0:
  107. self.y -= 10
  108. self.setGeometry(self.x,self.y,100,100)
  109. else:
  110. self.action = 'left_release'
  111. def right_down(self):
  112. if self.index+1 == self.action_dcit[self.action][1]:
  113. self.action = 'right_go'
  114. def left_down(self):
  115. if self.index+1 == self.action_dcit[self.action][1]:
  116. self.action = 'left_go'
  117. def right_release(self):
  118. if self.y + self.height > self.HEIGHT:
  119. self.action = 'right_down'
  120. else:
  121. self.action = 'right_release'
  122. self.y += 100
  123. self.setGeometry(self.x,self.y,100,100)
  124. def left_release(self):
  125. if self.y + self.height > self.HEIGHT:
  126. self.action = 'left_down'
  127. else:
  128. self.action = 'left_release'
  129. self.y += 100
  130. self.setGeometry(self.x,self.y,100,100)
  131. def right_go(self):
  132. self.x += 5
  133. self.action = 'right_go'
  134. if self.x + self.width> self.WIDTH:
  135. if random_probability(30):
  136. self.action = 'right_crawl'
  137. else:
  138. self.is_right = False
  139. self.action = 'left_go'
  140. if random_probability(1):
  141. self.action = 'right_rest'
  142. self.setGeometry(self.x,self.y,100,100)
  143. def left_go(self):
  144. self.x -= 5
  145. self.action = 'left_go'
  146. if self.x < 0:
  147. if random_probability(30):
  148. self.action = 'left_crawl'
  149. else:
  150. self.is_right = True
  151. self.action = 'right_go'
  152. if random_probability(1):
  153. self.action = 'left_rest'
  154. self.setGeometry(self.x,self.y,100,100)
  155. def right_rest(self):
  156. if random_probability(1):
  157. self.action = 'right_go'
  158. def left_rest(self):
  159. if random_probability(1):
  160. self.action = 'left_go'
  161. def right_hold(self):
  162. pass
  163. def left_hold(self):
  164. pass
  165. #更新图片
  166. def update_img(self):
  167. start_index,end_index = self.action_dcit[self.action]
  168. if self.pre_action != self.action:
  169. self.index = start_index
  170. self.pre_action = self.action
  171. if self.index == end_index:
  172. self.index = start_index
  173. else:
  174. self.index += 1
  175. q = QPixmap(path +'%s.png' % self.index)
  176. self.label.setPixmap(q)
  177. if __name__ == '__main__':
  178. path = os.environ['HOME']+'/shimeji/'
  179. app = QApplication(sys.argv)
  180. mywin = Donghua()
  181. mywin.show()
  182. sys.exit(app.exec())

写一个linux平台的桌面宠物的更多相关文章

  1. 如何给LG gram写一个Linux下的驱动?

    其实就是实现一下几个Fn键的功能,没有标题吹得那么牛. 不知道为啥,LG gram这本子意外的小众. 就因为这个,装Linux遇到的硬件问题就没法在网上直接搜到解决办法了. Fn + F9 实现阅读模 ...

  2. 如何成为一个Linux内核开发者

    你想知道如何成为一个Linux内核开发者么?或者你的老板告诉你,“去为这个设备写一个Linux驱动.“这篇文档的目的,就是通过描述你需要 经历的过程和提示你如何和社区一起工作,来教给你为达到这些目的所 ...

  3. Linux i2c子系统(一) _动手写一个i2c设备驱动

    i2c总线是一种十分常见的板级总线,本文以linux3.14.0为参考, 讨论Linux中的i2c驱动模型并利用这个模型写一个mpu6050的驱动, 最后在应用层将mpu6050中的原始数据读取出来 ...

  4. linux设备驱动第三篇:如何写一个简单的字符设备驱动?

    在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存 ...

  5. linux设备驱动第三篇:写一个简单的字符设备驱动

          在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分 ...

  6. 转:一个跨WINDOWS LINUX平台的线程类

     来源:http://blog.csdn.net/dengxu11/article/details/7232681 继Windows下实现一个CThread封装类之后,这里我再实现一个跨WINDOWS ...

  7. 写一个python脚本监控在linux中的进程

    在虚拟机中安装Linux中的CentOS7系统 https://baijiahao.baidu.com/s?id=1597320700700593557&wfr=spider&for= ...

  8. 写一个小CTF平台

    0x00.前言 协会要举办信息安全大赛了,初赛的web+crypto+misc主要由我来出题,注册.比赛的平台也都要由我来写    上周日完成了注册页面的后端(前端由另一个女生写的),前天下午大概完成 ...

  9. 利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 前面两篇文章已 ...

  10. 如何配置一个路径,能够既适合Linux平台,又适合Windows平台,可以从这个路径中读取文件

    如何配置一个路径,能够既适合Linux平台,又适合Windows平台,可以从这个路径中读取文件? 目的:就是希望在项目的配置文件中配上一样的路径,不管协作者使用的是什么平台,都能够读到文件. 比如:L ...

随机推荐

  1. 8. Ceph 基础篇 - 运维常用操作

    文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247485300&idx=1&sn=aacff9f7 ...

  2. MySQL 的七种日志总结

    文章转载自:https://mp.weixin.qq.com/s/ewv7HskHvH3O7kFyOmoqgw 一.MySQL 日志分类 日志类别 说明 备注 错误日志 错误日志记录了当MySQL启动 ...

  3. centos7安装sonarqube-9.2.4

    官方文档地址:https://docs.sonarqube.org/latest/requirements/requirements/ 使用 sonarqube 对 java 项目代码进行扫描的时候, ...

  4. 阿里云SLB的健康检查配置

    若阿里云SLB健康检查异常,则默认SLB无法访问到后端ECS,也就意味着通过SLB访问后端ECS上部署的服务会报502 gateway. 另一种办法是关闭健康检查(不推荐) 简要说明: SLB通过配置 ...

  5. Elasticsearch中的一些重要概念:cluster, node, index, document, shards及replica

    首先,我们来看下一下如下的这个图: Cluster Cluster也就是集群的意思.Elasticsearch集群由一个或多个节点组成,可通过其集群名称进行标识.通常这个Cluster 的名字是可以在 ...

  6. 0-mysql数据库下载及安装

    1 下载mysql源安装包 wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm 2 安装mysql源 yu ...

  7. H5调用微信支付

    这里用的是 vue项目; 首先在mounted中判断是否有openId,如果没有,则去获取 let openid = localStorage.getItem('openid'); if (!open ...

  8. Optional 常用方法总结

    转载请注明出处: Optional 类是 JAVA 8 提供的判断程序是否为空提供的包装工具类:可以减少代码中的 是否为空的判断,以及减少 NullPointerExceptions:使得程序变得更为 ...

  9. Vue+vant移动端处理弹窗不能滑动问题

    自己在做项目开发时,使用vantUI组件,在项目中遇到了弹窗组件里面当内容过多时,会出现滚动卡顿或者不能滚动问题,开始一直以为是自己的样式写的有问题,检查下来才发现并不是,而是弹窗组件的问题,于是找到 ...

  10. prometheus监控实战

    第一节.环境和软件版本 1.1.操作系统环境 主机ip 操作系统 部署软件 备注 192.168.10.10 Centos7.9 Grafana.Pushgateway.Blackbox Export ...