我最近遇到了一個奇怪的問題,我的QPlainTextEdit::selectionChanged處理函式在每當QTextCursor::mergeCharFormat/setCharFormat/setBlockCharFormat被呼叫時就會過早地終止。此外,在終止后,它被再次呼叫,并遇到同樣的問題,導致了一個無限回圈。
我正試圖復制許多文本編輯器(例如 Notepad )中的一個功能,即在選擇一個單詞時,整個檔案中的所有類似單詞都會被高亮顯示。我的TextEditor類是從QPlainTextEdit中多載的。
最小的可重復的例子如下:
main.cpp:
#include "mainWindow.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv)。
mainWindow w;
w.show()。
return a.exec()。
MainWindow.h:
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_mainWindow.h"
#include "TextEditor.h"
class mainWindow : public QMainWindow
{
Q_OBJECT
public:
mainWindow(QWidget *parent = Q_NULLPTR) : QMainWindow(parent)
{
ui.setupUi(this)。
auto textEdit = new TextEditor(this)。
textEdit->setPlainText("test lorem ipsum test
dolor sit test")。)
ui.tabWidget->addTab(textEdit, "Editor"); /Or any other way of adding the widget to the window.
}
private:
Ui::mainWindowClass ui;
};
TextEditor.h:
regex高亮部分是基于這個SO答案。
#pragma once
#include <QPlainTextEdit>
class TextEditor : public QPlainTextEdit
{
Q_OBJECT
public:
TextEditor(QWidget* parent) : QPlainTextEdit(father)
{
connect(this, &QPlainTextEdit::selectionChanged, this, &TextEditor::selectChangeHandler);
}
private:
void selectChangeHandler().
{
//Ignore empty selections。
if (textCursor(). selectionStart() >= textCursor().selectionEnd()
return;
//We only care about fully selected words (nonalphanumerical characters on either side of selection)
auto plaintext = toPlainText();
auto prevChar = plaintext.mid(textCursor). selectionStart() - 1, 1).toStdString() [0] 。
auto nextChar = plaintext.mid(textCursor). selectionEnd(), 1).toStdString()[0] 。
if (isalnum(prevChar) || isalnum(NextChar))
return;
auto qselection = textCursor().selectedText() 。
auto selection = qselection.toStdString()。
//我們也只關心那些本身不包含非字母數字字符的選擇。
if (std::find_if(selection.begin(), selection。 end(), [](char c) { return ! isalnum(c); }) != selection.end()
return;
//準備文本格式。
QTextCharFormat format。
format.setBackground(Qt::green)。
//Find all words in our document that match the selected word and apply the background format to them[/span>.
size_t pos = 0;
auto reg = QRegExp(qselection)。
auto cur = textCursor();
auto index = reg.indexIn(plaintext, pos)。
while (index >= 0)
{
//Select matched text and apply format(index >= 0)
cur.setPosition(index)。
cur.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor, 1)。
cur.mergeCharFormat(format); //這導致selectChangeHandler函式終止,然后再次執行,造成無限回圈,導致堆疊溢位。
//Move to next matchsize_t)reg.matchedLength() 。
index = reg.indexIn(plaintext, pos)。
}
}
};
我懷疑由于某種原因,格式無法應用,可能導致Qt內部捕獲例外,并終止父函式。我嘗試在有問題的區域周圍添加我自己的 try-catch 處理程式,但它什么也沒做(如預期)。
我不確定這是我的錯還是 Qt 內部的錯誤。有沒有人知道我做錯了什么,或者如何解決這個問題?
uj5u.com熱心網友回復:
一個無限的回圈正在產生,因為似乎獲得文本的變化也會改變選擇。一個可能的解決方案是使用QSignalBlocker來阻止這些信號:
void selectChangeHandler()
{
const QSignalBlocker blocker(this)。// <----這一行
//Ignore empty selections。
if (textCursor). selectionStart() >= textCursor().selectionEnd()
return;
/ ...
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/310187.html
標籤:
