Python实践项目讲解:如何用制作一个桌面宠物

news2024/11/24 13:34:36

制作一个桌面宠物(Desktop Pet)在Python中通常涉及多个步骤,包括创建宠物的图形界面、添加动画效果、处理用户交互等。下面是一个简化的步骤指南,帮助你开始使用Python制作桌面宠物:

  1. 选择图形库
    • Tkinter(Python自带的图形库,简单但功能有限)。
    • Pygame(适用于游戏和多媒体应用,功能强大)。
    • PyQt 或 PySide(跨平台的图形用户界面工具包,用于创建复杂的桌面应用)。
    • 第三方库如Kivy(多平台Python库,用于开发多触摸应用)或wxPython(另一个跨平台的GUI工具包)。
  2. 设计宠物形象
    • 你可以使用图像编辑软件(如Adobe Photoshop、GIMP等)来创建宠物的图片或动画。
    • 宠物可以有不同的状态,比如睡觉、跑动、吃东西等,每种状态对应不同的图片或动画。
  3. 编写代码
    • 初始化图形窗口,并加载宠物的初始状态图片。
    • 编写代码来处理宠物的动画,比如定期更换图片来模拟宠物的动作。
    • 添加用户交互功能,比如用户可以点击或拖动宠物来移动它,或者与宠物进行简单的互动。
  4. 添加逻辑
    • 根据用户的操作或时间的变化,更新宠物的状态和行为。
    • 可以添加一些随机性,使宠物的行为看起来更自然。
  5. 测试与调试
    • 在不同的操作系统和配置上测试你的桌面宠物,确保它能在各种环境下正常工作。
    • 调试并修复任何发现的问题。
  6. 打包与发布
    • 使用如PyInstallercx_Freeze等工具将你的应用打包成一个可执行文件。
    • 发布你的桌面宠物,可以分享到网上供其他人下载和使用。

运行结果:

Python代码示例:(代码不完整,完整代码请看文末图片)

我基本上快发完了,你们先自己试一下能不能写完它

ps:图片自己可以找,不一定要我的

import sys
import os
import random
from PyQt5 import QtWidgets, QtGui, QtCore

