PyQt custom widget not showing

2020-04-30 01:44发布

I'm new to PyQt.

I'm trying to put a QTableView in a class, so I can define it's behaviour in the class without mixing it with all the other code, but when I do so it just won't show.

Here's the code i'm learning from. It was borrowed from [ Edit table in pyqt using QAbstractTableModel ]. Readapted it slightly to use with Qt5 and moved the QTableView in a class

import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication, QVBoxLayout, QTableView, QWidget
from PyQt5.QtCore import *

# données à représenter
my_array = [['00','01','02'],
            ['10','11','12'],
            ['20','21','22']]

def main():
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

# création de la vue et du conteneur
class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        tablemodel = MyTableModel(my_array, self)
        table = Table(tablemodel)

        layout = QVBoxLayout(self)
        layout.addWidget(table)
        self.setLayout(layout)

# création du modèle

class Table(QWidget):
    def __init__(self, model):
        super().__init__()
        self.model = model
        self.initUI()

    def initUI(self):
        self.setMinimumSize(300,300)
        self.view = QTableView()
        self.view.setModel(self.model)


class MyTableModel(QAbstractTableModel):
    def __init__(self, datain, parent = None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.arraydata = datain

    def rowCount(self, parent):
        return len(self.arraydata)

    def columnCount(self, parent):
        return len(self.arraydata[0])

    def data(self, index, role):
        if not index.isValid():
            return None
        elif role != Qt.DisplayRole:
            return None
        return (self.arraydata[index.row()][index.column()])

    """
    def setData(self, index, value):
        self.arraydata[index.row()][index.column()] = value
        return True
    def flags(self, index):
        return Qt.ItemIsEditable
    """    

if __name__ == "__main__":
    main()

If I remove the class and use

table = QTableView()
table.setModel(tablemodel)

the table shows no problem.

What am I missing?

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-04-30 01:59

the problem: table.view has no parent. If you add self.view.show() to test to Table.initUi(), you get two widgets, MyWindow with empty table as tmoreau wrote and table.view as isolated widget.

You can either pass a parent when constructing table.view in Table.initUi()

self.view = QTableView(self) 

(then you don't need a layout) or add table.view to a layout as written by tmoreau, Then the tableview is reparented.

Removing the class has the same effect, then the tableview is added to layout.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2020-04-30 02:09

You defined Tableas a QWidget with an attribute self.view=QTableView. But you didn't define a layout on Table, so it will be displayed as an empty widget.

You either have to define a layout for Table, and add the view to it, or directly add the view to the main window's layout:

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        tablemodel = MyTableModel(my_array, self)
        table = Table(tablemodel)

        layout = QVBoxLayout(self)
        layout.addWidget(table.view)  #add view instead of table
        self.setLayout(layout)

A third way is to change the definition of Table: you could subclass QTableView instead of QWidget (code not tested):

class Table(QTableView):
    def __init__(self, model, parent):
        super(Table,self).__init__(parent)
        self.setMinimumSize(300,300)
        self.setModel(model) 
查看更多
登录 后发表回答