【发布时间】:2021-07-13 14:53:08
【问题描述】:
我正在尝试在 PyQT5 应用程序中显示 QListView 以显示一些数据。
我的目标是用复杂的表示来表示这些数据,而不仅仅是一行文本。
因此,我的 QListView 应该“实例化”从 Ui 文件加载的新 QWidget,并使用该 Ui 表示显示每个元素。
我的问题在于我的 Windows 布局。
我有一个主窗口,其中有一个 QSplitter,QListView 位于左侧,右侧有一些小部件(Label、textedit、...)
QMainWindow 设计器:
我想要表示为这个小部件的 QListView 的每一行:
小部件设计器:
似乎如果 QListView 在这样的小部件容器内:
Arbo 对象检查器:
然后我有一个奇怪的行为,其中子小部件显示在彼此之上:
ListView 小部件堆叠:
但是如果我删除 QListView 的容器 OkWindow 设计器:
和检查员的观点
它们显示正确
按预期工作:
知道为什么吗?
我的代码和在模型/视图 QListView 中实现复杂小部件表示的方式有什么问题吗?
这是应用示例的代码:
import typing
from PyQt5 import QtCore, uic
from PyQt5.QtCore import QAbstractListModel, QModelIndex, Qt
from PyQt5.QtWidgets import (
QApplication,
QStyledItemDelegate,
QWidget, QMainWindow, )
class Editor(QWidget):
def __init__(self, index, parent=None):
super().__init__(parent)
uic.loadUi('step.ui', self)
value = index.model().data(index, Qt.ItemDataRole)
self.label.setText(value)
class MyListModel(QAbstractListModel):
def __init__(self, parent=None):
super().__init__(parent)
self._data_list = []
def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> typing.Any:
if role == Qt.ItemDataRole:
return self._data_list[index.row()]
def rowCount(self, parent: QModelIndex = QModelIndex()) -> int:
return len(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.copy()
self.endResetModel()
class StyledItemDelegate(QStyledItemDelegate):
def __init__(self, parent):
QStyledItemDelegate.__init__(self, parent)
self.editor = None
def createEditor(self, parent, option, index):
self.editor = Editor(index, parent)
return self.editor
def sizeHint(self, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> QtCore.QSize:
if self.editor:
return self.editor.sizeHint()
else:
return super().sizeHint(option, index)
data = ["Apple", "Strawberry", "Cherry"]
class MainWindow(QMainWindow):
def __init__(self, qapp):
"""
Init main window
"""
super().__init__()
self.qapp = qapp
# Not working main_window ui file
# uic.loadUi('main_window.ui', self)
# Working main_window ui file
uic.loadUi('main_window_ok.ui', self)
self.load_data()
def load_data(self):
controller = MyCtrl(self)
controller.load_datalist()
class MyCtrl:
def __init__(self, parent: QMainWindow):
self.parent = parent
def load_datalist(self):
self.model = MyListModel()
self.model.data_list = data
self.parent.listView.setModel(self.model)
delegate = StyledItemDelegate(self.parent.listView)
self.parent.listView.setItemDelegate(delegate)
for i in range(self.model.rowCount()):
index = self.model.index(i, 0)
self.parent.listView.openPersistentEditor(index)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
main = MainWindow(app)
main.showMaximized()
sys.exit(app.exec_())
main_window.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>642</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListView" name="listView"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Ok</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>26</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
main_window_ok.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>799</width>
<height>642</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListView" name="listView"/>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Ok</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>799</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
step.ui 文件
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>387</width>
<height>173</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QDial" name="dial"/>
</item>
<item>
<widget class="QComboBox" name="comboBox"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
【问题讨论】:
标签: python model-view-controller pyqt5