如何从另一个类 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,因为 QDialogBu​​ttonBox 的默认按钮具有固定标签,并且它们都没有“添加”文本,但是可以根据需要重命名这些按钮。假设您的对话框上有一个名为buttonBox(带按钮的对话框的默认设置)的QDialogBu​​ttonBox,带有“确定”按钮,您可以直接在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 会自动将按钮框的acceptedrejected 信号连接到对话框的相关acceptreject 插槽。如果您不想重建整个 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 减小 QComboBox 的大小?

如何在 PyQt/PySide 中将项目添加到 QComboBox

Python / PyQt4:如何使 QComboBox 项可拖动

如何从 QComboBox 中获取所选项目以显示在 PyQt5 的 QTableWidget 中? (QComboBox 有复选框来选择项目)

如何将 pyqt5 qcomboBox 中的文本应用于列表值

PyQt5 组件之QComboBox