我有一个QWizard,它读取CSV文件的列标题并使用户选择他们想要的每一列。在此向导的第二页中,我将组合框添加到for循环中,该循环遍历CSV的列名。所有组合框均为必填字段。但是,另一个限制是,在用户可以按“下一步”之前,必须至少选择其中一个来选择3或更高(在我的MWE中为c1或c2)。
除了self.NextButton.setEnabled(False)
之外,我还根据此示例和此问题尝试使用isComplete
和completeChanged
,但由于是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
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
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。