首页 文章

Textarea记录速度慢

提问于
浏览
2

我有一个Qt应用程序,我想显示一些日志 . 我用 TextArea . 但是,如果日志很大或事件过快,GUI就无法足够快地绘制 Textarea .

我用Qt Creator(QML Profiler)分析了这个问题,如果日志很大,绘制GUI需要300毫秒 . 我在Raspberry Pi2上使用这个软件 .

任何想法如何解决这个问题?我应该使用其他QML控件吗?谢谢 .

QML代码:

TextArea {
    text: appHandler.rawCommunication
    readOnly: true        
}

C代码:

Q_PROPERTY(QString rawCommunication READ rawCommunication WRITE setrawCommunication NOTIFY rawCommunicationChanged)

void setrawCommunication(QString val)
{
    val.append("\n");
    val.append(m_rawCommunication);
    m_rawCommunication = val;
    emit rawCommunicationChanged(m_rawCommunication);
}

4 回答

  • 3

    使用view,如ListView . 它们instantiate their delegates as needed,基于视图所说的需要显示的数据,具体取决于用户在列表中的位置 . 这意味着它们在显示大量数据方面的表现要比 TextArea 这样的项目更好,在你的情况下,它会在内存中保留一个巨大的,不断增长的字符串 .

    你的delegate可能是 TextArea ,所以你需要造型,我建议你选择更轻松的东西,比如TextEdit . 更进一步:如果您不需要可编辑的文本,请使用普通的旧版本 Text . 切换到这些可能没什么区别,但如果你值得一试 .

  • 0

    尝试这种方法:创建一个c logger类将所有日志附加到此类并使用某些操作打印它们,例如单击按钮这将解决您的性能问题

    代码示例:

    Logger.h

    #ifndef LOGGER_H
    #define LOGGER_H
    
    #include <QQmlContext>
    #include <QObject>
    #include <QStringList>
    #include <QQmlEngine>
    #include <QString>
    #include <QtCore>
    #include <QDebug>
    
    class Logger : public QObject
    {
        Q_OBJECT
    public:
        explicit Logger(QObject *parent = 0);
        ~Logger();
        Q_INVOKABLE QStringList *getLogStream();
        Q_INVOKABLE void printLogStream();
        Q_INVOKABLE void appendLog(QString log);
        Q_INVOKABLE void log(QString log="");
        Q_INVOKABLE void log(QString fileName, QString log);
    signals:
    
    public slots:
    
    private:
         QStringList* stringStream_;
    };
    
    #endif // LOGGER_H
    

    Logger.cpp

    #include "logger.h"
    
        Logger::Logger(QObject *parent) :
            QObject(parent),
            stringStream_(new QStringList)
        {
        }
    
         ~Logger(){
                    if(stringStream_ != NULL)
                    {
                        delete stringStream_;
                        stringStream_ = NULL;
                     }
                  }
        QStringList* Logger::getLogStream(){
            return stringStream_;
        }
    
        void Logger::printLogStream()
        {
            QStringListIterator itr(*stringStream_);
                while (itr.hasNext())
        qDebug()<< itr.next()<<"\n";
        }
    
         void Logger::appendLog(QString log){
             stringStream_->push_back(log) ;
        }
    void Logger::log(QString fileName,QString log)
    {
    
    #ifdef ENABLElogs
    
        fileName.push_front(" [");
        if(!fileName.contains(".qml"))
        {
            fileName.append(".qml]:");
        }
        qDebug()<<fileName<<log;
    #else
        Q_UNUSED(log);
        Q_UNUSED(fileName);
    #endif
    }
    void Logger::log(QString log)
    {
    
    #ifdef ENABLElogs
        qDebug()<<log;
    #else
        Q_UNUSED(log);
    #endif
    }
    

    main.cpp

    #include <QtGui/QGuiApplication>
    #include "qtquick2applicationviewer.h"
    #include "logger.h"
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QtQuick2ApplicationViewer *viewer = new QtQuick2ApplicationViewer;
        Logger* stream = new Logger;
        viewer->rootContext()->setContextProperty("Stream",stream);
        viewer->setMainQmlFile(QStringLiteral("qml/project/main.qml"));
        viewer->showExpanded();
    
    
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.0
    import QtQuick.Controls 1.1
    
    Rectangle {
        width: 800
        height: 480
        Text {
            text: qsTr("Hello World")
            anchors.centerIn: parent
            Component.onCompleted: Stream.appendLog("Text object is completed")
        }
        Column{
            x:300
        Button{
            text:"append"
            onClicked: {
                Stream.appendLog("MouseArea object clicked")
            }
            Component.onCompleted: Stream.appendLog("Button object is completed")
        }
        Button{
            text:"logger"
            onClicked: {
             Stream.printLogStream()
            }
            Component.onCompleted: Stream.appendLog("Button logger object is completed")
        }
    }
    
    
        TextArea{
            text:"blablabla"
            Component.onCompleted: Stream.appendLog("TextArea object is completed")
        }
        Component.onCompleted: Stream.appendLog("the main object is completed")
    }
    

    project.pro

    #add this line
        # comment it, run qmake and recompile to disable logs
        DEFINES += ENABLElogs
    

    使用此approch,当您想释放软件时,可以通过单行更改来停止所有日志

  • 0

    但是,我已经包含了完整的代码,使用“QAbstractListModel”将日志记录重量数据发送到QML

    listmodel.h

    #ifndef LISTMODEL_H
    #define LISTMODEL_H
    #include <QAbstractListModel>
    
    class ListModel: public QAbstractListModel
    {
        Q_OBJECT
    public:
        ListModel();
    
       // Q_PROPERTY(QStringList logs READ name WRITE  nameChanged)
        int rowCount(const QModelIndex & parent = QModelIndex()) const;
        QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
        Q_INVOKABLE QVariant activate(int i);
    
    private:
        QStringList m_list;
    };
    
    #endif // LISTMODEL_H
    

    listmodel.cpp

    #include "listmodel.h"
    #include <QFile>
    #include <QHash>
    
    
    ListModel::ListModel()
    {
        QFile file("/home/ashif/LogFile");
        if(!file.open(QIODevice::ReadOnly))
        {
            qDebug( "Log file open failed" );
        }
        bool isContinue = true;
        do
        {
            if(file.atEnd())
            {
                isContinue = false;
            }
             m_list.append(file.readLine());
        }
        while( isContinue);
    }
    
    int ListModel::rowCount(const QModelIndex & parent ) const
    {
    
        return m_list.count();
    }
    QVariant ListModel::data(const QModelIndex & index, int role ) const
    {
        if(!index.isValid()) {
               return QVariant("temp");
           }
        return m_list.value(index.row());
    }
    

    main.qml

    import QtQuick 2.3
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    
    Window {
        visible: true
    
        ListView
        {
            width: 200; height: 250
            anchors.centerIn: parent
            model:mylistModel
            delegate: Text
            {
                text:mylistModel.activate(index)
            }
        }
    }
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlContext>
    #include <QQmlApplicationEngine>
    #include "logger.h"
    #include "listmodel.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        Logger myLogger;
        ListModel listModel;    
        engine.rootContext()->setContextProperty("listModel", &listModel);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        return app.exec();
    }
    
  • 0

    我尝试了 ListView 的建议,但它有几个缺点:

    • 添加新输出时,没有简单的方法可以将视图保持在底部

    • 没有跨行/代表的选择

    所以我最终使用了缓存的 TextArea ,每秒更新一次:

    TextArea {
                id: outputArea_text
                wrapMode: TextArea.Wrap
                readOnly: true
                font.family: "Ubuntu Mono, times"
    
                function appendText(text){
                    logCache += text + "\n";
                    update_timer.start();
                }
    
                property string logCache: ""
    
                Timer {
                    id: update_timer
                    // Update every second
                    interval: 1000
                    running: false
                    repeat: false
                    onTriggered: {
                        outputArea_text.append(outputArea_text.logCache);
                        outputArea_text.logCache = "";
                    }
                }
    
                Component.onCompleted: {
                    my_signal.connect(outputArea_text.appendText)
                }
            }
    

相关问题