我想基于两个QComboBox的选定文本启用或禁用QDialogBu​​ttonBox或最好仅启用QDialog中的“确定”按钮。

我的示例如下。当前不起作用,启用或禁用QDialogBu​​ttonBox时,两个ComboBox彼此独立工作。

import sys

from PyQt5.QtCore import QSignalMapper, pyqtSlot
from PyQt5.QtWidgets import (QGroupBox, QFormLayout, QLabel, QComboBox,
                             QApplication, QDialog, QDialogButtonBox,
                             QVBoxLayout)


class SheetColumns(QDialog):
    def __init__(self, column_header):
        super().__init__()

        self.setMinimumWidth(300)
        self.setWindowTitle("Input Column Names")

        self.column_headers = column_header

        self.column_headers.insert(0, ' ')
        self.setWhatsThis('Please match columns in your data sheet names'
                          ' with the right side labels')

        col_names = ["Student Name:", "Student ID:", "Cohort:", "Gender:",
                     "College:", "Department:", "Major:", "Minor", "Email:",
                     "Adviser", "Adviser Email"]
        self.form_group_box = QGroupBox("Specify Column Names")
        self.layout = QFormLayout()
        for col_name in col_names:
            combo = QComboBox()
            combo.addItems(self.column_headers)
            self.layout.addRow(QLabel(col_name), combo)
        self.form_group_box.setLayout(self.layout)

        self.button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

        self.button_box.setEnabled(False)

        self.layout.itemAt(0, 1).widget().currentTextChanged.connect(
            self.check_validity)
        self.layout.itemAt(1, 1).widget().currentTextChanged.connect(
            self.check_validity)

        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        main_layout = QVBoxLayout()
        main_layout.addWidget(self.form_group_box)
        main_layout.addWidget(self.button_box)
        self.setLayout(main_layout)

    def check_validity(self, text):
        print(text)
        if text == ' ':
            self.button_box.setEnabled(False)
        else:
            self.button_box.setEnabled(True)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = SheetColumns(['name student', 'id', 'cohort', 'test 1'])
    sys.exit(dialog.exec_())


我希望当两个ComboBox中的currentText不是''时启用QDialogBu​​ttonBox,而当它们都为''时禁用QDialogBu​​ttonBox。

我尝试使用QSignalMapper

但是,我无法使其正常运行。

class SheetColumns(QDialog):
    def __init__(self, column_header):
        super().__init__()

        self.setMinimumWidth(300)
        self.setWindowTitle("Input Column Names")

        self.column_headers = column_header

        self.column_headers.insert(0, ' ')
        self.setWhatsThis('Please match columns in your data sheet names'
                          ' with the right side labels')

        col_names = ["Student Name:", "Student ID:", "Cohort:", "Gender:",
                     "College:", "Department:", "Major:", "Minor", "Email:",
                     "Adviser", "Adviser Email"]
        self.form_group_box = QGroupBox("Specify Column Names")
        self.layout = QFormLayout()
        for col_name in col_names:
            combo = QComboBox()
            combo.addItems(self.column_headers)
            self.layout.addRow(QLabel(col_name), combo)
        self.form_group_box.setLayout(self.layout)

        self.button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

        self.button_box.setEnabled(False)

        self.mapper = QSignalMapper(self)

        comb_bx1 = self.layout.itemAt(0, 1).widget()
        comb_bx2 = self.layout.itemAt(1, 1).widget()

        comb_bx1.currentTextChanged.connect(self.mapper.map)
        comb_bx2.currentTextChanged.connect(self.mapper.map)

        self.mapper.setMapping(comb_bx1, comb_bx1.currentText())
        self.mapper.setMapping(comb_bx2, comb_bx2.currentText())

        self.mapper.mapped.connect(self.check_validity)

        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        main_layout = QVBoxLayout()
        main_layout.addWidget(self.form_group_box)
        main_layout.addWidget(self.button_box)
        self.setLayout(main_layout)

    def check_validity(self, text):
        print(text)
        if text == ' ':
            self.button_box.setEnabled(False)
        else:
            self.button_box.setEnabled(True)


有人可以告诉我我做错了什么吗,还是有更好的办法?

提前致谢

最佳答案

使用QSignalMapper可以满足您的需求,在这种情况下,您只需要遍历QComboBox并确认它们没有适当的选项,并根据该选项启用按钮,如下所示:

class SheetColumns(QDialog):
    def __init__(self, column_header, parent=None):
        super().__init__(parent)

        self.setMinimumWidth(300)
        self.setWindowTitle("Input Column Names")

        self.column_headers = column_header

        self.setWhatsThis(
            "Please match columns in your data sheet names"
            " with the right side labels"
        )

        col_names = [
            "Student Name:",
            "Student ID:",
            "Cohort:",
            "Gender:",
            "College:",
            "Department:",
            "Major:",
            "Minor",
            "Email:",
            "Adviser",
            "Adviser Email",
        ]

        self.combos = []

        flay = QFormLayout()
        for i, col_name in enumerate(col_names):
            combo = QComboBox()
            combo.addItems([""] + self.column_headers)
            flay.addRow(col_name, combo)
            if i in (0, 1):
                combo.currentIndexChanged.connect(self.check_validity)
                self.combos.append(combo)

        self.form_group_box = QGroupBox("Specify Column Names")
        self.form_group_box.setLayout(flay)

        self.button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        )
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        main_layout = QVBoxLayout(self)
        main_layout.addWidget(self.form_group_box)
        main_layout.addWidget(self.button_box)

    @pyqtSlot()
    def check_validity(self):
        is_enabled = True
        for combo in self.combos:
            if not combo.currentText():
                is_enabled = False
                break
        button = self.button_box.button(QDialogButtonBox.Ok)
        button.setEnabled(is_enabled)




@TheKewlStore在他的答案中指出了一些错误:QObjects的所有权不是由Python处理,而是由C ++部分处理。 python中一个QObject的所有权具有一个创建它的类,如果它是一个属性(在OP的示例中不满足),或者具有另一个QObject,它是在创建它或使用setParent时设置的父对象() 方法。对于QWidget,当您将其添加到布局中时,它会将其管理的小部件设置为父级。在您的情况下,QComboBoxes的所有权是QGroupBox,因此GC没有问题。

关于python - 基于多个QComboBox的文本启用或禁用QDialogBu​​ttonBox,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59181970/

10-12 05:18