520表白小程序设计Python代码详解(PyQt5界面,B站动漫风)

摘要:介绍一个动漫风的表白小程序,界面使用 P y t h o n_以及 _P y Q _t_实现,界面样式经过多次美化调整,使得整体清新美观。本文详细介绍代码设计和实现过程,不仅是居家表白必备,而且适合新入门的朋友学习界面设计,完整代码资源文件请转至文末的下载链接。本博文目录如下:

➷点击跳转至文末所有涉及的 完整代码文件下载页☇

代码介绍及演示视频链接: https://www.bilibili.com/video/BV1q3411G7vB/(正在更新中,欢迎关注博主B站视频)

前言

今年的520准备写一个表白程序,毕竟程序员一般都喜欢在这一天来点自己的特色,不过大多都是喜闻乐见的那一套代码。虽然表白是用不上的,但是还是可以学习一番的,既然如此,不如来点赏心悦目的,那就有了这篇博文的内容。想法是看到网上有个类似的移动按钮的表白小程序,点子是好的,不过界面有些简陋,我就自己重新设计了一个。从背景图到按钮制作都是用Photoshop和PPT设计的,三个界面的截图如下:

风格上是借鉴了B站的风格和配色,包括背景的粉红色、动漫人像等,当然图片主要来自网上,我利用Photoshop进行了抠图和美化处理。整体上依然保持博主一贯的清新简约风,不过既然是表白程序,主题当然要粉红甜蜜,至于细节之处大家也可以有自己的见解。

PS:表白有风险,编码需谨慎!表白程序只是趣味学习的代码,真正表白还是应该当面表达心声。尽管520已过,但是我还是补上这个代码吧,希望大家都能找到心中所爱,勇往直前!(别问我520怎么不发,520谁敲代码啊)

  1. 准备工作

(一)设计思路

程序的设计思路是一个粉红的表白界面,别人在打开程序后,可以点击按钮回应:”我爱你”、”不爱你”,点同意弹出2号界面,即表白成功;若不同意,鼠标滑动到”不爱你”按钮,该按钮自动跑开,别人是点击不到的;如果不想选,点击关闭窗口,则弹出3号窗口,请求再给一次机会。(其实有点无赖哈)

界面设计上,主界面用QtDesigner拖出背景label和两个按钮,另外两个界面同样的搭配Label和按钮。在逻辑上,点击”我爱你”按钮弹出2号窗口;监听鼠标位置,出现在”不爱你”附近则移动该按钮的位置;修改关闭事件的槽函数,使其打开3号界面,忽视程序关闭。

(二)图片准备

准备几张处理过的动漫图片,需要用到具有透明背景的优美图片。一般难找到透明背景的,所以使用Photoshop将动漫人物主体抠出,抠出的人物图片如下图所示:

抠出人物主体的图片可以任意叠加在界面中,更能体现立体感,至于抠图软件大家随意,没必要因为Photoshop就劝退。同样的,我们以此抠出以下的几张图片,都是保存为透明背景的图片。

我们还需要准备一些文字和按钮,以下文字按钮通过PPT制作,当然Photoshop也是可以的,用什么软件你开心就好,设计美观就够了。

  1. 界面设计

界面采用QtDesigner设计,新建love520.ui文件,向界面中拖入4个Label控件,并摆置成如下图所示的效果。并设置界面的qss样式,包括按钮的图标、label的背景图等等。

设置MainWindow的样式表如下,鼠标划过或选中时label和按钮有抖动的效果:

QLabel{border:10px;}
QLabel::hover {
border:0px;}

QToolButton {
    background-color: transparent;
    borde: 20px;
}
QToolButton:hover {
    border: 0px solid rgb(255, 255, 255);
}
QToolButton:pressed {
    background-color: transparent;
    border: 5px;
}

对每个label设置各自的背景图片,如label_2的背景样式为下图。依次打开label的styleSheet属性,设置前面准备的背景图片。经过样式和背景图片设置后,当鼠标滑动时图片或按钮有放大的效果,如下图所示:

border-image: url(:/back/girl-2.png);

对于按钮可以设置其icon属性为前期设计的按钮图标,调整尺寸并设置样式如下,主要是鼠标悬停和点击后的样式情况,调整边界值使其具有缩放效果。

