Question

i have Two forms with two views connected to the same dataModel class, but when i change data on one form it does not change on the other.

i am trying to get a comboBox on several different dialogs/forms to get updated when the underlying data changes from another dialog/form.

here is my code:

class Model(QStringListModel):

    def __init__(self, parent=None):
        super(Model, self).__init__(parent)
        data = QStringList()
        data << "one" << "two" << "three" << "four" << "five"
        self.setStringList(data)


class Form_2(QDialog):

    def __init__(self, parent=None):
        super(Form_2, self).__init__(parent)
        self.model = Model()
        self.combo = QListView()
        self.combo.setModel(self.model)

        layout = QVBoxLayout()
        layout.addWidget(self.combo)
        self.setLayout(layout)


class Form_1(QDialog):

    def __init__(self, parent=None):
        super(Form_1, self).__init__(parent)
        self.model = Model()
        self.listView = QListView()
        self.listView.setModel(self.model)
        self.combo = QComboBox()
        self.combo.setModel(self.model)
        self.form2_button = QPushButton("Open Form_2")

        layout = QVBoxLayout()
        layout.addWidget(self.listView)
        layout.addWidget(self.combo)
        layout.addWidget(self.form2_button)
        self.setLayout(layout)

        self.connect(self.form2_button, SIGNAL("clicked()"), self.form_2)

    def form_2(self):
        self.ft = Form_2()
        self.ft.show()


app = QApplication(sys.argv)
form = Form_1()
form.show()
app.exec_()
Was it helpful?

Solution

Here is a basic example of how multiple views based on the same model update themselves when the any of those views is modified:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from PyQt4 import QtGui, QtCore

class MyDialog(QtGui.QWidget):
    def __init__(self, modelSource, parent=None):
        super(MyDialog, self).__init__(parent)

        self.tableView = QtGui.QTableView(self)
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.setModel(modelSource)

        self.listView = QtGui.QListView(self)
        self.listView.setModel(modelSource)
        self.listView.setModelColumn(0)

        self.comboBox = QtGui.QComboBox(self)
        self.comboBox.setModel(modelSource)
        self.comboBox.setModelColumn(1)

        self.layoutGrid = QtGui.QGridLayout(self)
        self.layoutGrid.addWidget(self.comboBox, 0, 0, 1, 2)
        self.layoutGrid.addWidget(self.listView, 1, 0, 1, 1)
        self.layoutGrid.addWidget(self.tableView, 1, 1, 1, 1)

class MyWindow(QtGui.QWidget):
    _dialogs = []
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)

        self.modelSource = QtGui.QStandardItemModel(self)

        for rowNumber in range(3):
            items = []
            for columnNumber in range(3):
                item = QtGui.QStandardItem()
                item.setText("row: {0} column {1}".format(rowNumber, columnNumber))

                items.append(item)

            self.modelSource.appendRow(items)

        self.labelDialogs = QtGui.QLabel(self)
        self.labelDialogs.setText("Select a number of dialogs to create:")

        self.spinBoxDialogs = QtGui.QSpinBox(self)
        self.spinBoxDialogs.setValue(3)

        self.pushButtonShow = QtGui.QPushButton(self)
        self.pushButtonShow.setText("Show Dialogs!")
        self.pushButtonShow.clicked.connect(self.on_pushButtonShow_clicked)

        self.pushButtonClose = QtGui.QPushButton(self)
        self.pushButtonClose.setText("Close Dialogs")
        self.pushButtonClose.clicked.connect(self.on_pushButtonClose_clicked)

        self.layoutHorizontal = QtGui.QHBoxLayout(self)
        self.layoutHorizontal.addWidget(self.labelDialogs)
        self.layoutHorizontal.addWidget(self.spinBoxDialogs)
        self.layoutHorizontal.addWidget(self.pushButtonShow)
        self.layoutHorizontal.addWidget(self.pushButtonClose)

    @QtCore.pyqtSlot()
    def on_pushButtonShow_clicked(self): 
        self._dialogs = []
        dialogsNumber = self.spinBoxDialogs.value()

        for dialogNumber in range(dialogsNumber):  
            dialog = MyDialog(self.modelSource)
            dialog.show()
            dialog.move(100, 100)

            self._dialogs.append(dialog)

    @QtCore.pyqtSlot()
    def on_pushButtonClose_clicked(self): 
        for dialog in self._dialogs:
            dialog.close()

        self._dialogs = []

if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)
    app.setApplicationName('MyWindow')

    main = MyWindow()
    main.show()

    sys.exit(app.exec_())

OTHER TIPS

Thanks to ccc.larc for giving me the answer. we basically have to only use one instance of the model, it doesn't work if there several instances of the model. so you always have to pass the same instance of the model to which ever form you want it to use.

if i understand correctly this is what @X.Jacobs is saying, i m just showing my new code which is a bit more simple and could be better understood what contrasting it with my previous code (that didn't work)

so my above code just needs a minor change.

class Model(QStringListModel):

    def __init__(self, parent=None): 
        super(Model, self).__init__(parent)
        data = QStringList()
        data << "one" << "two" << "three" << "four" << "five"
        self.setStringList(data)


class Form_2(QDialog):

    def __init__(self, model, parent=None): #get the model from the calling form
        super(Form_2, self).__init__(parent)
        self.model = model
        self.combo = QListView()
        self.combo.setModel(self.model)

        layout = QVBoxLayout()
        layout.addWidget(self.combo)
        self.setLayout(layout)


class Form_1(QDialog):

    def __init__(self, parent=None):
        super(Form_1, self).__init__(parent)
        self.model = Model()
        self.listView = QListView()
        self.listView.setModel(self.model)
        self.combo = QComboBox()
        self.combo.setModel(self.model)
        self.form2_button = QPushButton("Open Form_2")

        layout = QVBoxLayout()
        layout.addWidget(self.listView)
        layout.addWidget(self.combo)
        layout.addWidget(self.form2_button)
        self.setLayout(layout)

        self.connect(self.form2_button, SIGNAL("clicked()"), self.form_2)

    def form_2(self):
        self.ft = Form_2(self.model) #pass the same model to the new form
        self.ft.show()


app = QApplication(sys.argv)
form = Form_1()
form.show()
app.exec_()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top