点我下载
https://download.csdn.net/download/lm_is_dc/88335301
加入Text Brower
做标题,几个按钮。
然后在左侧containers
中添加Stacked Widget
这个控件,初步布局如下:
在右侧属性中修改当前页名称,把第一页修改为page_first
选中Stacked Widget
,右键插入页
->当前页之后
,增加两页,并命名为page_fun1
,page_fun2
转化后代码:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'stacked.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# 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(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn_first = QtWidgets.QPushButton(self.centralwidget)
self.btn_first.setGeometry(QtCore.QRect(50, 100, 93, 28))
self.btn_first.setObjectName("btn_first")
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setGeometry(QtCore.QRect(45, 10, 711, 41))
self.textBrowser.setObjectName("textBrowser")
self.btn_fun1 = QtWidgets.QPushButton(self.centralwidget)
self.btn_fun1.setGeometry(QtCore.QRect(170, 100, 93, 28))
self.btn_fun1.setObjectName("btn_fun1")
self.btn_fun2 = QtWidgets.QPushButton(self.centralwidget)
self.btn_fun2.setGeometry(QtCore.QRect(280, 100, 93, 28))
self.btn_fun2.setObjectName("btn_fun2")
self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
self.stackedWidget.setGeometry(QtCore.QRect(50, 160, 691, 271))
self.stackedWidget.setObjectName("stackedWidget")
self.page_first = QtWidgets.QWidget()
self.page_first.setObjectName("page_first")
self.label = QtWidgets.QLabel(self.page_first)
self.label.setGeometry(QtCore.QRect(70, 50, 72, 21))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.page_first)
self.label_2.setGeometry(QtCore.QRect(70, 90, 72, 21))
self.label_2.setObjectName("label_2")
self.account_edit = QtWidgets.QLineEdit(self.page_first)
self.account_edit.setGeometry(QtCore.QRect(130, 50, 113, 21))
self.account_edit.setObjectName("account_edit")
self.password_edit = QtWidgets.QLineEdit(self.page_first)
self.password_edit.setGeometry(QtCore.QRect(130, 90, 113, 21))
self.password_edit.setObjectName("password_edit")
self.btn_login = QtWidgets.QPushButton(self.page_first)
self.btn_login.setGeometry(QtCore.QRect(130, 140, 93, 28))
self.btn_login.setObjectName("btn_login")
self.btn_registere = QtWidgets.QPushButton(self.page_first)
self.btn_registere.setGeometry(QtCore.QRect(250, 140, 93, 28))
self.btn_registere.setObjectName("btn_registere")
self.stackedWidget.addWidget(self.page_first)
self.page_fun1 = QtWidgets.QWidget()
self.page_fun1.setObjectName("page_fun1")
self.label_3 = QtWidgets.QLabel(self.page_fun1)
self.label_3.setGeometry(QtCore.QRect(60, 50, 72, 21))
self.label_3.setObjectName("label_3")
self.show_text_1 = QtWidgets.QTextBrowser(self.page_fun1)
self.show_text_1.setGeometry(QtCore.QRect(170, 40, 256, 192))
self.show_text_1.setObjectName("show_text_1")
self.stackedWidget.addWidget(self.page_fun1)
self.page_fun2 = QtWidgets.QWidget()
self.page_fun2.setObjectName("page_fun2")
self.label_4 = QtWidgets.QLabel(self.page_fun2)
self.label_4.setGeometry(QtCore.QRect(60, 30, 72, 21))
self.label_4.setObjectName("label_4")
self.show_text_2 = QtWidgets.QTextBrowser(self.page_fun2)
self.show_text_2.setGeometry(QtCore.QRect(130, 20, 256, 192))
self.show_text_2.setObjectName("show_text_2")
self.stackedWidget.addWidget(self.page_fun2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 27))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.stackedWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.btn_first.setText(_translate("MainWindow", "首页"))
self.textBrowser.setHtml(_translate("MainWindow", "\n"
"\n"
"PyQt5通过堆叠布局实现选项卡(多界面)功能
"))
self.btn_fun1.setText(_translate("MainWindow", "功能1"))
self.btn_fun2.setText(_translate("MainWindow", "功能2"))
self.label.setText(_translate("MainWindow", "账号"))
self.label_2.setText(_translate("MainWindow", "密码"))
self.btn_login.setText(_translate("MainWindow", "登录"))
self.btn_registere.setText(_translate("MainWindow", "注册"))
self.label_3.setText(_translate("MainWindow", "功能1"))
self.label_4.setText(_translate("MainWindow", "功能2"))
QStackedWidget 类继承自 QFrame类。
QStackedWidge t类提供了多页面切换的布局,一次只能看到一个界面。
QStackedWidget 类的信号:
currentChanged(int index):当前页面发生变化时候发射,index 为新的索引值。
widgetRemoved(int index):页面被移除时候发射,index 为页面对应的索引值。
QStackedWidget 类的槽函数:
setCurrentIndex(int index):设置索引 index 所在的页面为当前页面。setCurrentWidget(QWidget *widget):设置QWidget页面为当前页面。
使用如下程序可以设置 page_0 为当前显示的页面:
pageNo = 0 # 设置 page_0 为索引页(第一页面)
self.stackedWidget.setCurrentIndex(pageNo) # 设置使用 pageNo=0 作为当前显示页面
需要注意的是,不论我们为每个页面控件设置的名称(objectName)是什么,在 QStackedWidget 类中定义的页面索引 index 都是一个从 0 开始计数,即:第一页面的索引值 index=0,第二页面的索引值 index=1,…。
示例代码:
# -*- coding: utf-8 -*-
"""
@contact: 微信 1257309054
@file: main.py
@time: 2023/9/13 15:09
@author: LDC
"""
import datetime
import json
import sys
import time
from PyQt5 import QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal, QMutex
from PyQt5 import QtCore
from stacked import Ui_MainWindow
class StackedDemo(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(StackedDemo, self).__init__()
self.setupUi(self) # 创建窗体对象
self.init()
def init(self):
'''
初始化
:return:
'''
self.is_login = False # 是否登录
self.is_register = False # 是否注册
self.show_text_1_list = [] # 功能1显示内容列表
self.show_text_2_list = [] # 功能1显示内容列表
self.login_thread = LoginThread(self) # 开启多线程处理登录数据
# 关联按钮事件
self.btn_first.clicked.connect(self.btn_first_clicked) # 首页按钮点击事件
self.btn_fun1.clicked.connect(self.btn_fun1_clicked) # 功能1按钮点击事件
self.btn_fun2.clicked.connect(self.btn_fun2_clicked) # 功能2按钮点击事件
self.btn_login.clicked.connect(self.btn_login_clicked) # 登录按钮点击事件
self.btn_registere.clicked.connect(self.btn_register_clicked) # 注册按钮点击事件
self.login_thread._signal_login.connect(self.threading_slot) # 绑定线程回调处理函数
def btn_first_clicked(self):
# 首页
self.stackedWidget.setCurrentIndex(0)
def btn_fun1_clicked(self):
# 功能1
self.stackedWidget.setCurrentIndex(1)
def btn_fun2_clicked(self):
# 功能2
self.stackedWidget.setCurrentIndex(2)
def btn_login_clicked(self):
# 登录
self.stackedWidget.setCurrentIndex(1) # 切换界面
if not self.is_login:
self.show_text_1_list.append('功能1界面--登录')
self.login_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.show_text_1_list.append('登录时间:{}'.format(self.login_time))
self.is_login = True # 修改登录标志
if self.is_login:
self.login_thread.start()
def btn_register_clicked(self):
# 注册
self.stackedWidget.setCurrentIndex(2)
self.show_text_2.setText('功能2界面--注册')
def threading_slot(self, data):
'''
线程回调函数
:param data:
:return:
'''
data = json.loads(data)
if 'update_login_time' in data:
if len(self.show_text_1_list) > 6:
self.show_text_1_list.pop(0)
now_time = data['update_login_time']
time1 = datetime.datetime.strptime(self.login_time, '%Y-%m-%d %H:%M:%S')
time2 = datetime.datetime.strptime(now_time, '%Y-%m-%d %H:%M:%S')
diff = time2 - time1
days = diff.days
seconds = diff.seconds
self.show_text_1_list.append(
'\r\n{},已登录{}秒'.format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), seconds))
info_msg = ''
for stl in self.show_text_1_list:
info_msg += stl
self.show_text_1.setText(info_msg)
# 登录后处理
class LoginThread(QThread):
# 登录多线程
_signal_login = pyqtSignal(str)
def __init__(self, parent=None):
super(LoginThread, self).__init__(parent)
self.qmut = QMutex()
self.window = parent
self.is_exit = False
def run(self):
while 1:
self.qmut.lock()
if self.is_exit:
break
self.qmut.unlock()
now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self._signal_login.emit(json.dumps({'update_login_time': now_time})) # 发送信号给槽函数
time.sleep(5)
if __name__ == '__main__':
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) # 自适应分辨率
app = QtWidgets.QApplication(sys.argv)
ui = StackedDemo()
ui.show()
sys.exit(app.exec_())
通过线程来演示切换界面时,之前的界面功能不受影响。