开发者社区> 问答> 正文

如何在for循环中强制执行多个QComboBox中的任何一个的最小索引?

我有一个QWizard,它读取CSV文件的列标题并使用户选择他们想要的每一列。在此向导的第二页中,我将组合框添加到for循环中,该循环遍历CSV的列名。所有组合框均为必填字段。但是,另一个限制是,在用户可以按“下一步”之前,必须至少选择其中一个来选择3或更高(在我的MWE中为c1或c2)。

除了self.NextButton.setEnabled(False)之外,我还根据此示例和此问题尝试使用isCompletecompleteChanged,但由于是PyQt的初学者并且不太擅长C ++,所以我没有能够了解很多现有文档。目前,isComplete似乎还可以,但是向导未在注册它。

谁能教我如何实现我想要的目标(粗体文字)?

from PyQt5 import QtGui, QtWidgets, QtCore
import csv

class ChooseFile(QtWidgets.QWizardPage):

    def __init__(self, parent=None):
        super(ChooseFile, self).__init__(parent)

        body = QtWidgets.QVBoxLayout()

        self.filePathShow = QtWidgets.QLineEdit(self)
        self.filePathShow.setReadOnly(True)                      # not editable
        self.registerField("filePathShow\*, self.filePathShow)   # mandatory
        body.addWidget(self.filePathShow)

        browseButton = QtWidgets.QPushButton('Browse...', self)
        browseButton.clicked.connect(self.browseDialog)
        browseBox = QtWidgets.QHBoxLayout()
        browseBox.addWidget(browseButton)
        body.addLayout(browseBox)

        self.setLayout(body)

    def browseDialog(self):
        filePath, _ = QtWidgets.QFileDialog.getOpenFileName(self, 'Open CSV', '/home', '(\*csv)')
        if filePath:   # only changes if valid file, stays the same if user presses cancel
            self.setField("filePathShow", filePath)

class ChooseColumns(QtWidgets.QWizardPage):

    def __init__(self, parent=None):
        super(ChooseColumns, self).__init__(parent)

        self.box = QtWidgets.QGroupBox()
        body = QtWidgets.QVBoxLayout()
        body.addWidget(self.box)   # these are where the choices (comboboxes) go
        self.setLayout(body)


    def initializePage(self):
        filePath2 = self.field("filePathShow")
        with open(str(filePath2), 'r') as f:
            reader = csv.reader(f)
            self.columns = next(reader)            
            # make a combobox for each column
            grid = QtWidgets.QGridLayout()
            self.comboBoxes = [None] * len(self.columns)
            for i, col in enumerate(self.columns):
                grid.addWidget(QtWidgets.QLabel(col), i, 0)   # printscolumn name

                self.comboBoxes[i] = QtWidgets.QComboBox()
                self.comboBoxes[i].addItem("")         # default value since is mandatory field
                self.comboBoxes[i].addItem("a")
                self.comboBoxes[i].addItem("b")
                self.comboBoxes[i].addItem("c1")
                self.comboBoxes[i].addItem("c2")

                grid.addWidget(self.comboBoxes[i], i, 1)
                self.registerField("column" + str(i) + "\*, self.comboBoxes[i]) # all mandatory
                self.comboBoxes[i].currentIndexChanged.connect(self.isComplete)
                #self.connect(self.comboBoxes[i], QtCore.SIGNAL(currentIndexChanged()), 
                #            self, QtCore.SIGNAL(completeChanged()))
                self.comboBoxes[i].currentIndexChanged.connect(self.completeChanged)   # DOESN'T WORK
            self.box.setLayout(grid)

    def isComplete(self, other):   # WORKS
        self.selections = [None] * len(self.columns)
        for i in range(len(self.selections)):   # first fill the list
            self.selections[i] = self.comboBoxes[i].currentIndex()
        #print(self.selections)
        for item in self.selections:   # then evaluate the values
            if i >= 3:
                return True
        return False


class Manager(QtWidgets.QWizard):

    def __init__(self, parent=None):
        super(Manager, self).__init__(parent)

        self.resize(500, 300)

        self.addPage(ChooseFile(self))
        self.addPage(ChooseColumns(self))


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Manager()
    w.show()
    sys.exit(app.exec_())

问题来源:stackoverflow

展开
收起
is大龙 2020-03-24 21:30:46 651 0
1 条回答
写回答
取消 提交回答
  • isComplete信号必须返回一个布尔值,该值指示它可以前进到下一页还是终止该过程。此方法不应直接调用,而应通过completeChanged信号调用。

    这种情况很特殊,因为QComboBox的数量是可变的,所以如果用户返回到上一页并选择另一个.csv,则应该更改QComboBox的数量并进行注册将是一个问题,因此在这种情况下我不会这样做但是它是使用isComplete直接处理的。

    最后,由于目标(我想)是获取选定的值,因此我将使用QWizard的属性存储该信息,并能够在为测试添加的最后一页上获取它。

    import csv
    
    from PyQt5 import QtGui, QtWidgets, QtCore
    
    
    class ChooseFile(QtWidgets.QWizardPage):
        def __init__(self, parent=None):
            super(ChooseFile, self).__init__(parent)
    
            body = QtWidgets.QVBoxLayout(self)
    
            self.filePathShow = QtWidgets.QLineEdit(self)
            self.filePathShow.setReadOnly(True)  # not editable
            self.registerField("filePathShow\*, self.filePathShow)  # mandatory
            body.addWidget(self.filePathShow)
    
            browseButton = QtWidgets.QPushButton("Browse...", self)
            browseButton.clicked.connect(self.browseDialog)
            browseBox = QtWidgets.QHBoxLayout()
            browseBox.addWidget(browseButton)
            body.addLayout(browseBox)
    
        def browseDialog(self):
            filePath, _ = QtWidgets.QFileDialog.getOpenFileName(
                self, "Open CSV", "/home", "(\*csv)"
            )
            if filePath:
                self.setField("filePathShow", filePath)
    
    
    class ChooseColumns(QtWidgets.QWizardPage):
        def __init__(self, parent=None):
            super(ChooseColumns, self).__init__(parent)
    
            self.comboboxes = []
    
            box = QtWidgets.QGroupBox()
            lay = QtWidgets.QVBoxLayout(self)
            lay.addWidget(box)
            self.flay = QtWidgets.QFormLayout()
            box.setLayout(self.flay)
    
        def initializePage(self):
            for combo in self.comboboxes:
                self.flay.removeRow(combo)
            self.comboboxes = []
            self.wizard().setProperty("indexes_selected", [])
            self.wizard().setProperty("options_selected", [])
    
            filePath2 = self.field("filePathShow")
            options = ("", "a", "b", "c1", "c2")
            with open(filePath2, "r") as f:
                reader = csv.reader(f)
                header = next(reader)
                for i, text in enumerate(header):
                    combo = QtWidgets.QComboBox()
                    combo.addItems(options)
                    combo.currentIndexChanged.connect(self.completeChanged)
                    self.flay.addRow(text, combo)
                    self.comboboxes.append(combo)
    
        def isComplete(self):
            indexes = [combo.currentIndex() for combo in self.comboboxes]
            is_completed = all(index >= 1 for index in indexes) and any(
                index >= 3 for index in indexes
            )
            self.wizard().setProperty("indexes_selected", indexes)
            self.wizard().setProperty(
                "options_selected", [combo.currentText() for combo in self.comboboxes]
            )
            return is_completed
    
    
    class FinalPage(QtWidgets.QWizardPage):
        def initializePage(self):
            print(self.wizard().property("indexes_selected"))
            print(self.wizard().property("options_selected"))
    
    
    class Manager(QtWidgets.QWizard):
        def __init__(self, parent=None):
            super(Manager, self).__init__(parent)
    
            self.resize(500, 300)
    
            self.addPage(ChooseFile())
            self.addPage(ChooseColumns())
            self.addPage(FinalPage())
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = Manager()
        w.show()
        sys.exit(app.exec_())
    

    回答来源:stackoverflow

    2020-03-24 21:30:55
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载