【发布时间】:2021-07-20 23:53:22
【问题描述】:
我正在尝试制作一个 QListView,其中每行都表示有一个复杂的小部件。
我想要一个 QLabel 和一个 QTableView 代表一些数据。
到目前为止一切顺利。
问题是当我点击 QTableView(我禁用了焦点策略)时,它没有选择 QListView 的行。
但是当我点击 QLabel(这也是禁用焦点策略)时它正在工作
我做错了什么吗?我的 change_line 方法确实在单击“这是行”标签时被调用,但不是在它下面的表格上:(
我曾尝试在编辑器中使用 FocusPolicy 和 setFocusProxy,但到目前为止还不能正常工作。
感谢您的帮助
import sys
from typing import Any, Dict
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QAbstractListModel, QModelIndex, Qt, QAbstractTableModel, QSize
from PyQt5.QtMultimedia import QMediaMetaData
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QListView, QWidget, QStyledItemDelegate, \
QTableView, QHeaderView, QAbstractScrollArea, QLabel
class TableModel(QAbstractTableModel):
def __init__(self):
super().__init__()
self._data_list = []
@property
def data_list(self):
return self._data_list
@data_list.setter
def data_list(self, data_list):
self.beginResetModel()
self._data_list = data_list
self.endResetModel()
def headerData(self, section: int, orientation: QMediaMetaData.Orientation, role: int = ...) -> Any:
if role == Qt.DisplayRole:
if section == 0:
return "header"
def data(self, index: QModelIndex, role: int = ...) -> Any:
if index.column() == 0:
if role == Qt.DisplayRole:
return self.data_list[index.row()]
def rowCount(self, parent: QModelIndex = ..., *args, **kwargs) -> int:
return len(self.data_list)
def columnCount(self, parent: QModelIndex = ..., *args, **kwargs) -> int:
return 1
class ListModel(QAbstractListModel):
def __init__(self):
super().__init__()
def rowCount(self, parent=QModelIndex(), *args, **kwargs) -> int:
return 2
def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any:
if index.row() == 0:
if role == Qt.DisplayRole:
return ["Hello", "World!"]
elif index.row() == 1:
if role == Qt.DisplayRole:
return ["One", "Two", "Three!"]
class ItemEditor(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.verticalLayout = QVBoxLayout(self)
self.line_label = QLabel("This is a line", self)
self.verticalLayout.addWidget(self.line_label)
self.table_view = QTableView(self)
self.table_view.setFocusPolicy(QtCore.Qt.NoFocus)
self.table_view.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.table_view.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.table_view.horizontalHeader().setVisible(False)
self.table_view.verticalHeader().setVisible(False)
self.verticalLayout.addWidget(self.table_view)
class StyledItemDelegate(QStyledItemDelegate):
def __init__(self, parent):
super(StyledItemDelegate, self).__init__(parent)
self.editors: Dict[int, QTableView] = {}
def sizeHint(self, option: 'QStyleOptionViewItem', index: QModelIndex) -> QSize:
if index.row() in self.editors.keys():
return QSize(min(self.parent().width(), self.editors[index.row()].sizeHint().width()),
self.editors[index.row()].sizeHint().height())
else:
return super(StyledItemDelegate, self).sizeHint(option, index)
def createEditor(self, parent, option, index):
editor = ItemEditor(parent)
editor.setFocusProxy(parent)
editor.table_view.setModel(TableModel())
editor.table_view.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
header = editor.table_view.horizontalHeader()
header.setSectionResizeMode(0, QHeaderView.Stretch)
return editor
def setEditorData(self, editor: QTableView, index):
editor.table_view.model().data_list = index.data()
self.editors[index.row()] = editor
def change_line(index: QModelIndex):
# FIXME Only working when clicking on the "editor" widget or the QLabel, not on the Table
print(f"Changing to line {index.row()}")
if __name__ == "__main__":
app = QApplication([])
main_window = QMainWindow()
centralwidget = QWidget(main_window)
verticalLayout = QVBoxLayout(centralwidget)
listView = QListView(centralwidget)
listView.clicked.connect(change_line)
verticalLayout.addWidget(listView)
main_window.setCentralWidget(centralwidget)
listModel = ListModel()
listView.setModel(listModel)
delegate = StyledItemDelegate(listView)
listView.setItemDelegate(delegate)
for i in range(listModel.rowCount()):
index = listModel.index(i, 0)
listView.openPersistentEditor(index)
main_window.resize(600,400)
main_window.show()
sys.exit(app.exec_())
【问题讨论】:
-
表格永远不会接受任何鼠标事件吗?
-
确实,表格应该只允许单击以选择父行,仅此而已。这只是一个“只读”视图
标签: python model-view-controller pyqt5