带有QComboBox控件的QDataWidgetMapper,动态更改下拉列表中的可用项

时间:2017-11-29 16:17:24

标签: python qt pyqt qt5 pyqt5

我正在编写一个编辑器,用于为不同的系统配置一些属性。我有一个表模型用于显示和编辑所有数据,它的设置如下:

           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_())

0 个答案:

没有答案