如何在表单填写完成前禁止切换QTabWidget的标签页
解决方案
问题根因
你使用的currentChanged信号是标签页切换完成后才会触发的,所以收到信号时切换动作已经执行完毕,自然无法实现提前拦截的效果。
方案1:默认禁用未解锁标签(推荐,交互最优)
该方案直接让用户无法点击未完成前置条件的标签,没有多余提示,逻辑最通顺:
- 初始化时把Form 2对应的标签设为禁用状态
- 待Form 1填写完成后,再主动启用Form 2标签
修改后的完整代码:
import sys from PyQt5.QtCore import Qt from PyQt5 import QtWidgets class MyWidget(QtWidgets.QWidget): def __init__(self): super(MyWidget, self).__init__() self.setGeometry(0, 0, 800, 500) self.setLayout(QtWidgets.QVBoxLayout()) # Form1完成状态标记,填写完成后置为True self.form_completed = False # 构造Form1页面 self.widget_form1 = QtWidgets.QWidget() self.widget_form1.setLayout(QtWidgets.QVBoxLayout()) self.widget_form1.layout().setAlignment(Qt.AlignHCenter) label_form1 = QtWidgets.QLabel("FORM 1") # 这里可以加你的表单提交按钮,提交后调用self.form_finish() submit_btn = QtWidgets.QPushButton("完成Form1填写") submit_btn.clicked.connect(self.form_finish) self.widget_form1.layout().addWidget(label_form1) self.widget_form1.layout().addWidget(submit_btn) # 构造Form2页面 self.widget_form2 = QtWidgets.QWidget() self.widget_form2.setLayout(QtWidgets.QVBoxLayout()) self.widget_form2.layout().setAlignment(Qt.AlignHCenter) label_form2 = QtWidgets.QLabel("FORM 2") self.widget_form2.layout().addWidget(label_form2) # 构造标签页 self.tab_widget = QtWidgets.QTabWidget() self.tab_widget.addTab(self.widget_form1,"Form 1") self.tab_widget.addTab(self.widget_form2, "Form 2") # 初始化禁用Form2标签 self.tab_widget.setTabEnabled(1, False) self.layout().addWidget(self.tab_widget) def form_finish(self): # Form1提交后触发,启用Form2标签 self.form_completed = True self.tab_widget.setTabEnabled(1, True) QtWidgets.QMessageBox.about(self, "提示", "Form1已完成,可切换到Form2") if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) mw = MyWidget() mw.show() sys.exit(app.exec_())
方案2:点击标签时拦截校验(符合你原有交互预期)
如果你需要保留「点击后弹警告再停留在原页面」的交互,可以通过给标签栏安装事件过滤器实现拦截:
import sys from PyQt5.QtCore import Qt, QEvent from PyQt5 import QtWidgets class MyWidget(QtWidgets.QWidget): def __init__(self): super(MyWidget, self).__init__() self.setGeometry(0, 0, 800, 500) self.setLayout(QtWidgets.QVBoxLayout()) # Form1完成状态标记,填写完成后置为True self.form_completed = False # 构造Form1页面 self.widget_form1 = QtWidgets.QWidget() self.widget_form1.setLayout(QtWidgets.QVBoxLayout()) self.widget_form1.layout().setAlignment(Qt.AlignHCenter) label_form1 = QtWidgets.QLabel("FORM 1") self.widget_form1.layout().addWidget(label_form1) # 构造Form2页面 self.widget_form2 = QtWidgets.QWidget() self.widget_form2.setLayout(QtWidgets.QVBoxLayout()) self.widget_form2.layout().setAlignment(Qt.AlignHCenter) label_form2 = QtWidgets.QLabel("FORM 2") self.widget_form2.layout().addWidget(label_form2) # 构造标签页 self.tab_widget = QtWidgets.QTabWidget() self.tab_widget.addTab(self.widget_form1,"Form 1") self.tab_widget.addTab(self.widget_form2, "Form 2") # 给标签栏安装事件过滤器,拦截点击事件 self.tab_widget.tabBar().installEventFilter(self) self.layout().addWidget(self.tab_widget) def eventFilter(self, watched, event): # 只处理标签栏的鼠标点击事件 if watched == self.tab_widget.tabBar() and event.type() == QEvent.MouseButtonPress: # 获取点击的标签索引 tab_index = watched.tabAt(event.pos()) # 如果点击的是Form2且Form1未完成,拦截事件,弹警告 if tab_index == 1 and not self.form_completed: QtWidgets.QMessageBox.about(self, "Warning", "You must complete the form") return True return super().eventFilter(watched, event) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) mw = MyWidget() mw.show() sys.exit(app.exec_())
原程序运行效果图:
内容的提问来源于stack exchange,提问作者Leo Odriozola
相关产品推荐
相关产品推荐

