简体   繁体   中英

AttributeError: 'NoneType' object has no attribute 'setText'

I'm having trouble with a script to add, load and remove stuff from a JSON file, I'm only being able to edit two rows of items from the JSON, only being able to add stuff after the JSON was loaded in the GUI and not removing stuff for now.

Here's the code and the JSON files:

from PyQt5 import QtCore, QtGui, QtWidgets

import json

class Ui_Dialog(object):

    def botao_adicionar_clicked(self):
        QtWidgets.QTreeWidgetItem(self.lista_de_itens)

        with open('data.json', 'r') as file:
            data = json.load(file)
            for item in data['database']:
                num_id = int(item["num"])
                print(num_id + 1)

        item_input = self.box_item.text()
        valor_input = self.box_valor.text()
        unidades_input = self.box_unidades.text() 
        item_output = str(item_input)
        unidades_output = str(unidades_input)
        valor_output = str(valor_input)

        for item in data['database']:
            self.lista_de_itens.topLevelItem(num_id + 1).setText(0, item_output)

            self.lista_de_itens.topLevelItem(num_id + 1).setText(1, unidades_output)

            self.lista_de_itens.topLevelItem(num_id + 1).setText(2, valor_output)

        final_id = str(num_id + 1)

        item_final = {"num": final_id, "item":item_output, "unidades":unidades_output, "valor":valor_input}

        data["database"].append(item_final)

        with open('data.json', 'w') as file:
            json.dump(data, file, indent=4)

    def botao_carregar_clicked(self):
        QtWidgets.QTreeWidgetItem(self.lista_de_itens)

        with open('data.json', 'r') as file:
            data = json.load(file)
            #print(data['num'].count(["num"]))
            for item in data['database']:
                num_id = int(item["num"])
                print(num_id + 1)


        for item in data['database']:
            self.lista_de_itens.topLevelItem(int(item["num"])).setText(0, item["item"])
        for unidades in data['database']:
            self.lista_de_itens.topLevelItem(int(item["num"])).setText(1, unidades["unidades"])
        for valor in data['database']:
            self.lista_de_itens.topLevelItem(int(item["num"])).setText(2, valor["valor"])

    def botao_remover_clicked(self):
        QtWidgets.QTreeWidgetItem(self.lista_de_itens)

        with open('data.json', 'r+') as file:
            data = json.load(file)

        item_input = self.box_item.text()
        valor_input = self.box_valor.text()
        unidades_input = self.box_unidades.text() 
        item_output = str(item_input)
        unidades_output = str(unidades_input)
        valor_output = str(valor_input)

        if item_output in data['item']:
            del item_output
        elif unidades_output in data['unidades']:
            del unidades_output
        elif valor_output in data['valor']:
            del valor_output
        else:
            print('Não existe no BD')

        with open('data.json', 'w') as file:
            #item_final = {"item":item_output,"unidades":unidades_output,"valor":valor_input}
            json.dump(data, file)

    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(339, 329)
        Dialog.setSizeGripEnabled(False)
        self.lista_de_itens = QtWidgets.QTreeWidget(Dialog)
        self.lista_de_itens.setGeometry(QtCore.QRect(10, 10, 321, 191))
        self.lista_de_itens.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.lista_de_itens.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.lista_de_itens.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
        self.lista_de_itens.setAutoScroll(True)
        self.lista_de_itens.setIndentation(1)
        self.lista_de_itens.setRootIsDecorated(False)
        self.lista_de_itens.setUniformRowHeights(True)
        self.lista_de_itens.setItemsExpandable(False)
        self.lista_de_itens.setAnimated(False)
        self.lista_de_itens.setWordWrap(True)
        self.lista_de_itens.setExpandsOnDoubleClick(False)
        self.lista_de_itens.setObjectName("lista_de_itens")

        QtWidgets.QTreeWidgetItem(self.lista_de_itens)

        self.lista_de_itens.header().setVisible(True)
        self.lista_de_itens.header().setCascadingSectionResizes(False)
        self.lista_de_itens.header().setDefaultSectionSize(94)
        self.lista_de_itens.header().setHighlightSections(False)
        self.lista_de_itens.header().setMinimumSectionSize(35)
        self.lista_de_itens.header().setSortIndicatorShown(False)
        self.lista_de_itens.header().setStretchLastSection(False)

        self.box_item = QtWidgets.QLineEdit(Dialog)
        self.box_item.setGeometry(QtCore.QRect(10, 210, 321, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(14)
        self.box_item.setFont(font)
        self.box_item.setPlaceholderText("Item")
        self.box_item.setObjectName("box_item")

        self.box_unidades = QtWidgets.QLineEdit(Dialog)
        self.box_unidades.setGeometry(QtCore.QRect(10, 250, 151, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(14)
        self.box_unidades.setFont(font)
        self.box_unidades.setPlaceholderText("Unidades")
        self.box_unidades.setObjectName("box_unidades")

        self.box_valor = QtWidgets.QLineEdit(Dialog)
        self.box_valor.setGeometry(QtCore.QRect(180, 250, 151, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(14)
        self.box_valor.setFont(font)
        self.box_valor.setPlaceholderText("Valor")
        self.box_valor.setObjectName("box_valor")

        self.botao_carregar = QtWidgets.QPushButton(Dialog)
        self.botao_carregar.setGeometry(QtCore.QRect(121, 290, 111, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(16)
        self.botao_carregar.setFont(font)
        self.botao_carregar.setText("Carregar")
        self.botao_carregar.setObjectName("botao_carregar")

        self.botao_carregar.clicked.connect(self.botao_carregar_clicked)

        self.botao_adicionar = QtWidgets.QPushButton(Dialog)
        self.botao_adicionar.setGeometry(QtCore.QRect(11, 290, 101, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(16)
        self.botao_adicionar.setFont(font)
        self.botao_adicionar.setText("Adicionar")
        self.botao_adicionar.setObjectName("botao_adicionar")

        self.botao_adicionar.clicked.connect(self.botao_adicionar_clicked)

        self.botao_remover = QtWidgets.QPushButton(Dialog)
        self.botao_remover.setGeometry(QtCore.QRect(240, 290, 91, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(16)
        self.botao_remover.setFont(font)
        self.botao_remover.setText("Remover")
        self.botao_remover.setObjectName("botao_remover")

        self.botao_remover.clicked.connect(self.botao_remover_clicked)

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

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.lista_de_itens.setSortingEnabled(False)
        self.lista_de_itens.headerItem().setText(0, _translate("Dialog", "Item"))
        self.lista_de_itens.headerItem().setText(1, _translate("Dialog", "Unidades"))
        self.lista_de_itens.headerItem().setText(2, _translate("Dialog", "Valor"))
        __sortingEnabled = self.lista_de_itens.isSortingEnabled()
        self.lista_de_itens.setSortingEnabled(False)
        self.lista_de_itens.topLevelItem(0).setText(0, _translate("Dialog", "Test"))
        self.lista_de_itens.topLevelItem(0).setText(1, _translate("Dialog", "1000"))
        self.lista_de_itens.topLevelItem(0).setText(2, _translate("Dialog", "2,99"))
        self.lista_de_itens.setSortingEnabled(__sortingEnabled)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Dialog = QtWidgets.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())

JSON that at least load and can be added stuff:

{
    "database": [
        {
            "num": "0",
            "item": "Test2",
            "unidades": "200",
            "valor": "2,99"
        },
        {
            "num": "1",
            "item": "Test3",
            "unidades": "31",
            "valor": "5,99"
        }
    ]
}

JSON that doesn't work:

{
    "database": [
        {
            "num": "0",
            "item": "Test2",
            "unidades": "200",
            "valor": "2,99"
        },
        {
            "num": "1",
            "item": "Test3",
            "unidades": "31",
            "valor": "5,99"
        },
        {
            "num": "2",
            "item": "Test4",
            "unidades": "31",
            "valor": "5,99"
        }
    ]
}

Thanks in advance for any help!

Your main problem is that you are trying to access an item that does not exist so QTreeWidget will return None causing the error you have. In the first link you must order, Qt Designer does not provide a widget but a class that fills a widget so I recommend you create another class that inherits from a widget and use the previous class to fill.

Going to the problem, among the tasks you indicate you will always have to fill in the items from a file and vice versa, so it is better to create 2 methods that do it. On the other hand I created a custom QTreeWidgetItem that supports the 4 items, and so add them or remove it, with this I have been able to implement the functions of loading and saving. But the task of removing is confusing because I do not understand how you identify which row you want to eliminate, so I have proposed a new methodology: the selected row will be deleted, for this you must click on the row and then the button.

from PyQt5 import QtCore, QtGui, QtWidgets
import json


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(339, 329)
        Dialog.setSizeGripEnabled(False)
        self.lista_de_itens = QtWidgets.QTreeWidget(Dialog)
        self.lista_de_itens.setGeometry(QtCore.QRect(10, 10, 321, 191))
        self.lista_de_itens.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.lista_de_itens.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.lista_de_itens.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
        self.lista_de_itens.setAutoScroll(True)
        self.lista_de_itens.setIndentation(1)
        self.lista_de_itens.setRootIsDecorated(False)
        self.lista_de_itens.setUniformRowHeights(True)
        self.lista_de_itens.setItemsExpandable(False)
        self.lista_de_itens.setAnimated(False)
        self.lista_de_itens.setWordWrap(True)
        self.lista_de_itens.setExpandsOnDoubleClick(False)
        self.lista_de_itens.setObjectName("lista_de_itens")

        self.lista_de_itens.header().setVisible(True)
        self.lista_de_itens.header().setCascadingSectionResizes(False)
        self.lista_de_itens.header().setDefaultSectionSize(94)
        self.lista_de_itens.header().setHighlightSections(False)
        self.lista_de_itens.header().setMinimumSectionSize(35)
        self.lista_de_itens.header().setSortIndicatorShown(False)
        self.lista_de_itens.header().setStretchLastSection(False)

        self.box_item = QtWidgets.QLineEdit(Dialog)
        self.box_item.setGeometry(QtCore.QRect(10, 210, 321, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(14)
        self.box_item.setFont(font)
        self.box_item.setPlaceholderText("Item")
        self.box_item.setObjectName("box_item")

        self.box_unidades = QtWidgets.QLineEdit(Dialog)
        self.box_unidades.setGeometry(QtCore.QRect(10, 250, 151, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(14)
        self.box_unidades.setFont(font)
        self.box_unidades.setPlaceholderText("Unidades")
        self.box_unidades.setObjectName("box_unidades")

        self.box_valor = QtWidgets.QLineEdit(Dialog)
        self.box_valor.setGeometry(QtCore.QRect(180, 250, 151, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(14)
        self.box_valor.setFont(font)
        self.box_valor.setPlaceholderText("Valor")
        self.box_valor.setObjectName("box_valor")

        self.botao_carregar = QtWidgets.QPushButton(Dialog)
        self.botao_carregar.setGeometry(QtCore.QRect(121, 290, 111, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(16)
        self.botao_carregar.setFont(font)
        self.botao_carregar.setObjectName("botao_carregar")

        self.botao_adicionar = QtWidgets.QPushButton(Dialog)
        self.botao_adicionar.setGeometry(QtCore.QRect(11, 290, 101, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(16)
        self.botao_adicionar.setFont(font)
        self.botao_adicionar.setObjectName("botao_adicionar")

        self.botao_remover = QtWidgets.QPushButton(Dialog)
        self.botao_remover.setGeometry(QtCore.QRect(240, 290, 91, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(16)
        self.botao_remover.setFont(font)
        self.botao_remover.setObjectName("botao_remover")
        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.lista_de_itens.setSortingEnabled(False)
        self.lista_de_itens.headerItem().setText(0, _translate("Dialog", "Item"))
        self.lista_de_itens.headerItem().setText(1, _translate("Dialog", "Unidades"))
        self.lista_de_itens.headerItem().setText(2, _translate("Dialog", "Valor"))
        __sortingEnabled = self.lista_de_itens.isSortingEnabled()
        self.lista_de_itens.setSortingEnabled(False)
        self.lista_de_itens.setSortingEnabled(__sortingEnabled)
        self.botao_carregar.setText(_translate("Dialog", "Carregar"))
        self.botao_adicionar.setText(_translate("Dialog", "Adicionar"))
        self.botao_remover.setText(_translate("Dialog", "Remover"))


class TreeWidgetItem(QtWidgets.QTreeWidgetItem):
    def __init__(self, num, item, unidades, valor):
        super(TreeWidgetItem, self).__init__([item, unidades, valor])
        self._num = num


class Dialog(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self.setupUi(self)
        self.botao_carregar.clicked.connect(self.botao_carregar_clicked)
        self.botao_adicionar.clicked.connect(self.botao_adicionar_clicked)
        self.botao_remover.clicked.connect(self.botao_remover_clicked)

    @QtCore.pyqtSlot()
    def botao_carregar_clicked(self):
        # remove all items
        self.lista_de_itens.clear()
        # load new items from file
        self.carregar_itens_do_arquivo()

    @QtCore.pyqtSlot()
    def botao_adicionar_clicked(self):
        item_input = self.box_item.text()
        valor_input = self.box_valor.text()
        unidades_input = self.box_unidades.text()
        if not item_input or not valor_input or not unidades_input:
            print("empty fields")
            return
        num_input = max([self.lista_de_itens.topLevelItem(i)._num for i in range(self.lista_de_itens.topLevelItemCount())] + [-1])+1
        it = TreeWidgetItem(num_input, item_input, valor_input, unidades_input)
        self.lista_de_itens.addTopLevelItem(it)
        self.salvar_itens_em_um_arquivo()
        self.box_item.clear()
        self.box_valor.clear()
        self.box_unidades.clear()

    @QtCore.pyqtSlot()
    def botao_remover_clicked(self):
        for it in reversed(self.lista_de_itens.selectedItems()):
            i = self.lista_de_itens.indexOfTopLevelItem(it)
            it_ = self.lista_de_itens.takeTopLevelItem(i)
            del it_
        self.salvar_itens_em_um_arquivo()

    def carregar_itens_do_arquivo(self):
        with open('data.json', 'r') as file:
            data = json.load(file)
            for e in data['database']:
                it = TreeWidgetItem(int(e["num"]), e["item"], e["unidades"], e["valor"])
                self.lista_de_itens.addTopLevelItem(it)

    def salvar_itens_em_um_arquivo(self):
        data = { "database": [] }
        for i in range(self.lista_de_itens.topLevelItemCount()):
            it = self.lista_de_itens.topLevelItem(i)
            row = {"num": str(it._num), "item" : it.text(0), "unidades": it.text(1), "valor": it.text(2)}
            data["database"].append(row)

        with open('data.json', 'w') as file:
            json.dump(data, file, indent=4)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Dialog()
    w.show()
    sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM