组合框函数 currentIndexChanged 无法正常工作
Posted
技术标签:
【中文标题】组合框函数 currentIndexChanged 无法正常工作【英文标题】:ComboBox function currentIndexChanged not working correctly 【发布时间】:2019-09-14 12:28:46 【问题描述】:我采用了两个组合框,即 comboBox1 和 comboBox_2 以及两个函数 test 和 test1 并使用 currentIndexChanged(self.comboBOx1.currentIndexChanged 和 self.comboBOx_2.currentIndexChanged)调用它们。当从 comboBox1 中选择一个值时,它的相应函数 (self.comboBOx1.currentIndexChanged) 会被调用,并且对于 comboBox_2 也是如此。从 comboBox1 中选择值会更改 comboBox_2 中的值,并且其工作正常。但是我在这里遇到的问题是,首先,当我从 comboBox1 和 comboBox_2 中选择一个值时,我从被调用的函数中获取了预期值(打印'hello')。第二次,当我从 comboBox1 中选择一个值时,只应该调用测试函数,但是这里两个函数(test 和 test1)都被调用了,第二个函数(test1)被调用了两次(打印 'hello' 两次)和第三次时间它被调用四次(打印“你好”四次)。请问谁能帮我解决这个问题?
代码:
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.comboBox1 = QtGui.QComboBox(self.centralwidget)
self.comboBox1.setGeometry(QtCore.QRect(310, 150, 171, 31))
self.comboBox1.setObjectName(_fromUtf8("comboBox1"))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox_2 = QtGui.QComboBox(self.centralwidget)
self.comboBox_2.setGeometry(QtCore.QRect(310, 240, 171, 41))
self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.comboBox1.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox1.setItemText(1, _translate("MainWindow", "a", None))
self.comboBox1.setItemText(2, _translate("MainWindow", "b", None))
self.comboBox1.setItemText(3, _translate("MainWindow", "c", None))
self.comboBox_2.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox_2.setItemText(1, _translate("MainWindow", "p", None))
self.comboBox_2.setItemText(2, _translate("MainWindow", "q", None))
self.comboBox_2.setItemText(3, _translate("MainWindow", "r", None))
self.comboBox_2.setEnabled(0)
self.comboBox1.currentIndexChanged.connect(self.test)
def test(self):
s = str(self.comboBox1.currentText())
res=['aa','bb','cc','dd']
if (s == "- - select - -"):
self.comboBox_2.setEnabled(0)
self.comboBox_2.setCurrentIndex(0)
elif(len(s)== 0):
self.comboBox_2.setEnabled(1)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
else:
self.comboBox_2.setEnabled(1)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
self.comboBox_2.addItems(res)
self.comboBox_2.currentIndexChanged.connect(self.test1)
def test1(self):
print ("Hello")
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
【问题讨论】:
【参考方案1】:为了理解行为,我们将使用以下示例:
示例 1:
from PyQt4 import QtCore, QtGui
def on_clicked():
print("clicked")
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
button = QtGui.QPushButton("Press me")
for _ in range(4):
button.clicked.connect(on_clicked)
button.show()
sys.exit(app.exec_())
当您按下按钮时,它会打印 4 次,因为 Qt 不记得信号和函数之间是否已经存在连接,因此如果同一信号和函数之间有 n 个连接,它们将在发出信号。
示例 2:
from PyQt4 import QtCore, QtGui
def on_currentIndexChanged(ix):
print("currentIndex:", ix)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
combo = QtGui.QComboBox()
print("currentIndex:", combo.currentIndex())
combo.currentIndexChanged.connect(on_currentIndexChanged)
button_add = QtGui.QPushButton("Add Items")
button_add.clicked.connect(lambda: combo.addItems("1 2 3".split()))
button_clear = QtGui.QPushButton("Clear")
button_clear.clicked.connect(combo.clear)
w = QtGui.QWidget()
lay = QtGui.QVBoxLayout(w)
for widget in (combo, button_add, button_clear):
lay.addWidget(widget)
w.show()
sys.exit(app.exec_())
QComboBox 的默认 currentIndex 为 -1,当您添加项目时,currentIndex 变为 0,当您清理 QComboBox 时,currentIndex 恢复为 -1。因此,当您添加或清理项目时,会发出 currentIndexChanged 信号。
基于以上,我将解释您指出的行为:当在QCombobox 1中选择一个新的currentIndex时,调用测试方法,如果它在清理后进入else语句,并且添加您建立第一个连接的项目,如果现在重复相同的事情,因为有一个连接,currentIndexChanged 信号被发射两次(一个用于 clear(),另一个用于 addItems())并且您还创建第二个连接,如果再次重复,信号发出 4 次(1 clear() x 2 连接 + 1 addItems() x 2 连接)。
解决方案:
在只调用一次的函数中建立连接。 为了使 clear() 信号和 addItems() 不会发出 currentIndexChanged 信号,您必须使用 blockSignals()。 另外一点,建议不要修改Qt Designer生成的代码,除了使用装饰@QtCore.pyqtSlot()之外,建议创建另一个使用初始类作为接口的类。from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.comboBox1 = QtGui.QComboBox(self.centralwidget)
self.comboBox1.setGeometry(QtCore.QRect(310, 150, 171, 31))
self.comboBox1.setObjectName(_fromUtf8("comboBox1"))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox_2 = QtGui.QComboBox(self.centralwidget)
self.comboBox_2.setGeometry(QtCore.QRect(310, 240, 171, 41))
self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.comboBox1.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox1.setItemText(1, _translate("MainWindow", "a", None))
self.comboBox1.setItemText(2, _translate("MainWindow", "b", None))
self.comboBox1.setItemText(3, _translate("MainWindow", "c", None))
self.comboBox_2.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox_2.setItemText(1, _translate("MainWindow", "p", None))
self.comboBox_2.setItemText(2, _translate("MainWindow", "q", None))
self.comboBox_2.setItemText(3, _translate("MainWindow", "r", None))
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.comboBox_2.setEnabled(False)
self.comboBox1.currentIndexChanged[str].connect(self.test)
self.comboBox_2.currentIndexChanged.connect(self.test1)
@QtCore.pyqtSlot(str)
def test(self, s):
res=['aa','bb','cc','dd']
if s == "- - select - -":
self.comboBox_2.setEnabled(False)
self.comboBox_2.setCurrentIndex(0)
elif not s:
self.comboBox_2.setEnabled(True)
self.comboBox_2.blockSignals(True)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
self.comboBox_2.blockSignals(False)
else:
self.comboBox_2.setEnabled(True)
self.comboBox_2.blockSignals(True)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
self.comboBox_2.addItems(res)
self.comboBox_2.blockSignals(False)
@QtCore.pyqtSlot(int)
def test1(self, ix):
print("Hello", ix)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
【讨论】:
非常感谢您的回复。它按预期工作。以上是关于组合框函数 currentIndexChanged 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
如何将sender()名称转换为int [duplicate]