Интеграция QML, SQL и PySide: свойство ошибки send_message объекта SqlConversationModel (0x5561c01509c0) не является функцией - PullRequest
0 голосов
/ 09 июля 2020

Здравствуйте, я следую по этой ссылке QML, SQL и интеграция PySide

Я получаю эту ошибку при нажатии кнопки «Отправить»:

TypeError: Property 'send_message' of object SqlConversationModel(0x564692696f40) is not a function

это мой main.py:

import logging

from PySide2.QtCore import QDir, QFile, QUrl
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtSql import QSqlDatabase

from t2_SqlQmlPython.python.sqlDialog import SqlConversationModel

UI = "../ui/chat.qml"
logging.basicConfig(filename="chat.log", level=logging.DEBUG)
logger = logging.getLogger("logger")

def connectToDatabase():
    database = QSqlDatabase.database()
    if not database.isValid():
        database = QSqlDatabase.addDatabase("QSQLITE")
        if not database.isValid():
            logger.error("Cannot add database")

    write_dir = QDir()
    if not write_dir.mkpath("."):
        logger.error("Failed to create writable directory")

    # Ensure that we have a writable location on all devices.
    filename = "{}/chat-database.sqlite3".format(write_dir.absolutePath())

    # When using the SQLite driver, open() will create the SQLite
    # database if it doesn't exist.
    database.setDatabaseName(filename)
    if not database.open():
        logger.error("Cannot open database")
        QFile.remove(filename)

if __name__ == "__main__":
    app = QGuiApplication()
    connectToDatabase()
    sql_conversation_model = SqlConversationModel()

    engine = QQmlApplicationEngine()
    # Export pertinent objects to QML
    engine.rootContext().setContextProperty("chat_model", sql_conversation_model)
    engine.load(QUrl(UI))

    app.exec_()

, и это мой sqlDialog.py:

import datetime
import logging

from PySide2.QtCore import Qt, Slot
from PySide2.QtSql import QSqlDatabase, QSqlQuery, QSqlRecord, QSqlTableModel

table_name = "Conversations"


def createTable():
    if table_name in QSqlDatabase.database().tables():
        return

    query = QSqlQuery()
    if not query.exec_(
            """
            CREATE TABLE IF NOT EXISTS 'Conversations' (
                'author' TEXT NOT NULL,
                'recipient' TEXT NOT NULL,
                'timestamp' TEXT NOT NULL,
                'message' TEXT NOT NULL,
            FOREIGN KEY('author') REFERENCES Contacts ( name ),
            FOREIGN KEY('recipient') REFERENCES Contacts ( name )
            )
            """
    ):
        logging.error("Failed to query database")

    # This adds the first message from the Bot
    # and further development is required to make it interactive.
    query.exec_(
        """
        INSERT INTO Conversations VALUES(
            'machine', 'Me', '2019-01-07T14:36:06', 'Hello!'
        )
        """
    )
    logging.info(query)


class SqlConversationModel(QSqlTableModel):

    def __init__(self, parent=None):
        super(SqlConversationModel, self).__init__(parent)

        createTable()
        self.setTable(table_name)
        self.setSort(2, Qt.DescendingOrder)
        self.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.recipient = ""

        self.select()
        logging.debug("Table was loaded successfully.")

    def get_print_tb(self):
        logging.debug("mohsen is checking")

    def setRecipient(self, recipient):
        if recipient == self.recipient:
            pass

        self.recipient = recipient

        filter_str = (
            "(recipient = '{}' AND author = 'Me') OR " "(recipient = 'Me' AND author='{}')"
        ).format(self.recipient)
        self.setFilter(filter_str)
        self.select()

    def data(self, index, role):
        if role < Qt.UserRole:
            return QSqlTableModel.data(self, index, role)

        sql_record = QSqlRecord()
        sql_record = self.record(index.row())

        return sql_record.value(role - Qt.UserRole)

    def roleNames(self):
        """Converts dict to hash because that's the result expected
        by QSqlTableModel"""
        names = {}
        author = "author".encode()
        recipient = "recipient".encode()
        timestamp = "timestamp".encode()
        message = "message".encode()

        names[hash(Qt.UserRole)] = author
        names[hash(Qt.UserRole + 1)] = recipient
        names[hash(Qt.UserRole + 2)] = timestamp
        names[hash(Qt.UserRole + 3)] = message

        return names

    def send_message(self, recipient, message, author):
        timestamp = datetime.datetime.now()

        new_record = self.record()
        new_record.setValue("author", author)
        new_record.setValue("recipient", recipient)
        new_record.setValue("timestamp", str(timestamp))
        new_record.setValue("message", message)

        logging.debug('Message: "{}" \n Received by: "{}"'.format(message, recipient))

        if not self.insertRecord(self.rowCount(), new_record):
            logging.error("Failed to send message: {}".format(self.lastError().text()))
            return

        self.submitAll()
        self.select()