QToolButton {
    background-color: transparent;
    borde: 20px;
}
QToolButton:hover {
    border: 0px solid rgb(255, 255, 255);
}
QToolButton:pressed {
    background-color: transparent;
    border: 5px;
}

对于点击主界面关闭按钮后需要弹出的子窗口,设计如下,包括动漫人物图片、文字、按钮的摆放如下,其qss样式与主界面的类似,这里不再赘述。

同样的点击”我爱你”按钮后,需要弹出的子窗口设计如下,这时就只有label了,毕竟已经得手了,可以给一个庆祝送花的界面。

  1. 代码编写

界面准备完毕,我们可以用PyUIC工具将上一节设计完成的ui文件转换为py文件,这样可以直接调用该窗口的类和方法。另外,使用PyRcc工具可以将ui文件中涉及的qrc资源文件转换为py文件,方便对图片背景等文件进行读取。这里是一种逻辑界面分离的方式,代码逻辑和界面是分开的,这样对界面进行调整时,功能的逻辑代码就无需多做调整。

(一)主窗口界面

主窗口导出的窗口界面代码如下:

-*- coding: utf-8 -*-

Form implementation generated from reading ui file 'love520.ui'
author: sixuwuxian
Created by: PyQt5 UI code generator 5.15.4
website: wuxian.blog.csdn.net
WARNING: Any manual changes made to this file will be lost when pyuic5 is
run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1308, 789)
        MainWindow.setMinimumSize(QtCore.QSize(1308, 789))
        MainWindow.setMaximumSize(QtCore.QSize(1308, 789))
        MainWindow.setStyleSheet("QLabel{border:10px;}\n"
"QLabel::hover {\n"
"border:0px;}\n"
"\n"
"QPushButton {\n"
"    border:5px;}\n"
"\n"
"QPushButton:pressed {    \n"
"    background-color: transparent;\n"
"    border-radius: 0px;    \n"
"}\n"
"")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(42, 174, 1235, 575))
        self.label.setStyleSheet("QLabel {\n"
"    border:10px;\n"
"    border-image: url(:/back/back-image.png);\n"
"}")
        self.label.setText("")
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(42, -2, 547, 751))
        self.label_2.setStyleSheet("border-image: url(:/back/girl-2.png);\n"
"")
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(420, -2, 847, 211))
        self.label_3.setStyleSheet("border-image: url(:/back/love-text.png);")
        self.label_3.setText("")
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(1126, 542, 191, 213))
        self.label_4.setStyleSheet("border-image: url(:/back/baby-1.png);")
        self.label_4.setText("")
        self.label_4.setObjectName("label_4")
        self.toolButton = QtWidgets.QToolButton(self.centralwidget)
        self.toolButton.setGeometry(QtCore.QRect(564, 428, 225, 117))
        self.toolButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.toolButton.setStyleSheet("QToolButton {\n"
"    background-color: transparent;\n"
"    borde: 20px;    \n"
"}\n"
"QToolButton:hover {\n"
"    border: 0px solid rgb(255, 255, 255);\n"
"}\n"
"QToolButton:pressed {    \n"
"    background-color: transparent;\n"
"    border: 5px;    \n"
"}")
        self.toolButton.setText("")
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/back/yes.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.toolButton.setIcon(icon)
        self.toolButton.setIconSize(QtCore.QSize(400, 400))
        self.toolButton.setObjectName("toolButton")
        self.toolButton_2 = QtWidgets.QToolButton(self.centralwidget)
        self.toolButton_2.setGeometry(QtCore.QRect(872, 426, 225, 115))
        self.toolButton_2.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.toolButton_2.setStyleSheet("QToolButton {\n"
"    background-color: transparent;\n"
"    borde: 20px;    \n"
"}\n"
"QToolButton:hover {\n"
"    border: 0px solid rgb(255, 255, 255);\n"
"}\n"
"QToolButton:pressed {    \n"
"    background-color: transparent;\n"
"    border: 5px;    \n"
"}")
        self.toolButton_2.setText("")
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap(":/back/no.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.toolButton_2.setIcon(icon1)
        self.toolButton_2.setIconSize(QtCore.QSize(400, 400))
        self.toolButton_2.setObjectName("toolButton_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1308, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Bilibili: https://space.bilibili.com/456667721"))
import image_back_rc

(二)关闭窗口弹窗

