【源码放送】Python制作TIM登录界面完整源码

本源码来自于州的先生基于 Python 的 PyQt5 库制作的新版 TIM 登录界面。

有关具体的代码实现思路和方式,详见下面的文章:

除了还原 TIM 登录界面样式之外,还实现了如下的交互:

  • QQ/微信登录方式切换;
  • 二维码扫码登陆切换;
  • 用户名密码输入;

这份源码一共包含 1 个 Python 文件、1 个 JPG 图片文件和 15 个 svg 图片文件:

引入的模块

# coding:utf-8
# @文件: pyqt_tim_login_gui.py
# @创建者:州的先生
# #日期:2020/9/17
# 博客地址:zmister.com
# 公众号:zmister2016

from PyQt5 import QtWidgets,QtCore,QtGui
import sys
import qrcode
import io

主窗口类

class TimLogin(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(680,520)

        self.setObjectName('body')
        self.setStyleSheet('''
            QMainWindow#body{
                background-color:white;
            }
            QToolButton,QPushButton{
                border:none;
            }
            QPushButton:hover{
                color:#333;
            }
            QCheckBox::indicator {
                border: 1px solid #9FA3A9;

            }
            QWidget#acount_group,#pwd_gourp{
                border-bottom:1px solid #E0E0E0;
            }
            QCheckBox,QLabel{
                color:#9FA3A9;
            }
            QToolButton#wx_icon{
                color:#9FA3A9;
            }
            QToolButton#wx_icon:hover{
                color:#1ABB0E;
            }

            QToolButton#qq_icon{
                color:#378AFE;
            }
            QToolButton#qq_icon:hover{
                color:#378AFE;
            }

            QPushButton#setting_icon{
                border-image: url("./setting.svg");
            }

            QPushButton#setting_icon:hover {
                border-image: url("./setting_hover.svg");
            }

            QPushButton#close_icon{
                border-image: url("./close.svg");
            }
            QPushButton#close_icon:hover {
                border-image: url("./close_hover.svg");
            }

            QPushButton#acount_icon{
                border-image: url("./lower.svg");
            }
            QPushButton#acount_icon:hover {
                border-image: url("./lower_hover.svg");
            }

            QPushButton#forward_icon{
                border-image: url("./forward.svg");
            }
            QPushButton#forward_icon:hover {
                border-image: url("./forward_hover.svg");
            }

            QPushButton#qrcode_icon{
                border-image: url("./qrcode.svg");
            }
            QPushButton#qrcode_icon:hover {
                border-image: url("./qrcode_hover.svg");
            }

            QPushButton#close_icon{
                border-image: url("./close.svg");
            }
            QPushButton#close_icon:hover {
                border-image: url("./close_hover.svg");
            }
        ''')
        self.current_login = 'qq'
        # 主控件
        self.main_widget = QtWidgets.QWidget()
        # 主布局
        self.main_layout = QtWidgets.QGridLayout()
        self.main_layout.setContentsMargins(0,0,0,0)
        self.main_widget.setLayout(self.main_layout)

        # 左侧背景控件
        self.left_widget = QtWidgets.QWidget()
        self.left_widget.setStyleSheet('''
            background-image:url(./bg.jpg)
        ''')


        # 顶部控制按钮组
        self.top_btn_group = QtWidgets.QWidget()
        self.top_btn_group_layout = QtWidgets.QHBoxLayout()
        self.top_btn_group_layout.setAlignment(QtCore.Qt.AlignTop|QtCore.Qt.AlignRight) # 联合顶部对齐和右对齐
        self.top_btn_group.setLayout(self.top_btn_group_layout)

        self.top_setting_btn = QtWidgets.QPushButton()
        self.top_setting_btn.setObjectName('setting_icon')
        # self.top_setting_btn.setIcon(QtGui.QIcon('./setting.svg'))
        self.top_setting_btn.setFixedSize(20,20)
        self.top_setting_btn.setIconSize(QtCore.QSize(20,20))
        self.top_setting_btn.setToolTip("设置")

        self.top_close_btn = QtWidgets.QPushButton()
        self.top_close_btn.setObjectName('close_icon')
        # self.top_close_btn.setIcon(QtGui.QIcon('./close.svg'))
        self.top_close_btn.setFixedSize(20,20)
        self.top_close_btn.setIconSize(QtCore.QSize(20,20))
        self.top_close_btn.setToolTip("关闭")
        self.top_close_btn.clicked.connect(self.close_btn_slot)

        # self.top_setting_btn.installEventFilter(self)
        self.top_btn_group_layout.addWidget(self.top_setting_btn)
        self.top_btn_group_layout.addWidget(self.top_close_btn)

        # QQ 图标按钮
        self.qq_icon = QtWidgets.QToolButton()
        self.qq_icon.setObjectName('qq_icon')
        self.qq_icon.setText("QQ 登录")
        self.qq_icon.setIcon(QtGui.QIcon("./qq_hover.svg"))
        self.qq_icon.setIconSize(QtCore.QSize(60,60))
        self.qq_icon.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.qq_icon.clicked.connect(self.switch_to_qq_login)
        self.qq_icon.installEventFilter(self)


        # 微信图标按钮
        self.wx_icon = QtWidgets.QToolButton()
        self.wx_icon.setObjectName('wx_icon')
        self.wx_icon.setText("微信登录")
        self.wx_icon.setIcon(QtGui.QIcon("./wx.svg"))
        self.wx_icon.setIconSize(QtCore.QSize(60, 60))
        self.wx_icon.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.wx_icon.installEventFilter(self)
        self.wx_icon.clicked.connect(self.switch_to_wx_login)

        # 图标按钮组
        self.icon_btn_group = QtWidgets.QWidget()
        self.icon_btn_group_layout = QtWidgets.QHBoxLayout()
        self.icon_btn_group.setLayout(self.icon_btn_group_layout)
        self.icon_btn_group_layout.addWidget(self.qq_icon)
        self.icon_btn_group_layout.addWidget(self.wx_icon)

        # 微信二维码扫码登陆
        self.wx_qrcode = QtWidgets.QLabel()
        self.wx_qrcode.setObjectName('wx_qrcode')
        self.genera_qrcode()
        self.wx_qrcode.setContentsMargins(8,5,0,10)
        self.wx_qrcode_label = QtWidgets.QLabel("请使用微信扫描二维码登录")
        self.wx_qrcode_group = QtWidgets.QWidget()
        self.wx_qrcode_group.setContentsMargins(0,0,0,100)
        self.wx_qrcode_group.setFixedHeight(313)
        self.wx_qrcode_group_layout = QtWidgets.QVBoxLayout()
        self.wx_qrcode_group_layout.setAlignment(QtCore.Qt.AlignCenter)
        self.wx_qrcode_group.setLayout(self.wx_qrcode_group_layout)
        self.wx_qrcode_group_layout.addWidget(self.wx_qrcode)
        self.wx_qrcode_group_layout.addWidget(self.wx_qrcode_label)

        # 表单输入
        self.acount_input = QtWidgets.QLineEdit()
        font = self.acount_input.font()
        font.setPointSize(16)
        self.acount_input.setFont(font)
        self.acount_input.setStyleSheet('''
            border: dashed 1px #9FA3A9;
        ''')
        self.acount_icon = QtWidgets.QPushButton()
        self.acount_icon.setObjectName('acount_icon')
        # self.acount_icon.setIcon(QtGui.QIcon('./lower.svg'))
        self.acount_icon.setIconSize(QtCore.QSize(20,20))
        self.acount_icon.setFixedSize(20,20)

        self.acount_gourp = QtWidgets.QWidget()
        self.acount_gourp.setObjectName('acount_group')
        self.acount_gourp_layout = QtWidgets.QHBoxLayout()
        self.acount_gourp.setLayout(self.acount_gourp_layout)
        self.acount_gourp_layout.addWidget(self.acount_input)
        self.acount_gourp_layout.addWidget(self.acount_icon)

        self.pwd_input = QtWidgets.QLineEdit()
        self.pwd_input.setEchoMode(QtWidgets.QLineEdit.Password)
        self.pwd_input.setFont(font)
        self.pwd_input.setStyleSheet('''
            border: dashed 1px #9FA3A9;
        ''')
        self.pwd_icon = QtWidgets.QPushButton()
        self.pwd_icon.setObjectName('forward_icon')
        self.pwd_icon.setIconSize(QtCore.QSize(20, 20))
        self.pwd_icon.setFixedSize(20,20)

        self.pwd_gourp = QtWidgets.QWidget()
        self.pwd_gourp.setObjectName('pwd_gourp')
        self.pwd_gourp_layout = QtWidgets.QHBoxLayout()
        self.pwd_gourp.setLayout(self.pwd_gourp_layout)
        self.pwd_gourp_layout.addWidget(self.pwd_input)
        self.pwd_gourp_layout.addWidget(self.pwd_icon)

        self.qrcode_icon = QtWidgets.QPushButton()
        self.qrcode_icon.setObjectName('qrcode_icon')
        self.qrcode_icon.setIconSize(QtCore.QSize(16, 16))
        self.qrcode_icon.setFixedSize(16, 16)
        self.qrcode_widget = QtWidgets.QWidget()
        self.qrcode_widget_layout = QtWidgets.QHBoxLayout()
        self.qrcode_widget_layout.setAlignment(QtCore.Qt.AlignRight)
        self.qrcode_widget.setLayout(self.qrcode_widget_layout)
        self.qrcode_widget_layout.addWidget(self.qrcode_icon)
        self.qrcode_icon.clicked.connect(self.switch_to_tim_qrcode_login)

        self.form_group = QtWidgets.QWidget()
        self.form_group_layout = QtWidgets.QVBoxLayout()
        self.form_group.setLayout(self.form_group_layout)
        self.form_group_layout.addWidget(self.acount_gourp)
        self.form_group_layout.addWidget(self.pwd_gourp)
        self.form_group_layout.addWidget(self.qrcode_widget)


        # 选项
        self.option_group = QtWidgets.QWidget()
        self.option_group_layout = QtWidgets.QGridLayout()
        self.option_group_layout.setContentsMargins(50,0,0,0)
        self.option_group.setLayout(self.option_group_layout)
        # 记住密码
        self.remunber_pwd = QtWidgets.QCheckBox("记住密码")
        self.find_pwd = QtWidgets.QLabel("找回密码")
        self.auto_login = QtWidgets.QCheckBox("自动登录")
        self.register = QtWidgets.QLabel("注册账号")
        self.option_group_layout.addWidget(self.remunber_pwd,0,0,1,1)
        self.option_group_layout.addWidget(self.find_pwd,0,1,1,1)
        self.option_group_layout.addWidget(self.auto_login,1,0,1,1)
        self.option_group_layout.addWidget(self.register,1,1,1,1)

        # 右侧表单控件
        self.right_widget = QtWidgets.QWidget()
        self.right_layout = QtWidgets.QGridLayout()
        self.right_widget.setLayout(self.right_layout)
        self.right_layout.addWidget(self.top_btn_group,0,0,1,2)
        self.right_layout.addWidget(self.icon_btn_group,1,0,1,2)
        self.right_layout.addWidget(self.form_group,2,0,1,2)
        self.right_layout.addWidget(self.option_group,3,0,2,2)

        # 右侧 TIm 二维码控件 - 初始隐藏
        self.right_qrcode_ui()

        # 添加到主布局层
        self.main_layout.addWidget(self.left_widget,0,0,5,3) #
        self.main_layout.addWidget(self.right_widget,0,3,5,2)
        self.main_layout.setSpacing(0)  # 设置网格布局层中部件的间隙

        self.setCentralWidget(self.main_widget)
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)

    def right_qrcode_ui(self):
        # 顶部控制按钮组
        self.control_btn_group = QtWidgets.QWidget()
        self.control_btn_group_layout = QtWidgets.QHBoxLayout()
        self.control_btn_group_layout.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignRight)  # 联合顶部对齐和右对齐
        self.control_btn_group.setLayout(self.control_btn_group_layout)

        self.control_back_btn = QtWidgets.QPushButton()
        self.control_back_btn.setIcon(QtGui.QIcon('./back.svg'))
        self.control_back_btn.setFixedSize(20,20)
        self.control_back_btn.setIconSize(QtCore.QSize(20,20))
        self.control_back_btn.setToolTip('返回')
        self.control_back_btn.clicked.connect(self.switch_to_normal_login)

        self.control_setting_btn = QtWidgets.QPushButton()
        self.control_setting_btn.setObjectName('setting_icon')
        self.control_setting_btn.setFixedSize(20, 20)
        self.control_setting_btn.setIconSize(QtCore.QSize(20, 20))
        self.control_setting_btn.setToolTip("设置")

        self.control_close_btn = QtWidgets.QPushButton()
        self.control_close_btn.setObjectName('close_icon')
        self.control_close_btn.setFixedSize(20, 20)
        self.control_close_btn.setIconSize(QtCore.QSize(20, 20))
        self.control_close_btn.setToolTip("关闭")
        self.control_close_btn.clicked.connect(self.close_btn_slot)

        self.control_btn_group_layout.addWidget(self.control_back_btn)
        self.control_btn_group_layout.addWidget(self.control_setting_btn)
        self.control_btn_group_layout.addWidget(self.control_close_btn)

        # 二维码
        self.tim_qrcode = QtWidgets.QLabel()
        self.tim_qrcode.setObjectName('wx_qrcode')
        self.tim_qrcode.setPixmap(self.genera_qrcode())
        self.tim_qrcode.setContentsMargins(8, 5, 0, 10)
        self.tim_qrcode_label = QtWidgets.QLabel("用 <a href='https://office.qq.com/'>TIM 手机版 </a> 扫描二维码登录")
        self.tim_qrcode_label.setOpenExternalLinks(True)
        self.tim_qrcode_group = QtWidgets.QWidget()
        self.tim_qrcode_group.setContentsMargins(0, 0, 0, 100)
        self.tim_qrcode_group.setFixedHeight(300)
        self.tim_qrcode_group_layout = QtWidgets.QVBoxLayout()
        self.tim_qrcode_group_layout.setAlignment(QtCore.Qt.AlignCenter)
        self.tim_qrcode_group.setLayout(self.tim_qrcode_group_layout)
        self.tim_qrcode_group_layout.addWidget(self.tim_qrcode)
        self.tim_qrcode_group_layout.addWidget(self.tim_qrcode_label)

        self.right_qrcode_widget = QtWidgets.QWidget()
        self.right_qrcode_widget_layout = QtWidgets.QGridLayout()
        self.right_qrcode_widget.setLayout(self.right_qrcode_widget_layout)
        self.right_qrcode_widget_layout.addWidget(self.control_btn_group)
        self.right_qrcode_widget_layout.addWidget(self.tim_qrcode_group)


    # 窗口关闭信号
    def close_btn_slot(self):
        # self.close()
        self.parent().close()

    # 事件过滤器
    def eventFilter(self, QObject, QEvent):
        # print(QObject)
        # 修改微信图标
        if QObject is self.wx_icon:
            if self.current_login == 'qq':
                if QEvent.type() == QtCore.QEvent.HoverEnter:
                    self.wx_icon.setIcon(QtGui.QIcon('./wx_hover.svg'))
                elif QEvent.type() == QtCore.QEvent.HoverLeave:
                    self.wx_icon.setIcon(QtGui.QIcon('./wx.svg'))

        if QObject is self.qq_icon:
            if self.current_login == 'wx':
                if QEvent.type() == QtCore.QEvent.HoverEnter:
                    self.qq_icon.setIcon(QtGui.QIcon('./qq_hover.svg'))
                elif QEvent.type() == QtCore.QEvent.HoverLeave:
                    self.qq_icon.setIcon(QtGui.QIcon('./qq.svg'))


        return False

    # 切换到微信登录
    def switch_to_wx_login(self):
        if self.current_login == 'qq':
            # 移除表单和选项控件
            self.right_layout.removeWidget(self.form_group)
            self.right_layout.removeWidget(self.option_group)
            self.form_group.hide()
            self.option_group.hide()
            # 添加二维码控件
            self.right_layout.addWidget(self.wx_qrcode_group,2,0,3,2)
            self.wx_qrcode_group.show()
            # 设置微信图标状态
            self.wx_icon.setIcon(QtGui.QIcon('./wx_hover.svg'))
            self.current_login = 'wx'
            # 设置 QQ 图标状态
            self.qq_icon.setIcon(QtGui.QIcon('./qq.svg'))
            self.wx_icon.setStyleSheet('''
            QToolButton#wx_icon{
                color:#1ABB0E;
            }
            QToolButton#wx_icon:hover{
                color:#1ABB0E;
            }


            ''')
            self.qq_icon.setStyleSheet('''
            QToolButton#qq_icon{
                color:#9FA3A9;
            }
            QToolButton#qq_icon:hover{
                color:#378AFE;
            }
            ''')

    # 切换到 QQ 登录
    def switch_to_qq_login(self):
        if self.current_login == 'wx':
            # 移除二维码控件
            self.right_layout.removeWidget(self.wx_qrcode_group)
            self.wx_qrcode_group.hide()
            # 添加表单控件
            self.right_layout.addWidget(self.form_group, 2, 0, 1, 2)
            self.right_layout.addWidget(self.option_group,3,0,2,2)
            self.option_group.show()
            self.form_group.show()
            # 设置微信图标状态
            self.wx_icon.setIcon(QtGui.QIcon('./wx.svg'))
            self.current_login = 'qq'
            # 设置 QQ 图标状态
            self.qq_icon.setIcon(QtGui.QIcon('./qq_hover.svg'))

            self.wx_icon.setStyleSheet('''
                        QToolButton#wx_icon{
                            color:#9FA3A9;
                        }
                        QToolButton#wx_icon:hover{
                            color:#1ABB0E;
                        }


                        ''')
            self.qq_icon.setStyleSheet('''
                        QToolButton#qq_icon{
                            color:#378AFE;
                        }
                        QToolButton#qq_icon:hover{
                            color:#378AFE;
                        }
                        ''')


    # 切换到 TIM 手机扫码登陆
    def switch_to_tim_qrcode_login(self):
        # 移除右侧控件
        self.main_layout.removeWidget(self.right_widget)
        self.right_widget.hide()
        # 添加 TIM 扫码登陆控件
        self.main_layout.addWidget(self.right_qrcode_widget,0,3,5,2)
        self.right_qrcode_widget.show()

    # 切换到常规登录
    def switch_to_normal_login(self):
        # 移除右侧控件
        self.main_layout.removeWidget(self.right_qrcode_widget)
        self.right_qrcode_widget.hide()
        # 添加常规登录控件
        self.main_layout.addWidget(self.right_widget,0,3,5,2)
        self.right_widget.show()

    # 生成一个二维码
    def genera_qrcode(self,qr_text="https://zmister.com"):
        qr = qrcode.QRCode(
            version=1,
            box_size=5,
            border=0
        )
        qr.add_data(qr_text)
        self.qr_img = qr.make_image()

        fp = io.BytesIO()
        self.qr_img.save(fp, "BMP")
        image = QtGui.QImage()
        image.loadFromData(fp.getvalue(), "BMP")
        qr_pixmap = QtGui.QPixmap.fromImage(image)
        self.wx_qrcode.setPixmap(qr_pixmap)
        return qr_pixmap

容器类

class Container(QtWidgets.QWidget):
    def __init__(self, window):
        super().__init__()
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(window)
        lay.setContentsMargins(10, 10, 10, 10)
        shadow = QtWidgets.QGraphicsDropShadowEffect(self,
            blurRadius=9.0,
            color=QtGui.QColor(116, 116, 116),
            offset=QtCore.QPointF(0, 0)
        )
        window.setGraphicsEffect(shadow)

    # 重写三个方法使我们的窗口支持拖动,上面参数 window 就是拖动对象
    def mousePressEvent(self, event):  # 鼠标长按事件
        if event.button() == QtCore.Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            event.accept()
            self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))

    def mouseMoveEvent(self, QMouseEvent):  # 鼠标移动事件
        if QtCore.Qt.LeftButton and self.m_drag:
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):  # 鼠标释放事件
        self.m_drag = False
        self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

运行方法

def main():
    app = QtWidgets.QApplication(sys.argv)
    gui = TimLogin()
    container = Container(gui)
    container.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

资源图片

州的先生微信公众号回复“0022”获取所需的图片文件资源。

猜你也喜欢

发表评论

邮箱地址不会被公开。