我有一个拼写检查线程,可以不时触发spellcheck()
信号,这些信号与我的荧光笔的rehighlight()
方法相关联。后者将整个块设置为红色前景。
这曾在Qt 5.6.2中使用,并且不再适用于较新版本。我绝望地等待它在Qt 5.9.5中得到修复,但它仍然不起作用(在Windows 10和OS X中都没有)。
可以从这里https://bitbucket.org/ribtoks/qt-highlighting-issue获得重现问题的小例子(为了重新编写,在输入中键入内容。rehighlight()
将从后台线程每7秒触发一次)
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickTextDocument>
#include <QSyntaxHighlighter>
#include <QThread>
#include <QString>
class SpellCheckWorker : public QObject
{
Q_OBJECT
public:
explicit SpellCheckWorker(QObject *parent = 0) : QObject(parent), m_Counter(0), m_IsOK(false)
{ }
public:
bool isOK() { return m_IsOK; }
signals:
void spellcheck();
public slots:
void process() {
qInfo() << "Worker Thread is" << QThread::currentThreadId();
while (1) {
m_Counter++;
m_IsOK = m_Counter % 7 == 0;
QThread::sleep(1);
emit spellcheck();
}
}
private:
int m_Counter;
volatile bool m_IsOK;
};
class SpellCheckErrorsHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
SpellCheckErrorsHighlighter(SpellCheckWorker *worker, QTextDocument *document):
QSyntaxHighlighter(document),
m_Worker(worker)
{ }
virtual ~SpellCheckErrorsHighlighter() {}
protected:
virtual void highlightBlock(const QString &text) override {
if (!m_Worker->isOK()) {
qDebug() << "Worker is not OK" << text;
return;
}
qInfo() << "Reapplied formatting for" << text;
qInfo() << "Highlight thread is" << QThread::currentThreadId();
this->setFormat(0, text.length(), QColor(0xff, 0, 0));
}
private:
SpellCheckWorker *m_Worker;
};
class MainModel : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
explicit MainModel(QObject *parent = 0) : QObject(parent), m_Worker(nullptr)
{ }
public:
QString name() const { return m_name; }
void startChecking() {
qInfo() << "Main thread is" << QThread::currentThreadId();
m_Worker = new SpellCheckWorker();
QThread *thread = new QThread();
m_Worker->moveToThread(thread);
QObject::connect(thread, &QThread::started, m_Worker, &SpellCheckWorker::process);
thread->start();
}
Q_INVOKABLE void initNameHighlighting(QQuickTextDocument *document) {
SpellCheckErrorsHighlighter *highlighter = new SpellCheckErrorsHighlighter(m_Worker, document->textDocument());
QObject::connect(m_Worker, &SpellCheckWorker::spellcheck,
highlighter, &SpellCheckErrorsHighlighter::rehighlight);
}
signals:
void nameChanged();
public slots:
void setName(QString name)
{
if (m_name == name)
return;
m_name = name;
emit nameChanged();
}
private:
SpellCheckWorker *m_Worker;
QString m_name;
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
MainModel mainModel;
mainModel.startChecking();
QQmlApplicationEngine engine;
QQmlContext *rootContext = engine.rootContext();
rootContext->setContextProperty("mainModel", &mainModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
#include "main.moc"
和main.qml
import QtQuick 2.6
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.3
import QtQuick.Window 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
StackView {
id: mainStackView
anchors.fill: parent
focus: true
initialItem: Rectangle {
anchors.fill: parent
Rectangle {
id: titleRect
height: 30
width: 300
anchors.centerIn: parent
color: "#ffffff"
border.color: "#000000"
border.width: titleTextInput.activeFocus ? 1 : 0
clip: true
focus: false
Flickable {
id: titleFlick
contentWidth: titleTextInput.paintedWidth
contentHeight: titleTextInput.paintedHeight
height: parent.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 5
anchors.rightMargin: 5
clip: true
flickableDirection: Flickable.HorizontalFlick
interactive: false
focus: false
function ensureVisible(r) {
if (contentX >= r.x)
contentX = r.x;
else if (contentX+width <= r.x+r.width)
contentX = r.x+r.width-width;
}
TextEdit {
id: titleTextInput
width: paintedWidth > titleFlick.width ? paintedWidth : titleFlick.width
height: titleFlick.height
text: mainModel.name
focus: true
onTextChanged: mainModel.name = text
Component.onCompleted: mainModel.initNameHighlighting(titleTextInput.textDocument)
onCursorRectangleChanged: titleFlick.ensureVisible(cursorRectangle)
}
}
}
}
}
}
有没有办法让它使用变通方法?我需要在后台线程中保留拼写检查逻辑,因此无法将其移动到主线程。
答案 0 :(得分:-1)
您似乎指的是两个不同的根本原因,并带有以下两个陈述:
向荧光笔提供插槽调用没有问题。
和
m_Worker-&gt; isOK()检查是否有理由每7秒执行一次突出显示。 Qt中的错误只能用这个证明。
如果我只关注第二个语句,看起来问题是你无法点击语句if (!m_Worker->isOK())
吗?
由于您的代码或特定平台上的Qt问题,这可能是一个问题。
您是否可以更改代码以避免出现这种情况,即仅在7秒后发出spellcheck
信号以避免从另一个线程进行此检查?
答案 1 :(得分:-3)
好的,所以在弄乱你的代码之后,问题是你没有在第55行附近的main.cpp
中的hilightBlock指令中调用这一行,以保持之前的格式。
添加此内容以修复它(我认为)问题仍然相当不明确......
if (!m_Worker->isOK()) {
qDebug() << "Worker is not OK" << text;
this->setFormat(0, text.length(), this->format(0));
return;
}
问题的另一部分是您没有为语法高亮显示器定义任何规则...因此一旦变为红色它将始终为红色。