当点击主窗口关闭按钮后,弹出的窗口界面代码如下:

-*- coding: utf-8 -*-

Form implementation generated from reading ui file 'love520.ui'
author: sixuwuxian
Created by: PyQt5 UI code generator 5.15.4
website: wuxian.blog.csdn.net
WARNING: Any manual changes made to this file will be lost when pyuic5 is
run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.setWindowModality(QtCore.Qt.ApplicationModal)
        Dialog.resize(743, 415)
        Dialog.setMinimumSize(QtCore.QSize(743, 415))
        Dialog.setMaximumSize(QtCore.QSize(743, 415))
        Dialog.setStyleSheet("")
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(2, 0, 335, 415))
        self.label.setStyleSheet("border-image: url(:/back/close-1.jpeg);")
        self.label.setText("")
        self.label.setObjectName("label")
        self.toolButton = QtWidgets.QToolButton(Dialog)
        self.toolButton.setGeometry(QtCore.QRect(436, 276, 205, 77))
        self.toolButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.toolButton.setStyleSheet("QToolButton {\n"
"    background-color: transparent;\n"
"    borde: 10px;    \n"
"}\n"
"QToolButton:hover {\n"
"    border: 0px solid rgb(255, 255, 255);\n"
"}\n"
"QToolButton:pressed {    \n"
"    background-color: transparent;\n"
"    border: 5px;    \n"
"}")
        self.toolButton.setText("")
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/back/choose.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.toolButton.setIcon(icon)
        self.toolButton.setIconSize(QtCore.QSize(400, 400))
        self.toolButton.setObjectName("toolButton")
        self.label_2 = QtWidgets.QLabel(Dialog)
        self.label_2.setGeometry(QtCore.QRect(352, 78, 377, 145))
        self.label_2.setStyleSheet("border-image: url(:/back/choose-text.png);")
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "考虑一下吧"))
import image_back_rc

(三)按钮点击弹窗

点击”我爱你”按钮,弹出的子窗口界面代码如下:

-*- coding: utf-8 -*-

Form implementation generated from reading ui file 'love520.ui'
author: sixuwuxian
Created by: PyQt5 UI code generator 5.15.4
website: wuxian.blog.csdn.net
WARNING: Any manual changes made to this file will be lost when pyuic5 is
run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(680, 401)
        Dialog.setMinimumSize(QtCore.QSize(680, 401))
        Dialog.setMaximumSize(QtCore.QSize(680, 401))
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(2, 12, 323, 389))
        self.label.setStyleSheet("border-image: url(:/back/loved-2.png);")
        self.label.setText("")
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(Dialog)
        self.label_2.setGeometry(QtCore.QRect(360, 144, 271, 269))
        self.label_2.setStyleSheet("border-image: url(:/back/flower.png);")
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(Dialog)
        self.label_3.setGeometry(QtCore.QRect(302, 20, 343, 145))
        self.label_3.setStyleSheet("border-image: url(:/back/loveyou.png);")
        self.label_3.setText("")
        self.label_3.setObjectName("label_3")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "我也喜欢你"))
import image_back_rc

(四)界面窗口逻辑

要想实现前面演示的功能,需要调用以上三个窗口的类和方法,并添加一些额外的功能。由于逻辑界面分离,我们不会直接修改以上导出的代码,这就要用到类继承的方式。首先我们导入需要用到的依赖:

import random
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog
from PyQt5.QtWidgets import QDesktopWidget

from ps.closeUI import Ui_Dialog
from ps.love520 import Ui_MainWindow
from ps.loveyou import Ui_Dialog as Ui_YesDialog

以上代码最后三行分别表示导入关闭主界面的弹窗、主界面窗口、点击按钮弹窗的类。我们新建两个类分别命名为CloseWindow、YesWindow,它们均继承QDialog类,以及Ui_Dialog和Ui_YesDialog这两个子窗口,初始化时继承原有构造方法,增加setupUi以及retranslateUi方法调用,以创建子窗口控件。然后重写Ui_YesDialog中的close方法,使其关闭时关闭所有事件。

class CloseWindow(QDialog, Ui_Dialog):
    def __init__(self):
        super(CloseWindow, self).__init__()
        self.setupUi(self)
        self.retranslateUi(self)
        self.toolButton.clicked.connect(self.close)