class DeskPet(QtWidgets.QLabel):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.childPets = []
        self.isDragging = False
        self.isMoving = False
        self.change = False

    def initUI(self):
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setGeometry(500, 500, 130, 130)
        self.currentAction = self.startIdle
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.updateAnimation)
        self.changeDirectionTimer = QtCore.QTimer(self)  # 添加定时器
        self.changeDirectionTimer.timeout.connect(self.changeDirection)  # 定时器触发时调用changeDirection方法
        self.startIdle()
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showMenu)
        self.setMouseTracking(True)
        self.dragging = False

    def loadImages(self, path):
        return [QtGui.QPixmap(os.path.join(path, f)) for f in os.listdir(path) if f.endswith('.png')]

    def startIdle(self):
        self.setFixedSize(130, 130)
        self.currentAction = self.startIdle
        self.images = self.loadImages("Deskpet/resource/xianzhi")
        self.currentImage = 0
        self.timer.start(100)
        self.moveSpeed = 0
        self.movingDirection = 0
        if self.changeDirectionTimer.isActive():
            self.changeDirectionTimer.stop()  # 停止方向改变的定时器

    def startWalk(self):
        self.setFixedSize(130, 130)
        if not self.isDragging:
            self.currentAction = self.startWalk
            direction = random.choice(["zuo", "you"])
            self.images = self.loadImages(f"Deskpet/resource/sanbu/{direction}")
            self.currentImage = 0
            self.movingDirection = -1 if direction == "zuo" else 1
            self.moveSpeed = 10
            self.timer.start(100)
            self.changeDirectionTimer.start(3000)  # 启动定时器

    def movePet(self):
        screen = QtWidgets.QDesktopWidget().screenGeometry()
        new_x = self.x() + self.movingDirection * self.moveSpeed
        if new_x < 10:
            new_x = 10
            if self.currentAction == self.startWalk:
                self.movingDirection *= -1
                # 停止加载原先的图片
                self.timer.stop()
                self.images = []  # 清空当前图片列表
                if self.movingDirection == -1:  # 向左移动
                    self.images = self.loadImages("Deskpet/resource/sanbu/zuo")
                else:  # 向右移动
                    self.images = self.loadImages("Deskpet/resource/sanbu/you")

                self.currentImage = 0
                self.timer.start(100)
        elif new_x > screen.width() - self.width() - 10:
            new_x = screen.width() - self.width() - 10
            if self.currentAction == self.startWalk:
                self.movingDirection *= -1
                # 停止加载原先的图片
                self.timer.stop()
                self.images = []  # 清空当前图片列表
                # 根据移动方向加载对应的图片
                if self.movingDirection == -1:  # 向左移动
                    self.images = self.loadImages("Deskpet/resource/sanbu/zuo")
                else:  # 向右移动
                    self.images = self.loadImages("Deskpet/resource/sanbu/you")

                self.currentImage = 0
                self.timer.start(100)
        self.deskpet_rect = self.geometry()
        for child in self.childPets:
            if isinstance(child, XiaobaiWindow):
                self.xiaobai_rect = child.geometry()
                if self.deskpet_rect.intersects(self.xiaobai_rect):
                    child.close()
                    self.startMeet()
        self.move(new_x, self.y())

    def startMeet(self):
        self.setFixedSize(150, 150)
        self.currentAction = self.startMeet
        self.images = self.loadImages("Deskpet/resource/meet")
        self.currentImage = 0
        self.moveSpeed = 0
        self.movingDirection = 0
        self.timer.start(30)

    def startLift(self):
        self.setFixedSize(160, 160)
        self.currentAction = self.startLift
        self.images = self.loadImages("Deskpet/resource/linqi")
        self.currentImage = 0
        self.moveSpeed = 0
        self.movingDirection = 0
        self.timer.start(100)

    def startFall(self):
        self.setFixedSize(150, 150)
        self.currentAction = self.startFall
        self.images = self.loadImages("Deskpet/resource/xialuo")
        self.currentImage = 0
        self.movingDirection = 0
        self.moveSpeed = 5
        self.stopOtherActions()
        self.timer.start(30)

    def stopOtherActions(self):
        self.timer.stop()
        if self.currentAction == self.startWalk:
            self.changeDirectionTimer.stop()  # 停止方向判定定时器
            self.startIdle()
        elif self.currentAction == self.startLift:
            self.startIdle()
        elif self.currentAction == self.startFall:
            pass
        else:
            self.startIdle()

    def updateAnimation(self):
        self.setPixmap(self.images[self.currentImage])
        self.currentImage = (self.currentImage + 1) % len(self.images)
        if hasattr(self, 'movingDirection'):
            if self.currentAction == self.startFall:
                self.fallPet()
            else:
                self.movePet()

    def fallPet(self):
        self.setFixedSize(130, 130)
        screen = QtWidgets.QDesktopWidget().screenGeometry()
        new_y = self.y() + self.moveSpeed
        if new_y > screen.height() - self.height() - 10:
            new_y = screen.height() - self.height() - 10
            self.timer.stop()
            self.startIdle()
        self.move(self.x(), new_y)

    def showMenu(self, position):
        menu = QtWidgets.QMenu()
        if self.currentAction == self.sleep:
            menu.addAction("偷吃宵夜", self.Snack)
            menu.addAction("唤醒", self.WakeUp)
            menu.addSeparator()
            menu.addAction("隐藏", self.minimizeWindow)
            menu.addAction("退出", self.close)
        else:
            menu.addAction("散步", self.startWalk)
            menu.addAction("下落", self.startFall)
            menu.addAction("运动", self.exercise)
            menu.addAction("吃饭", self.eating)
            menu.addAction("睡觉", self.sleep)
            menu.addAction("屁屁舞", self.pipi)
            menu.addAction("分身术", self.clonePet)
            menu.addAction("动感光波!", self.transform)
            menu.addAction("呼唤小白", self.summonXiaobai)
            menu.addAction("测试", self.startMeet)
            child_menu = menu.addMenu("小彩蛋")
            child_menu.addAction("开发者的Q/A", self.starttalk)
            child_menu.addAction("小游戏", self.transform)
            menu.addSeparator()
            menu.addAction("停止", self.startIdle)
            menu.addAction("隐藏", self.minimizeWindow)
            menu.addAction("退出", self.close)
        menu.exec_(self.mapToGlobal(position))

    def Snack(self):
        self.setFixedSize(160, 130)
        self.currentAction = self.sleep
        self.images = self.loadImages("Deskpet/resource/snack")
        self.currentImage = 0
        self.timer.start(100)
        self.moveSpeed = 0
        self.movingDirection = 0
        QtCore.QTimer.singleShot(len(self.images) * 100, self.sleep)


    def transform(self):
        self.setFixedSize(160, 130)
        self.currentAction = self.transform
        self.images = self.loadImages("Deskpet/resource/xiandanchaoren")
        self.currentImage = 0
        self.timer.start(100)
        self.moveSpeed = 0
        self.movingDirection = 0

    def pipi(self):
        self.setFixedSize(300, 130)
        self.currentAction = self.pipi
        self.images = self.loadImages("Deskpet/resource/pipi")
        self.currentImage = 0
        self.timer.start(25)
        self.moveSpeed = 0
        self.movingDirection = 0

    def exercise(self):
        self.setFixedSize(150,180 )
        self.currentAction = self.exercise
        self.images = self.loadImages("Deskpet/resource/yundong")
        self.currentImage = 0
        self.timer.start(125)
        self.moveSpeed = 0
        self.movingDirection = 0

    def eating(self):
        self.setFixedSize(160, 90)
        self.currentAction = self.eating
        self.images = self.loadImages("Deskpet/resource/eat")
        self.currentImage = 0
        self.timer.start(25)
        self.moveSpeed = 0
        self.movingDirection = 0
        QtCore.QTimer.singleShot(len(self.images) * 30, self.startIdle)

    def sleep(self):
        self.setFixedSize(315, 500)
        self.currentAction = self.sleep
        self.images = self.loadImages("Deskpet/resource/sleep")
        self.currentImage = 0
        self.timer.start(155)
        self.moveSpeed = 0
        self.movingDirection = 0

    def showWakeUpMenu(self):
        self.setFixedSize(130, 130)
        self.sleeping = True
        menu = QtWidgets.QMenu()
        menu.addAction("唤醒", self.wakeUp)
        menu.exec_(self.mapToGlobal(self.pos()))

    def WakeUp(self):
        self.setFixedSize(180, 180)
        self.sleeping = False
        self.currentAction = self.WakeUp
        self.images = self.loadImages("Deskpet/resource/waken")
        self.currentImage = 0
        self.timer.start(30)
        # 延时,等待所有图片加载完成
        QtCore.QTimer.singleShot(len(self.images) * 30, self.finishWakeUp)

    def Ninjia(self):
        self.setFixedSize(160, 150)
        self.sleeping = False
        self.currentAction = self.Ninjia
        self.images = self.loadImages("Deskpet/resource/Ninjia")
        self.currentImage = 0
        self.timer.start(30)
        # 延时,等待所有图片加载完成
        QtCore.QTimer.singleShot(len(self.images) * 30, self.startIdle)

    def Ninjia2(self):
        new_pet = DeskPet()
        self.childPets.append(new_pet)
        self.setFixedSize(160, 150)
        self.sleeping = False
        self.currentAction = self.Ninjia2
        self.images = self.loadImages("Deskpet/resource/Ninjia2")
        self.currentImage = 0
        self.timer.start(30)
        # 延时,等待所有图片加载完成
        QtCore.QTimer.singleShot(len(self.images) * 30, self.startIdle)

    def finishWakeUp(self):
        self.movingDirection = 0
        self.wakeUpImagesLoaded = True
        self.setFixedSize(180, 180)
        self.timer.stop()
        self.currentAction = self.startIdle
        self.images = self.loadImages("Deskpet/resource/xianzhi")
        self.currentImage = 0
        self.timer.start(100)

    def clonePet(self):
        new_pet = DeskPet()
        self.childPets.append(new_pet)
        self.Ninjia()
        new_pet.show()
        new_pet.Ninjia2()

    def starttalk(self):
        starttalk = ChatApp()
        starttalk.show()
        self.childPets.append(starttalk)

    def summonXiaobai(self):
        xiaobai = XiaobaiWindow()
        xiaobai.show()
        self.childPets.append(xiaobai)

    def closeEvent(self, event):
        for child in self.childPets:
            child.close()  # 关闭所有子窗口
        super().closeEvent(event)

    def minimizeWindow(self):
        self.showMinimized()

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.dragging = True
            self.isDragging = True
            self.drag_position = event.globalPos() - self.pos()
            self.prevAction = self.currentAction
            self.startLift()

            event.accept()

    def mouseMoveEvent(self, event):
        if QtCore.Qt.LeftButton and self.dragging:
            self.move(event.globalPos() - self.drag_position)
            event.accept()

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.dragging = False
            self.isDragging = False

            # 根据需要重新启动changeDirectionTimer
            if self.currentAction == self.startWalk:
                self.changeDirectionTimer.start()

            self.prevAction()  # 或者 self.startIdle(), 根据之前的动作恢复状态
            event.accept()

    def changeDirection(self):
        if self.currentAction == self.startFall or self.currentAction == self.eating or self.currentAction == self.transform or self.currentAction == self.sleep or self.currentAction == self.pipi or self.currentAction == self.exercise or self.currentAction == self.WakeUp or self.currentAction == self.startIdle or self.startMeet:
            return  # 如果正在执行下落动作,不改变方向

        if random.random() < 0.5:  # 随机选择是否改变方向
            self.movingDirection *= -1
            self.change = True
            if self.change == True:
                # 停止加载原先的图片
                self.timer.stop()
                self.images = []  # 清空当前图片列表
                self.startWalk()
                self.change = False

class XiaobaiWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setGeometry(500, 500, 125, 100)
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.updateAnimation)
        self.images = self.loadImages("Deskpet/resource/xiaobai")
        self.currentImage = 0
        self.timer.start(20)
        self.dragPosition = QtCore.QPoint()
        self.label = QtWidgets.QLabel(self)
        self.label.setGeometry(0, 0, 140, 100)

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()
            event.accept()

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton:
            self.move(event.globalPos() - self.dragPosition)
            event.accept()

    def showMenu(self, position):
        menu = QtWidgets.QMenu()
        menu.addAction("隐藏", self.minimizeWindow)
        menu.addAction("回去", self.close)
        menu.exec_(self.mapToGlobal(position))

    def loadImages(self, path):
        return [QtGui.QPixmap(os.path.join(path, f)) for f in os.listdir(path) if f.endswith('.png')]

    def updateAnimation(self):
        self.label.setPixmap(self.images[self.currentImage])
        self.currentImage = (self.currentImage + 1) % len(self.images)

    def minimizeWindow(self):
        self.showMinimized()

    def closeEvent(self, event):
        self.timer.stop()
        super().closeEvent(event)

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.ContextMenu:
            self.showMenu(event.pos())
            return True
        return super().eventFilter(obj, event)

    def showEvent(self, event):
        self.installEventFilter(self)

