Qml实现文本框显示文本,可指定某行高亮

功能描述

读取文本后进行显示,Qt中提供了QTextBrowser等控件可以用于显示文本内容;但是指定某一行文本高亮的功能,没有找到相应的方法。本人利用Qml实现了一个能够指定某行文本高亮的功能,但存在部分限制,还需完善。

效果

在这里插入图片描述
这里采用的是定时器,每隔1s更改行数号,自动递增。

环境

Ubuntu16.04+Qt5.7.1

功能分割

  • 文件打开与读取部分由C++实现——class OpenFile;为Qml显示提供文本数据等;
  • 显示部分由Qml实现——main.qml;

实现

这里使用了Qml中的ListView来进行显示,并写一个Component用于显示高亮,而指定某行高亮则使用index行号进行高亮显示。

class OpenFile

OpenFile.h文件中提供了如下的接口:

#ifndef OPENFILE_H
#define OPENFILE_H

#include <QObject>
#include <QFile>
#include <QApplication>
#include <QTimer>
#include <QUrl>

class OpenFile : public QObject
{
    Q_OBJECT
public:
    explicit OpenFile(QObject *parent = 0);
    ~OpenFile();

    Q_INVOKABLE QStringList getFileTextList(QVariant filePath);
    Q_INVOKABLE void start();//启动定时器,用于模拟行号改变

signals:
    void lineIndexOutput(int index);

public slots:
    void onTimeOut();

private:
    QStringList m_fileContentList;
    QTimer m_timer;
    int    m_lineIndex;
};

#endif // OPENFILE_H

OpenFile.cpp文件如下:

#include "OpenFile.h"

OpenFile::OpenFile(QObject *parent) : QObject(parent)
{
    m_timer.setInterval(1000);
    m_lineIndex = 0;
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
}

OpenFile::~OpenFile()
{

}

QStringList OpenFile::getFileTextList(QVariant filePath)
{
    //由于Qml中获取到的文件路径是Url类型,所以使用QVariant进行转化
    QFile file(filePath.toUrl().toLocalFile());
    QString fileContent = "";

    /* open failed */
    if (! file.open(QIODevice::ReadOnly|QIODevice::Text)) {
        return m_fileContentList;
    }

    fileContent = file.readAll();

    m_fileContentList = fileContent.split("\n");
    return m_fileContentList;
}

void OpenFile::start()
{
    m_timer.start();
}

void OpenFile::onTimeOut()
{
    emit lineIndexOutput(m_lineIndex);
    m_lineIndex++;
}

main.qml

qml文件如下:

import QtQuick 2.5
import QtQuick.Controls 1.4
import MyModel 1.0
import QtQuick.Dialogs 1.2

Rectangle {
    id: root
    width: 320
    height: 480
    color: "lightGray"

    OpenFile {
        id: openFile
    }

    MyTextBrowser {
        id: textBrowser
        width: parent.width
        height: parent.height - 40
    }

    Connections {
        target: openFile
        onLineIndexOutput: {
            textBrowser.lineIndex = index
        }
    }

    FileDialog {
        id: fileSelectDialog
        nameFilters: ["Text files (*.txt *.c *.h *.cpp *.qml)", "All files (*)"]

        onAccepted: {
            textBrowser.model = openFile.getFileTextList(fileSelectDialog.fileUrl)
            openFile.start()
        }
    }

    Button {
        id: openFileBtn
        anchors.top: textBrowser.bottom
        anchors.horizontalCenter: textBrowser.horizontalCenter
        anchors.topMargin: 5
        text: "OpenFile"

        onClicked: {
            fileSelectDialog.open()
        }
    }
}

MyTextBrowser.qml

自定义的文本显示控件内容如下:

import QtQuick 2.0
import QtQuick.Controls 1.4

Item {
    id: root

    property int lineIndex: 0
//    property variant model
    property alias model: textView.model

    width: parent.width
    height: parent.height

    ScrollView {
        width: parent.width
        height: parent.height
        ListView {
            id: textView
            width: parent.width - 20
            currentIndex: lineIndex
            delegate: delegateItem
            highlight: highlightComponent
            focus: true
        }
    }

    Component {
        id: delegateItem
        Item {
            width: textView.width
            height: 65

            Text {
                //此处存疑,不明白modelData是什么意思,为什么必须这样写?
                text: modelData

                width: parent.width
                height: parent.height
                wrapMode: Text.WrapAnywhere
                font.pixelSize: 14
            }
        }
    }

    Component {
        id: highlightComponent
        Rectangle {
            color: "lightblue"
            radius: 5
        }
    }
}

过程中遇到的问题

  1. 一开始不知道用什么组件来实现这样的效果,后面是想到Listview有每一行的分割以及自定义高亮的功能,因此耍了一个小聪明用Listview来实现;
  2. 在打开文件对话框中,使用了QML的FileDialog,FileDialog选中返回的文件路径时是以Url/Urls类型返回的,因此我将OpenFile中getFileTextList的参数处理为QVariant类型,通过QVariant->toUrl->toLocalFile得到本地的绝对文件路径;
  3. 在上面MyTextBrowser.qml中,Text此处的text:modelData,modelData是QML中某种内部变量吗?这里不明白为什么这样写(我这样写是因为参考了其他代码这样处理字符串进行显示)。希望大神不吝赐教。
    Component {
        id: delegateItem
        Item {
            width: textView.width
            height: 65

            Text {
                //此处存疑,不明白modelData是什么意思,为什么必须这样写?
                text: modelData

                width: parent.width
                height: parent.height
                wrapMode: Text.WrapAnywhere
                font.pixelSize: 14
            }
        }
    }

问题与不足

  1. 从上面的gif图可以看出,当高亮达到最下面时,高亮行没有居中显示;
  2. 每一行的显示受限制,比如当每一行的文本很长时,需要修改Listview中每一行的高度或宽度,否则会造成文本显示重叠;

代码下载链接

https://download.csdn.net/download/zefinng/10964833

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值