使用 PyQt 创建带有滑块的模型/视图接口

假设我们有一个 GUI,其中包含许多滑块,而我们想要的是,当底层数据发生变化时,滑块的位置会自动更新,而不是手动更新。为了实现这个目标,我们可以将数据存储在 QAbstractListModel 的子类中,然后让滑块的位置自动更新。
在这里插入图片描述

from PyQt4 import QtCore

class myDataModel(QtCore.QAbstractListModel):
    def __init__(self, initData, parent=None):
        super(myDataModel, self).__init__(parent)
        self.__data = initData

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if not index.isValid():
            return None

        if index.row() > len(self.__data):
            return None

        if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
            return self.__data[index.row()]

        return None

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.__data)

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if not index.isValid() or role != QtCore.Qt.EditRole:
            return False

        self.__data[index.row()] = value
        self.dataChanged.emit(index, index)
        return True

我们的问题是如何将这个模型与 GUI 中的滑块连接起来,以便当模型中的数据发生改变时,滑块也会发生变化,反之亦然。

2、解决方案

以下是如何将模型与 GUI 中的滑块连接起来的代码示例:

import sys
from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        main_layout = QtGui.QVBoxLayout()
        # Create the model
        self.model = MyModel()
        # Create a slider and link it to the model
        self.slider1 = QtGui.QSlider()
        self.model.add_slider(self.slider1)
        main_layout.addWidget(self.slider1)
        # Add a lineEdit and button to force update the model
        # Note that the LineEdit is not linked to the model, so won't update with the slider
        self.edit = QtGui.QLineEdit()
        button = QtGui.QPushButton('update model')
        button.clicked.connect(self.on_clicked)
        main_layout.addWidget(self.edit)
        main_layout.addWidget(button)
        self.setLayout(main_layout)

    def on_clicked(self):
        self.model.update_model(int(self.edit.text()), self.slider1)

class MyModel(QtGui.QStandardItemModel):
    def __init__(self, *args, **kwargs):
        super(MyModel, self).__init__(*args, **kwargs)
        self._slider_list = {}
        self.itemChanged.connect(self.on_item_changed)

    def add_slider(self, slider):
        if slider in self._slider_list:
            raise Exception('You cannot link a slider to the model twice')
        item = QtGui.QStandardItem(str(slider.value()))
        self._slider_list[slider] = item
        self.appendRow(item)
        slider.valueChanged.connect(lambda value: self.update_model(value, slider))

    def update_model(self, value, slider):
        if str(value) != self._slider_list[slider].text():
            self._slider_list[slider].setText(str(value))
            print('update_model: %d' % value)

    def on_item_changed(self, item):
        slider = self._slider_list.keys()[self._slider_list.values().index(item)]
        if slider.value() != int(item.text()):
            slider.setValue(int(item.text()))
            print('on_item_changed: %s' % item.text())

app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

这个解决方案使用 QDataWidgetMapper 将模型与滑块连接起来。当模型中的数据发生变化时,滑块的位置会自动更新。反之亦然。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值