【源码放送】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”获取所需的图片文件资源。
分类目录: 图形用户界面