使用 QtQuick.Controls 1.12 将 Qt TextTable 与 TextArea 一起使用时,文本会错位

Posted

技术标签:

【中文标题】使用 QtQuick.Controls 1.12 将 Qt TextTable 与 TextArea 一起使用时,文本会错位【英文标题】:Text gets missaligned when using Qt TextTable with TextArea using QtQuick.Controls 1.12 【发布时间】:2020-08-14 08:38:52 【问题描述】:

我在 Qml 中使用 TextArea 时遇到问题。 C++ 模型包含对该 TextArea 的引用。 当我在 C++ 模型中插入 QTextTable 时,一切都很好,直到用户输入一些文本。在用户手动编辑一些单元格并在其中写入一些文本后,一切都会变得一团糟。有人知道如何解决吗?

我还有其他功能运行良好。所以我猜c++模型和textarea的连接应该没有错。

这里是 Documenthandler.h

#include <QQuickTextDocument>

#include <QtGui/QTextCharFormat>
#include <QtCore/QTextCodec>

#include <qqmlfile.h>

QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE

class DocumentHandler : public QObject

    Q_OBJECT

    Q_ENUMS(HAlignment)

    Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)

public:
    DocumentHandler();

    Q_INVOKABLE void createTable(int columns ,int rows);

    QQuickItem *target()  return m_target; 

    void setTarget(QQuickItem *target);

    QString text() const;


public Q_SLOTS:

    void setText(const QString &arg);


Q_SIGNALS:
    void targetChanged();

    void textChanged();
    void error(QString message);

private:
    QTextCursor textCursor() const;

    QQuickItem *m_target;
    QTextDocument *m_doc;

    QString m_text;
;

这里是documenthandler.cpp 在“createTable”函数中,我创建了表

#include "documenthandler.h"

#include <QtGui/QTextDocument>
#include <QtGui/QTextList>
#include <QtGui/QTextTable>
#include <QtGui/QTextCursor>
#include <QtGui/QFontDatabase>
#include <QtCore/QFileInfo>

DocumentHandler::DocumentHandler()
    : m_target(0)
    , m_doc(0)



void DocumentHandler::setTarget(QQuickItem *target)

    m_doc = 0;
    m_target = target;
    if (!m_target)
        return;

    QVariant doc = m_target->property("textDocument");
    if (doc.canConvert<QQuickTextDocument*>()) 
        QQuickTextDocument *qqdoc = doc.value<QQuickTextDocument*>();
        if (qqdoc)
            m_doc = qqdoc->textDocument();
    
    emit targetChanged();


void DocumentHandler::setText(const QString &arg)

    if (m_text != arg) 
        m_text = arg;
        emit textChanged();
    


QString DocumentHandler::text() const

    return m_text;


QTextCursor DocumentHandler::textCursor() const

    if (!m_doc)
        return QTextCursor();

    QTextCursor cursor = QTextCursor(m_doc);

    return cursor;


void DocumentHandler::createTable(int columns , int rows)

    QTextCursor cursor = textCursor();
    if (cursor.isNull())
        return;

    cursor.insertTable(rows,columns);



这里是主要的qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 1.6
import DocumentHandler 1.0

Window 
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Button
    
        id:btn
        text:"test"
        onClicked: document.createTable(5,5);
    


    TextArea 
        Accessible.name: "document"
        id: tooltip_area

        selectByMouse: true

        anchors.left:parent.left
        anchors.right:parent.right
        anchors.top: btn.bottom
        anchors.bottom: parent.bottom

        baseUrl: "qrc:/"
        text: document.text
        textFormat: Qt.RichText
        wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
        Component.onCompleted: forceActiveFocus()
           
    DocumentHandler
        id: document
        target: tooltip_area



    



这里是main函数,没有什么特别的,只是我注册了QML Type

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "documenthandler.h"

int main(int argc, char *argv[])

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    qmlRegisterType<DocumentHandler>("DocumentHandler",1,0,"DocumentHandler");
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) 
                         if (!obj && url == objUrl)
                             QCoreApplication::exit(-1);
                     , Qt::QueuedConnection);
    engine.load(url);

    return app.exec();

这是填满一些单元格后的样子

【问题讨论】:

请提供minimal reproducible example 现在您的代码示例不完整。 @folibis 我更改了描述并添加了一个最小的可重现示例 我还是不明白你是如何用数据填充表格的,但我猜问题出在格式上。您是否以某种方式使用QTextTableFormat?我看到相同的字符串看起来不同,所以你可能以不同的方式插入它。 哦,很抱歉造成混乱。用户手动将一些文本写入单元格。不,我不使用 QTextTableFormat。 【参考方案1】:

所以我通过选择所有内容并在文本更改时取消选择来解决它。理论上我只需要在 Table Block 时这样做。

onTextChanged:

    if(recoursionlock)
    
        recoursionlock =false;

        var curpos = tooltip_area.cursorPosition;
        var select_start = tooltip_area.selectionStart;
        var select_end = tooltip_area.selectionEnd;


        selectAll();
        deselect();
        if(curpos !== -1 && curpos >= tooltip_area.text.lenght)
            tooltip_area.cursorPosition = curpos;
        else
            tooltip_area.select(select_start,select_end)

        recoursionlock = true;

    


【讨论】:

以上是关于使用 QtQuick.Controls 1.12 将 Qt TextTable 与 TextArea 一起使用时,文本会错位的主要内容,如果未能解决你的问题,请参考以下文章

如何在 TableView QtQuick.Controls 2.4 中实现 TableView QtQuick.Controls 1.4 的 Selectable future

如何在 Ubuntu 上安装 QtQuick.Controls 1.4?

QML:带有图标的 QtQuick.Controls 选项卡

错误:“未安装模块“QtQuick.Controls””

QtQuick.Controls 2.2 中的 QML 组合框样式问题

QML QtQuick.Controls 2.2 Combobox 没有 selectByMouse;啥是替代方案?