PySide:如何使用静态函数重载类

时间:2014-09-15 19:04:55

标签: python oop pyside

我想重载QInputDialog,因为我想将QCombobox替换为我自己的QCombobox派生词。我检查了QInputDialog的源代码,并尝试重载ensureCombobox()。但是,当我尝试类似的东西时:

class AutoCompleteInputDialog(QtGui.QInputDialog):

    def __init__(self, *args, **kwargs):
        self.ensureComboBox()
        super(AutoCompleteInputDialog, self).__init__(*args, **kwargs)


    def ensureComboBox(self):
        print "ensureComboBox"
        self.comboBox = AutoCompleteComboBox(self)
        self.comboBox.hide()

        self.comboBox.editTextChanged.connect(self.textChanged)
        self.comboBox.currentIndexChanged.connect(self.textChanged)

AutoCompleteInputDialog.getItems(None, "test title", "test label", ["albatross 12", "tiger 12", "item 2", "item 3"])

ensureCombobox永远不会被调用。

我还尝试定义一个创建QInputDialog并设置其组合框的静态方法。但它也不起作用。

    @staticmethod
    def getItem(*args, **kwargs):
        dialog = QtGui.QInputDialog()
        dialog.comboBox = AutoCompleteComboBox(dialog)
        return dialog.getItem(*args, **kwargs)

为完整起见,AutoCompleteCombobox

的代码
class AutoCompleteComboBox(QtGui.QComboBox):
    def __init__(self, *args, **kwargs):
        super(AutoCompleteComboBox, self).__init__(*args, **kwargs)

        self.setEditable(True)
        self.setInsertPolicy(self.NoInsert)

        # self.comp = QtGui.QCompleter([""], self)
        self.comp = CustomQCompleter([""], self)
        self.comp.setCompletionMode(QtGui.QCompleter.PopupCompletion)
        self.comp.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.setCompleter(self.comp)#
        self.setModel(["hallo babe", "world", "we", "are babe"])

    def setModel(self, strList):
        # self.comp.model().setStringList(strList)
        self.clear()
        self.insertItems(0, strList)
        self.comp.setModel(self.model())

    def focusInEvent(self, event):
        self.clearEditText()
        super(AutoCompleteComboBox, self).focusInEvent(event)

class CustomQCompleter(QtGui.QCompleter):
    """
    copied from: http://stackoverflow.com/a/7767999/2156909
    """
    def __init__(self, *args):#parent=None):
        super(CustomQCompleter, self).__init__(*args)
        self.local_completion_prefix = ""
        self.source_model = None

    def setModel(self, model):
        self.source_model = model
        super(CustomQCompleter, self).setModel(self.source_model)

    def updateModel(self):
        local_completion_prefix = self.local_completion_prefix
        class InnerProxyModel(QtGui.QSortFilterProxyModel):
            def filterAcceptsRow(self, sourceRow, sourceParent):
                index0 = self.sourceModel().index(sourceRow, 0, sourceParent)
                return local_completion_prefix.lower() in self.sourceModel().data(index0).lower()
        proxy_model = InnerProxyModel()
        proxy_model.setSourceModel(self.source_model)
        super(CustomQCompleter, self).setModel(proxy_model)

    def splitPath(self, path):
        self.local_completion_prefix = path
        self.updateModel()
        return ""

3 个答案:

答案 0 :(得分:4)

为了在PySide或PyQt中重新实现C ++方法,必须至少满足三个条件:

  1. 该方法必须是Qt公共API的一部分
  2. 该方法必须定义为虚拟
  3. PySide / PyQt必须为方法
  4. 提供python包装器

    注意,如果第二个条件不成立,那么python中的方法的重新实现永远不会被Qt内部调用,因此几乎没用。 Qt文档应该始终清楚地表明方法是否是虚拟的,例如:

        virtual QSize sizeHint() const
    

    因此,由于ensureCombobox没有满足上述条件,因此应该很清楚重新实现它并不会有效(正如您已经发现的那样)。

    但无论如何,对于像输入对话框这样简单的东西,尝试创建子类真的值得花费吗?它只是对话框中的四个小部件......

答案 1 :(得分:2)

好的,问题是当你调用QInputDialog时,它会在C ++中设置子窗口小部件 - 或者在我看来是这样的,所以你不能直接替换你最喜欢的味道。因此,您需要按照所示的更典型的路线:

class AutoCompleteInputDialog(QtGui.QDialog):

    def __init__(self, *args, **kwargs):
        super(AutoCompleteInputDialog, self).__init__(*args, **kwargs)
        self.comboBox = AutoCompleteComboBox(self)
        self.va = QtGui.QVBoxLayout(self)
        self.va.addWidget(self.comboBox)
        self.box = QtGui.QWidget(self)
        self.ha = QtGui.QHBoxLayout(self)
        self.va.addWidget(self.box)
        self.box.setLayout(self.ha)
        self.OK = QtGui.QPushButton("OK",self)
        self.OK.setDefault(True)
        self.cancel = QtGui.QPushButton("Cancel",self)
        self.ha.addWidget(self.OK)
        self.ha.addWidget(self.cancel)
        self.OK.clicked.connect(self.accept)
        self.cancel.clicked.connect(self.reject)

结果值存储在acid.comboBox.currentText()

答案 2 :(得分:0)

AutoCompleteInputDialog.getItems是一个类方法,在这种情况下,通过继承实际上与QtGui.QInputDialog.getItems相同。重载仅适用于实例方法,通过传递隐式self。所以为了使这个工作,您需要重新实现getItems,或者直接使用该类而没有便利功能:

acid = AutoCompleteInputDialog(parent=None)
#set up options, buttons
answer = acid.exec_()