我正在编写一个编辑器,用于为不同的系统配置一些属性。我有一个表模型用于显示和编辑所有数据,它的设置如下:
RowCount | Text1Position | Text1 | Text2Position | Text2 | text3Position | ....
+----------+---------------+-------+---------------+-------+---------------+-----+
Graphic1 | 8 | 1 | 'xyz' | 3 | 'abc' | 2 |
+----------+---------------+-------+---------------+-------+---------------+-----+
Graphic2 | 16 | 16 | 'xyz' | 15 | 'abc' | 14 |
+----------+---------------+-------+---------------+-------+---------------+-----+
有32对文本和位置以及用于行计数的列。 (这是用于从存储在PLC AOI中的值填充的HMI弹出窗口,它有32个可以按任意顺序重新排列的行)行计数列用于确定弹出图形,大小如8/16/32。
对于我的GUI,我使用QDataWidgetMapper将编辑器面板上的每个控件映射到模型中的一列。然后我有一个listview来改变mapper的当前索引。每个位置列都映射到QComboBox。我想将其设置为每个组合框的下拉列表仅显示剩余位置的位置。位置0是“隐藏”,因此应该始终是一个选项。因此,对于上面的行Graphic1,下拉列表中的唯一项目应为:['隐藏',4,5,6,7,8]。
我想我想使用仅显示可用位置的代理模型,但我找不到一个例子。现在我使用一个QStringListModel作为所有组合框的源模型。我还尝试重写showPopup方法,用可用的项填充每个组合框的项目,但这会破坏列映射,然后不再更新。
在下面的示例代码中,我希望组合框下拉列表仅显示介于0和cboRows
中选择的任何值之间的值减去在其他组合框中选择的任何数字。有关如何实施的建议吗?
from PyQt5.QtWidgets import QApplication, QWidget, QComboBox, QVBoxLayout
from PyQt5.QtWidgets import QLineEdit, QGridLayout, QDataWidgetMapper, QPushButton, QLabel
from PyQt5.QtCore import QAbstractTableModel
import sys
class View(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.layout = QGridLayout(self)
self.lblRowNumber = QLabel()
self.layout.addWidget(self.lblRowNumber, 0, 0)
self.cboRows = QComboBox()
self.cboRows.addItems([str(x) for x in [8, 16, 24, 32]])
self.layout.addWidget(self.cboRows, 1, 0)
for i in range(32):
pos_name = f'cboPosition{i}'
txt_name = f'txtText{i}'
setattr(self, pos_name, QComboBox())
setattr(self, txt_name, QLineEdit())
self.layout.addWidget(getattr(self, pos_name), i+2, 0)
self.layout.addWidget(getattr(self, txt_name), i+2, 1)
getattr(self, pos_name).addItems([f'{i}' for i in range(32)])
self.mapper = QDataWidgetMapper()
def map_model(self, model):
self.mapper.setModel(model)
self.mapper.addMapping(self.cboRows, 0)
col = 1
for i in range(32):
self.mapper.addMapping(getattr(self, f'cboPosition{i}'), col)
col += 1
self.mapper.addMapping(getattr(self, f'txtText{i}'), col)
col += 1
def next_row(self):
self.mapper.setCurrentIndex((self.mapper.currentIndex() + 1) % self.mapper.model().rowCount())
self.lblRowNumber.setText(f'Row: {self.mapper.currentIndex()}')
class Model(QAbstractTableModel):
def __init__(self, plc=None, parent=None):
super().__init__(parent)
self.plc = plc
self.rows = {}
self._build()
def _build(self):
tags = {'Tag1', 'Tag2', 'Tag3', 'Tag4', 'Tag5'}
for row_idx, tag in enumerate(tags):
row = [16]
for i in range(32):
row.append(0)
row.append('Description')
self.rows[row_idx] = row
def rowCount(self, parent=None):
return len(self.rows)
def columnCount(self, parent=None):
return len(self.rows[0]) if self.rows else 0
def data(self, index, role=None):
val = self.rows[index.row()][index.column()]
return val
def setData(self, index, value, role=None):
self.rows[index.row()][index.column()] = value
return True
if __name__ == '__main__':
app = QApplication([])
m = Model()
v = View()
v.map_model(m)
v.mapper.setCurrentIndex(0)
w = QWidget()
l = QVBoxLayout(w)
btn = QPushButton('Next Row')
btn.clicked.connect(v.next_row)
l.addWidget(btn)
l.addWidget(v)
w.show()
sys.exit(app.exec_())