如何从另一个类 PyQT 向 QComboBox 添加项目?
Posted
技术标签:
【中文标题】如何从另一个类 PyQT 向 QComboBox 添加项目?【英文标题】:How to Add Items to QComboBox from another class PyQT? 【发布时间】:2020-11-02 18:32:29 【问题描述】:我正在使用 PyQt 在 Qt Designer 上设计这个东西。所以我有一个QMainWindow
,用户可以从中打开一个QDialog
来输入我保存在Json 文件中的一些数据(下面的AddUser 函数)
我想要的是当单击 AddUser 按钮时,从 AddUser 函数中,如何在 MainWindow 类中定义的 Combobox 中添加新项目?
这是两个类的代码
import ui.mainwindow as MnWindow
import ui.AddUserDialog as AddUserDialog
#First GUI
class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
#Second GUI
class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
def __init__(self,parent=None):
super(AddUserDialog,self).__init__(parent)
self.setupUi(self)
self.pushButtonAddUser.clicked.connect(self.AddUser)
def AddUser(self):
DateDeNaissance = self.dateEditDateDeNaissance.date().toString(Qt.ISODate)
DateDeSortie = self.dateEditDateDeSortie.date().toString(Qt.ISODate)
new_user =
'firstname' : self.lineEditPrenom.text(),
'lastname' : self.lineEditNom.text(),
'DateDeNaissance' : DateDeNaissance[-2:] + DateDeNaissance[5:7] + DateDeNaissance[:4],
'LieuDeNaissance' : self.lineEditLieuNaissance.text(),
'Adresse' : self.lineEditAdresse.text(),
'Ville' : self.lineEditVille.text(),
'CodePostal' : self.lineEditCodePostal.text(),
'DateDeSortie' : DateDeSortie[-2:] + DateDeSortie[5:7] + DateDeSortie[:4],
'Heure' : str(self.timeEditSortie.time().hour()),
with open('TestJson.json','r') as f:
data = json.load(f)
data['users'].append(new_user)
with open('TestJson.json','w') as f:
json.dump(data,f,indent=3)
MainWindow.UserComboBox.addItem(new_user['firstname'] + ' ' + new_user['lastname'])
最后一行当然是不正确的,我该怎么做呢?
PS:我读过我需要从 MainWindow 类继承,但我一直在尝试,但没有成功。
【问题讨论】:
交互式对话框通常用于在对话框关闭后立即获得返回某些结果(通过接受或拒绝 它),并且在正常情况下,它们不应该能够直接与创建它们的对象进行交互。所以,最重要的问题是:您希望能够在对话框仍然打开时更改主窗口中的项目,还是希望从对话框中取回结果然后做出相应的反应? @musicamante 不,主窗口中的更改是在对话框关闭后进行的,如何使用对话框结果对主窗口小部件执行操作?我是 Qt 的新手,所以我不知道是否有一种简单明了的方法可以做到这一点。谢谢, 【参考方案1】:有两种可能的方法。
最简单的方法是从对实例的引用中访问属性(或小部件的属性)。
class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.someButton.clicked.connect(self.addUser)
def addUser(self):
dialog = AddUserDialog(self)
if dialog.exec_():
firstname = dialog.lineEditPrenom.text()
lastname = dialog.lineEditNom.text()
self.UserComboBox.addItem(' '.format(firstname, lastname))
或者,您可以覆盖对话框的exec_()
方法并在对话框被接受时返回值:
class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.addUserButton.clicked.connect(self.addUser)
def addUser(self):
res = AddUserDialog(self).exec_()
if res:
self.UserComboBox.addItem(res)
class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
def exec_(self):
if super().exec_():
firstname = self.lineEditPrenom.text()
lastname = self.lineEditNom.text()
return ' '.format(firstname, lastname)
两种解决方案都假设用户接受对话框,这通常通过按下“确定”按钮来实现。如果要使用自定义按钮,还应该在AddUser()
函数的末尾调用self.accept()
。
考虑到 Qt 为此目的提供了QDialogButtonBox,您不需要添加自己的按钮。我相信您可能正在使用 QPushButton,因为 QDialogButtonBox 的默认按钮具有固定标签,并且它们都没有“添加”文本,但是可以根据需要重命名这些按钮。假设您的对话框上有一个名为buttonBox
(带按钮的对话框的默认设置)的QDialogButtonBox,带有“确定”按钮,您可以直接在accept()
函数中实现json 写入:
class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
def __init__(self,parent=None):
super(AddUserDialog,self).__init__(parent)
self.setupUi(self)
self.buttonBox.button(self.buttonBox.Ok).setText('Add user')
def accept(self):
DateDeNaissance = self.dateEditDateDeNaissance.date().toString(Qt.ISODate)
DateDeSortie = self.dateEditDateDeSortie.date().toString(Qt.ISODate)
new_user =
'firstname' : self.lineEditPrenom.text(),
'lastname' : self.lineEditNom.text(),
'DateDeNaissance' : DateDeNaissance[-2:] + DateDeNaissance[5:7] + DateDeNaissance[:4],
'LieuDeNaissance' : self.lineEditLieuNaissance.text(),
'Adresse' : self.lineEditAdresse.text(),
'Ville' : self.lineEditVille.text(),
'CodePostal' : self.lineEditCodePostal.text(),
'DateDeSortie' : DateDeSortie[-2:] + DateDeSortie[5:7] + DateDeSortie[:4],
'Heure' : str(self.timeEditSortie.time().hour()),
with open('TestJson.json','r') as f:
data = json.load(f)
data['users'].append(new_user)
with open('TestJson.json','w') as f:
json.dump(data,f,indent=3)
super().accept()
请注意,Designer 会自动将按钮框的accepted
和rejected
信号连接到对话框的相关accept
和reject
插槽。如果您不想重建整个 GUI 并仍然添加按钮框,只需创建一个带有按钮的新对话框并将按钮框按住 ctrl 并拖动到现有界面,但您必须手动重新创建连接;您可以使用 Designer 的信号/插槽编辑模式(编辑菜单 -> 编辑信号/插槽或 F4)或在您的代码中执行此操作:
class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
def __init__(self,parent=None):
super(AddUserDialog,self).__init__(parent)
self.setupUi(self)
self.buttonBox.button(self.buttonBox.Ok).setText('Add user')
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
# ...
【讨论】:
【参考方案2】:您可以在创建 AddUserDialog 实例时将组合框作为参数传递:
class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
def __init__(self,parent=None, combobox= None):
super(AddUserDialog,self).__init__(parent)
self.setupUi(self)
self.combobox = combobox
在 AddUser 方法中,使用self.combobox
:
# MainWindow.UserComboBox.addItem(new_user['firstname'] + ' ' + new_user['lastname'])
self.combobox.addItem(new_user['firstname'] + ' ' + new_user['lastname'])
或者,您在创建实例时已经知道对话框的父级。我认为super(AddUserDialog,self).__init__(parent)
行将为对话框设置self.parent
。然后在 AddUser 方法中,使用这个语句:
self.parent.UserComboBox..addItem(new_user['firstname'] + ' ' + new_user['lastname'])
【讨论】:
以上是关于如何从另一个类 PyQT 向 QComboBox 添加项目?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PyQt/PySide 中将项目添加到 QComboBox
Python / PyQt4:如何使 QComboBox 项可拖动
如何从 QComboBox 中获取所选项目以显示在 PyQt5 的 QTableWidget 中? (QComboBox 有复选框来选择项目)