class ChatApp(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('聊天窗口')
        layout = QtWidgets.QVBoxLayout()
        label = QtWidgets.QLabel("你好,我是开发者”乐子猪“\n请问你想问什么?\n(该聊天的内容不完善且功能有缺陷)")
        layout.addWidget(label)

        button1 = QtWidgets.QPushButton("开发者你是哪里人呀?")
        button1.clicked.connect(self.on_button1_clicked)
        layout.addWidget(button1)

        button2 = QtWidgets.QPushButton("开发者你是一个什么样的人呀?")
        button2.clicked.connect(self.on_button2_clicked)
        layout.addWidget(button2)

        button3 = QtWidgets.QPushButton("我想给开发者生猴子(〃ノωノ)")
        layout.addWidget(button3)

        self.new_window = None  # 新窗口实例作为成员变量
        self.setLayout(layout)

    def on_button1_clicked(self):
        self.new_window = QtWidgets.QWidget()
        self.new_window.setWindowTitle('新窗口')
        layout = QtWidgets.QVBoxLayout()
        label = QtWidgets.QLabel("我是广东人。(不过不是土生土长的)\n#请问你还想聊什么?")
        layout.addWidget(label)

        button4 = QtWidgets.QPushButton("开发者你喜欢吃什么")
        button4.clicked.connect(self.on_button4_clicked)
        layout.addWidget(button4)

        button3 = QtWidgets.QPushButton("我想给开发者生猴子(〃ノωノ)")
        layout.addWidget(button3)

        self.new_window.setLayout(layout)
        self.new_window.show()


    def on_button2_clicked(self):
        self.new_window = QtWidgets.QWidget()
        self.new_window.setWindowTitle('新窗口')
        layout = QtWidgets.QVBoxLayout()
        label = QtWidgets.QLabel("一个帅气逼人,温柔可爱,风流倜傥的美男子!\n#请问你还想聊什么?")
        layout.addWidget(label)

完整代码在这里👇↓↓↓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1870257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

音视频开发30 FFmpeg 视频编码- 流程以及重要API,H264编码原理说明,该章节使用h264编码说明

一.H264编码原理 1 视频为什么需要进行编码压缩 ◼ 一张为 720x480 的图像&#xff0c;用 YUV420P 的格式来表示&#xff0c;其大小为&#xff1a; 720*480*1.5 约等于 0.5MB 。 ◼ 如果是 25 帧&#xff0c; 10 分钟的数据量 0.5M*10*60*25 7500MB -> 7GB 多 ◼ …

SQL注入漏洞—SQL注入简介与原理

一、SQL注入基础 1.1 什么是SQL注入漏洞 SQL注入漏洞从1998年圣诞节大火以来长盛不衰&#xff0c;虽然开发人员想出各种方法对他进行围追堵截&#xff0c;却始终无法将其赶尽杀绝&#xff0c;SQL注入的根本原因就是将SQL代码插入或添加到应用&#xff08;用户&#xff09;的输…

Facebook之梦:数字社交的无限可能

在当今数字化和全球化的时代&#xff0c;社交网络已经成为人们日常生活不可或缺的一部分。作为全球最大的社交平台之一&#xff0c;Facebook不仅连接了数十亿用户&#xff0c;还深刻影响了我们的社交方式、文化交流和信息传播。然而&#xff0c;Facebook所代表的不仅仅是一个网…

Python湍流隐式模型耗散粘性方程和大涡流模拟

&#x1f3af;要点 &#x1f3af;达朗贝尔一维波动通解&#xff0c;二维变速模拟 | &#x1f3af;达朗贝尔算子解双曲波形微分方程 | &#x1f3af;耗散系统粘性伯格斯方程快速傅里叶变换算法 | &#x1f3af;二维线性和非线性对流扩散解和湍流隐式建模 &#x1f4dc;偏微分方…

MMCV【mmclassification】 从0到1 之 Docker 容器环境搭建步骤总结

🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 📙 Linux 下 Docker 安装环境检查Docker 安装 [ root 或者 sudo 权限用户可安装 ]给 普通用户 加入 Docker …

非最大值抑制(NMS)函数

非最大值抑制&#xff08;NMS&#xff09;函数 flyfish 非最大值抑制&#xff08;Non-Maximum Suppression, NMS&#xff09;是计算机视觉中常用的一种后处理技术&#xff0c;主要用于目标检测任务。其作用是从一组可能存在大量重叠的候选边界框中&#xff0c;筛选出最具代表…

软件必须要进行跨浏览器测试吗?包括哪些内容和注意事项?

随着互联网的普及和发展&#xff0c;用户对软件的要求越来越高。无论是在台式机、笔记本还是移动设备上&#xff0c;用户都希望能够以最好的体验来使用软件。然而&#xff0c;不同的浏览器在解析网页的方式、支持的技术标准等方面存在差异&#xff0c;这就导致了同一个网页在不…

LeetCode 585, 438, 98

目录 585. 2016年的投资题目链接表要求知识点思路代码 438. 找到字符串中所有字母异位词题目链接标签思路代码 98. 验证二叉搜索树题目链接标签合法区间思路代码 中序遍历思路代码 585. 2016年的投资 题目链接 585. 2016年的投资 表 表Insurance的字段为pid、tiv_2015、tiv…

RabbitMQ WEB管理端介绍

页面功能概览 Overview(概述)Connections(连接)Channels(通道)Exchanges(交换器)Queues(队列)Admin(用户管理)。 1. Overview(概述) 主要分为三部分 1.1 Queued messages&#xff08;所有队列的消息情况&#xff09; Ready&#xff1a;待消费的消息总数Unacked&#xff1a;待应…

抖音集成:通过MessageBox引领数字化营销新潮流

抖音集成&#xff1a;通过MessageBox引领数字化营销新潮流 在数字化营销的大潮中&#xff0c;企业需要不断探索新的方式来优化其营销策略&#xff0c;以抓住更多的市场机会。抖音作为一款全球知名的短视频社交平台&#xff0c;凭借其庞大的用户群体和高度互动的特性&#xff0…

[leetcode]24-game

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:static constexpr int TARGET 24;static constexpr double EPSILON 1e-6;static constexpr int ADD 0, MULTIPLY 1, SUBTRACT 2, DIVIDE 3;bool judgePoint24(vector<int> &nums) {vector&l…

A股跌懵了,股民一片茫然!

今天的A股跌懵了&#xff0c;股民一片茫然&#xff01;让人脸色苍白&#xff0c;盘面上出现了非常奇怪的一幕&#xff0c;不废话&#xff0c;直接说重点&#xff1a; 1、今天两市低开低走&#xff0c;跌懵了&#xff0c;昨晚人民币汇率大幅贬值&#xff0c;创下7.3的记录&#…

转转游戏MQ重构:思考与心得之旅

文章目录 1 背景1.1 起始之由1.2 重构前现状1.3 问题分析 2 重构2.1 目标2.2 制定方案2.2.1 架构设计2.2.2 实施计划2.2.3 测试计划 2.3 部分细节设计 3. 总结 1 背景 游戏业务自 2017 年启航&#xff0c;至今已近乎走过七个春秋&#xff0c;历经漫长岁月的发展&#xff0c;不…

SpringSecutrity原理

一、基于RBAC实现的权限管理通常需要涉及以下几张表&#xff1a; 1. 用户表&#xff08;user&#xff09;&#xff1a;记录系统中的所有用户&#xff0c;包括用户ID、用户名、密码等信息。 2. 角色表&#xff08;role&#xff09;&#xff1a;记录系统中的所有角色&#xff0…

【MySQL】(基础篇十七) —— 存储过程

存储过程 本文将介绍什么是存储过程&#xff0c;为什么要使用存储过程以及如何使用存储过程&#xff0c;并且介绍创建和使用存储过程的基本语法。 MySQL的存储过程是预编译的SQL语句集合&#xff0c;它们作为一个可执行单元存储在数据库中。存储过程能够封装复杂的业务逻辑&a…

分享一款永久免费内网穿透工具——巴比达内网穿透

最近在做web项目&#xff0c;想办法将web项目映射到公网进行访问&#xff0c;由于没有固定IP&#xff0c;只能使用内网穿透的方法&#xff0c;于是在网上搜索了一番&#xff0c;只有神卓互联旗下的这款巴比达内网穿透是真正免费的&#xff0c; 其它的要么用不了、要么限制没有流…

文件进行周期性备份后权限更改的解决方案--使用脚本和定时任务

这里写目录标题 背景现象解决方案原因分析面临的问题解决思路操作步骤每个文件夹权限分配表测试chmod和chown两个命令是否可行写脚本实现定时同步同时修改权限 异地同步改权限在NAS上生成SSH密钥对将NAS的公钥复制到Linux服务器在NAS上编写同步脚本在NAS上执行脚本&#xff0c;…

记录一次OPDS trunc()函数使用错误

说明&#xff1a;本文介绍 场景 在一次SQL查询时&#xff0c;需要对结果值保留两位小数&#xff0c;不四舍五入&#xff0c;直接截取到小数点后两位。如 59.156到59.15&#xff0c;23.2134到23.21&#xff0c;查看官方帮助文档&#xff08;https://help.aliyun.com/zh/maxcom…

【分享】30秒在线自助制作电子证件照

近期由于自己需要制作电子证件照&#xff0c;所以在网上找在线制作电子证件照的网站&#xff0c;找了很多网站都是收费的&#xff0c;也下载了很多app制作&#xff0c;都是要收费的。最后&#xff0c;所以索性自己开发一个网站制作电子证件照。这里分享给需要的朋友。&#xff…

探索Android架构设计

Android 应用架构设计探索&#xff1a;MVC、MVP、MVVM和组件化 MVC、MVP和MVVM是常见的三种架构设计模式&#xff0c;当前MVP和MVVM的使用相对比较广泛&#xff0c;当然MVC也并没有过时之说。而所谓的组件化就是指将应用根据业务需求划分成各个模块来进行开发&#xff0c;每个…