Some time ago, a little friend left a message saying that I would like to take you to write a small desktop pendant. Today, I would like to meet the request of a little friend who has left similar words. But I feel that it is not interesting to write a desktop calendar, so I will simply take you to make a desktop pet~
Don't talk too much. Let's start happily~
Python version: 3.6.4 Related modules: PyQt5 module; And some modules that come with Python.
Since you want to write a desktop pet, first of all, you need to find the pet's picture material. Here we use PET image materials from shimiji mobile APP, such as Picchu:
I have about 60 kinds of pet pictures for you to choose from:
It's packed and provided in related files, so there's no need to share the crawler code here (I picked it up, as long as it's not ugly, I basically kept it), and don't bring unnecessary pressure to other people's servers.
Next, we can start designing our desktop pets. Out of the ordinary official account, the desktop hanger written on python is basically based on tkinter. In order to highlight the difference of public numbers, we use PyQt5 to realize our desktop pets.
First, let's initialize a desktop pet window component:
class DesktopPet(QWidget): def __init__(self, parent=None, **kwargs): super(DesktopPet, self).__init__(parent) self.show()
It works like this:
Next, let's set the following window properties to make it more suitable for a pet window:
# Initialization self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint|Qt.SubWindow) self.setAutoFillBackground(False) self.setAttribute(Qt.WA_TranslucentBackground, True) self.repaint()
And randomly import a pet picture to see the running effect:
# Randomly import a pet self.pet_images, iconpath = self.randomLoadPetImages() # Currently displayed picture self.image = QLabel(self) self.setImage(self.pet_images)
The function code of randomly importing all pictures of a pet is as follows:
'''Randomly import all pictures of a desktop pet''' def randomLoadPetImages(self): pet_name = random.choice(list(cfg.PET_ACTIONS_MAP.keys())) actions = cfg.PET_ACTIONS_MAP[pet_name] pet_images =  for action in actions: pet_images.append([self.loadImage(os.path.join(cfg.ROOT_DIR, pet_name, 'shime'+item+'.png')) for item in action]) iconpath = os.path.join(cfg.ROOT_DIR, pet_name, 'shime1.png') return pet_images, iconpath
Of course, we also hope that every time a pet appears on the desktop, it will be more interesting:
'''Random to a location on a screen''' def randomPosition(self): screen_geo = QDesktopWidget().screenGeometry() pet_geo = self.geometry() width = (screen_geo.width() - pet_geo.width()) * random.random() height = (screen_geo.height() - pet_geo.height()) * random.random() self.move(width, height)
Now, when we run our program, it works like this:
It seems pretty good. Wait a minute. There seems to be a problem. After resetting the window properties, how can this thing exit? It seems strange to put a x in the top right corner of a pet?
Don't worry, we can add a tray icon to our desktop pet to realize the exit function of desktop pet program:
# Set exit options quit_action = QAction('Sign out', self, triggered=self.quit) quit_action.setIcon(QIcon(iconpath)) self.tray_icon_menu = QMenu(self) self.tray_icon_menu.addAction(quit_action) self.tray_icon = QSystemTrayIcon(self) self.tray_icon.setIcon(QIcon(iconpath)) self.tray_icon.setContextMenu(self.tray_icon_menu) self.tray_icon.show()
The effect is like this:
OK, it seems that there is a model. But it seems that it's not right. The position of the pet generated on the desktop is random every time, but we can't adjust the position of the pet. It's obviously unreasonable. As a desktop pet, you can't hinder the owner's work! Otherwise, let's write the functions when the mouse is pressed, moved and released, so that you can drag it with the mouse:
'''When the left mouse button is pressed, Pets will be bound to mouse position''' def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.is_follow_mouse = True self.mouse_drag_pos = event.globalPos() - self.pos() event.accept() self.setCursor(QCursor(Qt.OpenHandCursor)) '''Mouse movement, Pets move''' def mouseMoveEvent(self, event): if Qt.LeftButton and self.is_follow_mouse: self.move(event.globalPos() - self.mouse_drag_pos) event.accept() '''When the mouse is released, Unbind''' def mouseReleaseEvent(self, event): self.is_follow_mouse = False self.setCursor(QCursor(Qt.ArrowCursor))
The effect is as follows:
Ha ha, it's getting more and more decent. Finally, as a lively pet, you can't be so rigid and motionless, can you? Do you want to learn to make faces to make the host happy? OK, let's set a timer first:
# Do an action every once in a while self.timer = QTimer() self.timer.timeout.connect(self.randomAct) self.timer.start(500)
The timer switches the selected pet's pictures every other period of time to achieve the animation effect of the pet's expression action (the basic content of the video is composed of one frame of pictures doesn't need me to popularize it). Of course, here we must classify the pictures (pictures of the same action belong to the same category) to ensure the consistency of the pet's expression actions. Specifically, the code implementation is as follows:
'''Do a random action''' def randomAct(self): if not self.is_running_action: self.is_running_action = True self.action_images = random.choice(self.pet_images) self.action_max_len = len(self.action_images) self.action_pointer = 0 self.runFrame() '''Complete every frame of the action''' def runFrame(self): if self.action_pointer == self.action_max_len: self.is_running_action = False self.action_pointer = 0 self.action_max_len = 0 self.setImage(self.action_images[self.action_pointer]) self.action_pointer += 1
OK, it's finished. See the related documents for the complete source code.