и chat.qml:

import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12

ApplicationWindow {
    id: window
    title: qsTr("Chat")
    width: 640
    height: 960
    visible: true
    ColumnLayout {
        anchors.fill: parent

        ListView {

            id: listView
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.margins: pane.leftPadding + messageField.leftPadding
            displayMarginBeginning: 40
            displayMarginEnd: 40
            verticalLayoutDirection: ListView.BottomToTop
            spacing: 12
            model: chat_model
            delegate: Column {
                readonly property bool sentByMe: model.recipient !== "Me"
                anchors.right: sentByMe ? parent.right : undefined
                spacing: 6

                Row {
                    id: messageRow
                    spacing: 6
                    anchors.right: sentByMe ? parent.right : undefined

                    Rectangle {
                        width: Math.min(messageText.implicitWidth + 24, listView.width - messageRow.spacing)
                        height: messageText.implicitHeight + 24
                        radius: 15
                        color: sentByMe ? "lightgrey" : "#ff627c"

                        Label {
                            id: messageText
                            text: model.message
                            color: sentByMe ? "black" : "white"
                            anchors.fill: parent
                            anchors.margins: 12
                            wrapMode: Label.Wrap
                        }
                    }
                }

                Label {
                    id: timestampText
                    text: Qt.formatDateTime(model.timestamp, "d MMM hh:mm")
                    color: "lightgrey"
                    anchors.right: sentByMe ? parent.right : undefined
                }
            }

            ScrollBar.vertical: ScrollBar {}
        }
        Pane {
            id: pane
            Layout.fillWidth: true

            RowLayout {
                width: parent.width

                TextArea {
                    id: messageField
                    Layout.fillWidth: true
                    placeholderText: qsTr("Compose message")
                    wrapMode: TextArea.Wrap
                }

                Button {
                    id: sendButton
                    text: qsTr("Send")
                    enabled: messageField.length > 0
                    onClicked: {
                        chat_model.send_message("machine", messageField.text, "me");

                        messageField.text = "";

                    }
                }
            }
        }
    }

}

и это put is:

TypeError: Property 'send_message' of object SqlConversationModel(0x564692696f40) is not a function

Я перешел по этой ссылке class-visible-to-qml-error-in-fashion-typeerror-property-of-object-is , но я не мог это понять out.

Что я делаю не так?

1 Ответ

0 голосов
/ 09 июля 2020

поэтому я узнал, что в их коде есть ошибка, а правильный код для метода send_message -

    @Slot(str,str,str)
    def send_message(self, recipient, message, author):
        timestamp = datetime.datetime.now()

        new_record = self.record()
        new_record.setValue("author", author)
        new_record.setValue("recipient", recipient)
        new_record.setValue("timestamp", str(timestamp))
        new_record.setValue("message", message)

        logging.debug('Message: "{}" \n Received by: "{}"'.format(message, recipient))

        if not self.insertRecord(self.rowCount(), new_record):
            logging.error("Failed to send message: {}".format(self.lastError().text()))
            return

        self.submitAll()
        self.select()
...