如何将 QTableView 项目的方向从垂直更改为水平?

How to change QTableView items Orientation from Vertical to Horizontal?

下面的代码创建了一个 window,其中放置了两个 QTableView side-by-side:

left-side TableView 链接到 QAbstractTableModel。根据 Model.data() 中定义的逻辑,tableView 的项目是垂直放置的。

right-side TableView 链接到 QSortFilterProxyModel。我想用它来将垂直的 TableView 项目放置更改为水平。

请 post 您就如何实现这一目标提出建议。如果更改项目方向的解决方案不需要 ProxyModel 也没关系......只要它有效!

稍后发布源代码。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class Model(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = ['Row0_Column0','Row0_Column1','Row0_Column2']

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        row=index.row()
        if row<len(self.items):
            return QVariant(self.items[row])
        else:
            return QVariant()

class Proxy(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy, self).__init__()

    def rowCount(self, parent):
        return 1 
    def columnCount(self, parent):
        sourceModel=self.sourceModel()
        return len(sourceModel.items) 

    def filterAcceptsRow(self, row, parent):
        sourceModel=self.sourceModel()
        sourceModelIndex=sourceModel.index(row, 0, QModelIndex())

        sourceModelIndexName=sourceModel.data(sourceModelIndex, Qt.DisplayRole).toString()
        return True

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

        tablemodel=Model(self)               

        proxy=Proxy()
        proxy.setSourceModel(tablemodel)

        tableviewA=QTableView() 
        tableviewA.setModel(tablemodel)

        tableviewB=QTableView() 
        tableviewB.setModel(proxy)

        layout = QHBoxLayout(self)
        layout.addWidget(tableviewA)
        layout.addWidget(tableviewB)
        self.setLayout(layout)

    def test(self, arg):
        print arg

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

一个有趣的作业...

class Model2(QAbstractTableModel):
    def __init__(self, model, parent=None):
        self.model = model
        QAbstractTableModel.__init__(self, parent)

    def rowCount(self):
        return self.model.columnCount()

    def columnCount(self):
        return self.model.rowCount()

    def data(self, a, b):
        return self.model.data(b, a)

这是使用代理将项目从垂直方向重新定向为水平方向的有效解决方案。

诀窍是通过在代理模型下声明它来覆盖源模型的 .data() 方法。在 Proxy 上声明时,它优先于源模型的 .data() 方法:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class Model(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = ['Row0_Column0','Row0_Column1','Row0_Column2']

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return len(self.items)  

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        row=index.row()
        if row<len(self.items):
            return QVariant(self.items[row])
        else:
            return QVariant()

    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid():            
            if role == Qt.EditRole:                
                row = index.row()
                self.items[row]=value  
                return True
        return False

class Proxy(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy, self).__init__()        

    def rowCount(self, parent):
        return 1 
    def columnCount(self, parent):
        sourceModel=self.sourceModel()
        return len(sourceModel.items) 

    def filterAcceptsRow(self, row, parent):
        sourceModel=self.sourceModel()
        sourceModelIndex=sourceModel.index(row, 0, QModelIndex())

        sourceModelIndexName=sourceModel.data(sourceModelIndex, Qt.DisplayRole).toString()
        return True

    def data(self, index, role):
        sourceModel=self.sourceModel()
        items=sourceModel.items

        if not index.isValid(): return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        row=index.row()
        column=index.column()

        if column<len(items):
            return QVariant(items[column])
        else:
            return QVariant()


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

        tablemodel=Model(self)               

        proxy=Proxy()
        proxy.setSourceModel(tablemodel)

        tableviewA=QTableView() 
        tableviewA.setModel(tablemodel)

        tableviewB=QTableView() 
        tableviewB.setModel(proxy)

        layout = QHBoxLayout(self)
        layout.addWidget(tableviewA)
        layout.addWidget(tableviewB)
        self.setLayout(layout)

    def test(self, arg):
        print arg

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

这是受 mdurant 答案启发的第二个解决方案。我在这里起诉两个 QAbstractTableModel。第二个模型查询第一个模型self.items数据变量。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class Horizontal(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = ['Row0_Column0','Row0_Column1','Row0_Column2']
        self.childModel=None

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        row=index.row()
        if row<len(self.items):
            return QVariant(self.items[row])
        else:
            return QVariant()

    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid():            
            if role == Qt.EditRole:                
                row = index.row()
                self.items[row]=value  
                if self.childModel: self.childModel.reset()
                return True
        return False

class Vertical(QAbstractTableModel):
    def __init__(self, items=None, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = items

    def rowCount(self, parent):
        return 1      
    def columnCount(self, parent):
        return len(self.items)    

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        column=index.column()
        if column<len(self.items):
            return QVariant(self.items[column])
        else:
            return QVariant()

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

        modelV=Horizontal(self)         

        tableviewA=QTableView() 
        tableviewA.setModel(modelV)

        modelH=Vertical(modelV.items)
        modelV.childModel=modelH

        tableviewB=QTableView() 
        tableviewB.setModel(modelH)

        layout = QHBoxLayout(self)
        layout.addWidget(tableviewA)
        layout.addWidget(tableviewB)
        self.setLayout(layout)

    def test(self, arg):
        print arg

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())