Benjamin
Benjamin

Reputation: 308

Qt and Python Data

I am writing a Python Programm that mainly consists of Data organized in a Python object and I want to write a GUI using PyQt for it.

Since I want to be able to use the Python part without the GUI as well, I don't want Qt code in my Data structure. Qt encourages you to separate the data model from the GUI/View part of the program, so I thought this approach should be fairly common in PyQt. However I don't understand how the Data is to be connected and kept persistent with the GUI.

I think I understand the model/view concept - but it seems to me that the model in Qt terms is a Qt object as well and would need to be kept in sync with my pure python object so I don't see the point of it.

I guess there is still something crucial that I don't understand yet. Can anyone give me a hint?

Update 1:

Following Armatita's comment I give the following minimal example:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
#Python Data:
class car:
    def __init__(self, name, color):
        self.name = name
        self.color = color

#Window:
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(650, 510, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.treeView = QtWidgets.QTreeView(self.centralwidget)
        self.treeView.setGeometry(QtCore.QRect(30, 20, 591, 481))
        self.treeView.setObjectName("treeView")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(680, 120, 113, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(630, 120, 46, 13))
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Apply"))
        self.label.setText(_translate("MainWindow", "Value"))

if __name__ == "__main__":
    #create Data
    blue_car = car("family_car", "blue")
    red_car = car("sports_car", "red")

    #open UI
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

    #now I would like to show the cars and their properties (name, color) in the treeview...

In this Example I would like to show the cars I created in the tree view Widget and manipulate them with the input field an the apply button.

Upvotes: 2

Views: 635

Answers (1)

armatita
armatita

Reputation: 13465

There are typically two types of interfaces to widgets in Qt. One is the view version, the other is the widget version (which inherits the view). The easiest to use is the widget version, and for what you seem to be trying to do it is what I recommend.

Also, although its possible to software the way you were doing it is generally better to follow the more common conventions. I've adapted your code (including the way you build the MainWindow) to have the small GUI working with a new method (addCar) to add your car class information to the QTreeWidget:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
#Python Data:
class car:
    def __init__(self, name, color):
        self.name = name
        self.color = color

#Window:
class Ui_MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()

        self.setupUi()

    def setupUi(self):
        self.setObjectName("MainWindow")
        self.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(650, 510, 75, 23))
        self.pushButton.setObjectName("pushButton")

        # self.treeView = QtWidgets.QTreeView(self.centralwidget)
        self.treeView = QtWidgets.QTreeWidget(self.centralwidget)
        self.treeView.setColumnCount(1)
        self.treeView.setGeometry(QtCore.QRect(30, 20, 591, 481))
        self.treeView.setObjectName("treeView")

        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(680, 120, 113, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(630, 120, 46, 13))
        self.label.setObjectName("label")
        self.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        self.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        self.retranslateUi()
        QtCore.QMetaObject.connectSlotsByName(self)

    def addCar(self, car, name):
        item = QtWidgets.QTreeWidgetItem([name])
        child1 = QtWidgets.QTreeWidgetItem(["Type: " + car.name])
        child2 = QtWidgets.QTreeWidgetItem(["Type: " + car.color])
        item.addChild(child1)
        item.addChild(child2)
        self.treeView.addTopLevelItem(item)

    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Apply"))
        self.label.setText(_translate("MainWindow", "Value"))

if __name__ == "__main__":
    #create Data
    blue_car = car("family_car", "blue")
    red_car = car("sports_car", "red")

    #open UI
    app = QtWidgets.QApplication(sys.argv)
    # MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    # ui.setupUi(MainWindow)

    # Add car object
    ui.addCar(blue_car, "Blue Car")
    ui.addCar(red_car, "Red Car")

    ui.show()
    sys.exit(app.exec_())

The result is this:

Main Window and QTree Widget example

Also I recommend you try checking out an online quick tutorial for pyQt5 (arbitrary example: zetcode) since if you start building software now using the methodology it seems to me you were trying to apply you'll end up re-writing most of it in the future (I think...). I've made the same mistake in the past.

Upvotes: 1

Related Questions