【问题标题】:do not change the TAB of the QTabWidget until the form is complete在表单完成之前不要更改 QTabWidget 的 TAB
【发布时间】:2021-11-12 11:28:28
【问题描述】:

我试图让用户在填写表格 1 之前不要切换到“表格 2”所在的下一个 TAB。

我尝试了“currentChange”事件,但它没有按我想要的方式工作,因为它在已从 TAB 更改时显示警报。

有没有办法在任务完成之前保持当前 TAB 不变?

我附上代码和图片

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())

        #flag to not show the alert when starting the program
        self.flag = True

        #changes to True when the form is completed
        self.form_completed = False

        #WIDGET TAB 1
        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)

        #WIDGET TAB 2
        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)

        #QTABWIDGET
        self.tab_widget = QtWidgets.QTabWidget()
        self.tab_widget.currentChanged.connect(self.changed)
        self.tab_widget.addTab(self.widget_form1,"Form 1")
        self.tab_widget.addTab(self.widget_form2, "Form 2")

        self.layout().addWidget(self.tab_widget)

    def changed(self,index):
        if self.flag:
            self.flag = False
            return

        if not self.form_completed:
            QtWidgets.QMessageBox.about(self, "Warning", "You must complete the form")
            return

if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    mw = MyWidget()
    mw.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qtabwidget


    【解决方案1】:

    currentChanged 信号在索引已经改变时发出(动词是过去时:Changed),所以如果你想阻止改变,您必须检测任何用户尝试切换选项卡。

    为此,您必须同时检查鼠标和键盘事件:

    • 鼠标左键点击标签栏;
    • 选项卡小部件上的 Ctrl+TabCtrl+Shift+Tab

    由于您必须从主窗口控制该行为,唯一的解决方案是在选项卡小部件及其tabBar() 上安装事件过滤器,然后如果该操作会更改索引但表单未完成,您必须返回 True 以便该小部件不会处理该事件。

    请考虑以下假设必须保持活动的选项卡是当前(第一个添加的选项卡,或使用setCurrentIndex() 设置的选项卡)。

    class MyWidget(QtWidgets.QWidget):
        def __init__(self):
            # ...
            self.tab_widget.installEventFilter(self)
            self.tab_widget.tabBar().installEventFilter(self)
    
        def eventFilter(self, source, event):
            if event.type() == event.KeyPress and \
                event.key() in (Qt.Key_Left, Qt.Key_Right):
                    return not self.form_completed
            elif source == self.tab_widget.tabBar() and \
                event.type() == event.MouseButtonPress and \
                event.button() == Qt.LeftButton:
                    tab = self.tab_widget.tabBar().tabAt(event.pos())
                    if tab >= 0 and tab != self.tab_widget.currentIndex():
                        return self.isInvalid()
            elif source == self.tab_widget and \
                event.type() == event.KeyPress and \
                event.key() in (Qt.Key_Tab, Qt.Key_Backtab) and \
                event.modifiers() & Qt.ControlModifier:
                    return self.isInvalid()
            return super().eventFilter(source, event)
        def isInvalid(self):
            if not self.form_completed:
                QTimer.singleShot(0, lambda: QtWidgets.QMessageBox.about(
                    self, "Warning", "You must complete the form"))
                return True
            return False
    

    请注意,我使用 QTimer 显示消息框是为了立即正确返回事件过滤器。

    还要考虑在对象创建和配置结束时连接信号是一种很好的做法,这对于通知属性更改的信号更为重要:您不应在设置可能触发它的属性之前连接它。 由于一个空的 QTabWidget 有一个-1 索引,一旦你添加第一个选项卡,索引就会更改为0,从而触发信号。只需在添加选项卡后移动currentChanged 信号连接,就可以摆脱self.flag 检查。

    【讨论】:

    • 抱歉,Qt::Key_LeftQt::Key_Right 键呢
    • @S.Nick 你说得对,我忘了。谢谢,看看更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 2014-05-19
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多