class YesWindow(QDialog, Ui_YesDialog):
    def __init__(self):
        super(YesWindow, self).__init__()
        self.setupUi(self)
        self.retranslateUi(self)

    def close(self):
        sender = self.sender()
        event = QApplication.instance()
        event.quit()

主窗口继承QMainWindow和前面设计的Ui_MainWindow类,初始化方法中除了setupUi和retranslateUi方法,还实例化CloseWindow、YesWindow的对象,以便后面调用。为两个按钮绑定了事件的槽函数,分别是”我爱你”按钮(toolButton)的点击事件槽函数、”不爱你”按钮(toolButton_2)的鼠标事件监听。

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, *args, obj=None, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)
        self.retranslateUi(self)  # 界面控件
        # self.center()

        # self.setWindowFlags(QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
        # self.setWindowTitle("我喜欢你")

        self.toolButton.clicked.connect(self.trueEvent)
        self.toolButton_2.installEventFilter(self)
        # self.toolButton_2.move(300, 400)
        # self.toolButton_2.move(300, 400)
        self.myDialog = CloseWindow()
        self.yesDialog = YesWindow()

    def trueEvent(self):
        self.yesDialog.show()
        self.hide()
        # sender = self.sender()
        # event = QApplication.instance()
        # event.quit()

    def eventFilter(self, object, event):
        if event.type() == QtCore.QEvent.HoverMove:
            self.toolButton_2.move(random.randint(472, 918),
                                   random.randint(174, 624))
            return True
        return False

    def closeEvent(self, event):
        # reply = QMessageBox.question(self.centralwidget, "小姐姐", "不能逃避的哦", QMessageBox.Yes, QMessageBox.Yes)
        # myDialog = ChildWindow()
        self.myDialog.show()
        event.ignore()
        # if reply == QMessageBox.Yes:
        #     event.ignore()

    def center(self):
        screen = QDesktopWidget().screenGeometry()  # 计算显示屏幕的大小
        size = self.geometry()  # 用来获取窗口的大小
        self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)  # 将窗口移动到屏幕中央

以上代码中设计的几个方法,其功能如下:

  1. trueEvent方法:toolButton按钮被点击时执行该函数,显示yesDialog(表白成功子窗口)界面,同时隐藏主界面;
  2. eventFilter方法:首先判断事件类型,当鼠标悬停移动时,将toolButton按钮的位置移动到一定范围的随机坐标,实现”不爱你”按钮的跑路功能;
  3. closeEvent方法:主界面的关闭按钮被点击时调用该方法,方法中显示myDialog窗口,同时将关闭窗口事件忽略,即阻止窗口关闭;
  4. center方法:此方法调用时可以将主界面移动到屏幕的中心位置。

(五)主程序的调用

以上类方法实现后,则可以调用MainWindow类,将主界面显示在系统界面中。如下代码实现代码调用:

-*- coding: utf-8 -*-
@Time    : 2022/05/20 10:06
@Author  : sixuwuxian
@Email   : sixuwuxian@aliyun.com
@blog    : wuxian.blog.csdn.net
@Software: PyCharm

from sys import argv, exit
from PyQt5.QtWidgets import QApplication
from loveUI import MainWindow

if __name__ == '__main__':

    app = QApplication(argv)

    win = MainWindow()
    win.show()
    exit(app.exec_())
  1. 下载链接

若您想获得博文中涉及的实现完整全部程序文件(包括测试图片、视频, _py, UI_文件等,如下图),这里已打包上传至博主的百度云盘,有需要的朋友可关注本人 B站(思绪亦无限)公众号(AI技术研究与分享)后,回复: love520 获取。

Python版本:3.8,请勿使用其他版本,需要安装的依赖: PyQt5 == 5.15.5

PS:可独立运行的exe文件同样包含在分享的完整代码包中。

结束语

由于博主能力有限,博文中提及的方法即使经过试验,也难免会有疏漏之处。希望您能热心指出其中的错误,以便下次修改时能以一个更完美更严谨的样子,呈现在大家面前。同时如果有更好的实现方法也请您不吝赐教。

Original: https://www.cnblogs.com/sixuwuxian/p/16300552.html
Author: 思绪无限
Title: 520表白小程序设计Python代码详解(PyQt5界面,B站动漫风)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/567721/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球