Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Integrating QML and C++ problem



  • I do as described in the tutorial: https://doc.qt.io/qt-5/qtqml-cppintegration-topic.html

    I am writing a simple logger transmitting messages from within the program to the text area of the application.:
    .h

    #ifndef LOGGER_H
    #define LOGGER_H
    
    #include <QObject>
    
    class Logger : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
    
    public:
        explicit Logger(QObject *parent = nullptr);
    
    signals:
        void messageChanged();
    
    public:
        QString message() const;
        Logger& operator << (QString value);
        void setMessage(const QString& value);
    
    private:
        QString log_message;
    };
    
    #endif // LOGGER_H
    

    .cpp

    #include "include/logger.h"
    
    Logger::Logger(QObject *parent) : QObject(parent)
    {
    }
    
    QString Logger::message() const
    {
        return log_message;
    }
    
    Logger& Logger::operator << (QString value)
    {
        setMessage(value);
    
        return *this;
    }
    
    void Logger::setMessage(const QString& value)
    {
        if (log_message != value) {
            log_message = value;
    
            emit messageChanged();
        }
    }
    
    

    main.cpp

    qmlRegisterType<Logger>("edu.logger", 0, 1, "Logger");
    

    And trying to get the value in the form.

    Logger {
         id: log;
         onMessageChanged: logWidget.append(log.message)  <------- This does not work
    }
    
    TextArea {
         id: logWidget
         placeholderText: qsTr("Clear log")
         text: log.message        <------- It works
    }             
    

    For some reason, onMessageChanged event does not occur. There are no error messages, variables are changing.


  • Moderators

    @Alexey-Moiseev said in Integrating QML and C++ problem:

    text: log.getLastMessage <------- It works

    How? There is no getLastMessage property in your Logger class!

    How do you call your setMessage() method or modify message property?



  • @sierdzio Sorry, too many versions of the same I wrote too. Mixed when inserted. Fixed the code in the initial post. Existing functions are called.
    I call setMessage from an overloaded operator "<<", where setMessage changes the variable. If you display the values through qDebug, then you can see that the values come and change. But the signal does not call. As I pointed out in the code, when log.message is called separately, it works. But the onMessageChanged event does not occur.


  • Moderators

    That's weird. I can think of only 3 explanations:

    • you're trying to log the same message, so if (log_message != value) { condition is not met, and signal is not emitted (BTW. it's quite bizarre to have a logger which prevents the same message from being logged twice!)
    • TextArea.append() somehow does not work... but that's unlikely. Or maybe text is added below your viewport? append() adds a newline so you might miss it if your UI is small
    • log.message does not return correct value when invoked in a slot... but that's unlikely

    One possible solution: pass message as argument in messageChanged(const QString &msg) signal, then use it in slot onMessageChanged: logWidget.append(msg).



  • Why did the question get downvoted? This isn't SO.



  • @sierdzio

    1. That was the first thing I checked.
    2. The text is inserted where necessary, it works:
    TextArea {
         text: log.message
    }
    
    1. log.message returns the correct value, because № 2.
    2. This solution was the second that I tried.

  • Moderators

    @Alexey-Moiseev

    can you check the following? Maybe append is the issue here.

    Logger {
    id: log;
    onMessageChanged: logWidget.append(log.message) <------- This does not work
    onMessageChanged: logWidget.text = log.message <------- Does this work ?
    }



  • @J-Hilk No. Like any other action written in onMessageChanged. For some reason, onMessageChanged is not called. I also can’t check the emit function call, because it's void.


  • Moderators

    @Alexey-Moiseev and when you simply print something to the console ?

    onMessageChanged:console.log("onMessageChanged", log.message)
    

Log in to reply