0

I have subclassed QTableView to implement contextMenuEvent. Now if I create an instance of my subclass I have to call the methods (like shown below in the example) instead of passing them as keyword arguments. But if I don't call the __init__ method it accepts keyword arguments.

I wasn't able to figure out how I would have to subclass QTableView correctly to be able to use keyword arguments when instantiating it. This question is not just about how to use functionality when subclassing in general, it's more about understanding how it works.

I read through documentation and browsed the code of the related .pyi files, but it's still not clear to me.

Example:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


data = ["file_name", "file_infos"]

class MyCustomTable(QTableView):
    # if I don't call __init__ I'm able to use the
    # keyword arguments below when instantiating the class
    def __init__(self, parent):
        super().__init__(parent)

    def contextMenuEvent(self, event):
        """Create context menu, etc."""


class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.resize(450, 280)
        centralwidget = QWidget(self)

        # custom_table
        custom_table = MyCustomTable(
            centralwidget,
            selectionBehavior=QAbstractItemView.SelectRows,
            editTriggers=QAbstractItemView.NoEditTriggers,
            sortingEnabled=True
        )

        #if instantiating my subclass of QTableView then I would
        #have to call this methods instead of passing them as
        #keyword arguments:

        #self.setSelectionBehavior(QAbstractItemView.SelectRows)
        #self.setEditTriggers(QAbstractItemView.NoEditTriggers)
        #self.setSortingEnabled(True)

        self.model = QStandardItemModel(0, 2, centralwidget)
        self.model.setHorizontalHeaderLabels(["column 1", "column 2"])
        custom_table.setModel(self.model)

        v_layout1 = QVBoxLayout(centralwidget)
        v_layout1.addWidget(custom_table)
        self.setCentralWidget(centralwidget)

    def populate_table(self):
        self.model.setRowCount(0)
        for item in data:
            self.model.insertRow(0)
            for i, text in enumerate(data):
                self.model.setItem(0, i, QStandardItem(text))


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)

    mainUI = Ui_MainWindow()
    mainUI.populate_table()
    mainUI.show()

    sys.exit(app.exec_())

Output:

Traceback (most recent call last):
  File "/home/mvce/subclassing.py", line 28, in init_ui
    custom_table = MyCustomTable(
TypeError: __init__() got an unexpected keyword argument 'selectionBehavior'
Joey
  • 1,436
  • 2
  • 19
  • 33

1 Answers1

0

What you need are to capture the keyword-arguments or kwargs. This answer should help: https://stackoverflow.com/a/1769475/6569951

Basically, parent in MyCustomTable is one argument. If you want an arbitray number of key-word arguments, you need to use ** before the parameter name, such as **parent or **kwargs .

SuperDyl
  • 40
  • 1
  • 8
  • Okay, I called `def __init__(self, parent, **kwargs)` and now it accepts the kwargs. But there's no functionality. – Joey Apr 29 '20 at 06:20
  • You should either replace all instances of "parent" with **parent or **kwargs . I'm fairly certain that you don't need both in the parameters. – SuperDyl Apr 29 '20 at 06:22
  • Calling `def __init__(self, *args, **kwargs):` and `super().__init__(*args, **kwargs)` did it. – Joey Apr 29 '20 at 06:25
  • Glad to hear! That's a great way to set up your code :) – SuperDyl Apr 29 '20 at 06:35