gpt4 book ai didi

c++ - 使用 QTextEdit 检测用户输入(并将其与应用程序更改区分开来)

转载 作者:IT王子 更新时间:2023-10-29 01:25:50 25 4
gpt4 key购买 nike

Gtk3 丰富 text widget机械(基于 GtkTextBufferGtkTextView )同时具有 "begin-user-action""end-user-actions"信号,允许快速方便地处理用户输入(并将其与应用程序对缓冲区或 View 生成的更改区分开来)。

但是Qt5好像没有类似的东西。例如,我不完全的理解是 QTextEdit::insertHtmlQTextDocument::contentsChangeQTextDocument::contentsChanged不会将与用户输入(键盘或粘贴等)相关的更改与应用程序完成的更改分开。

我的想法是一些面向语法的编辑器。

我可能误解了 Qt5 富文本编辑器支持。

(对于好奇的人:我正在用 C 和 GTK 重新设计和重新实现我的 MELT monitor 到用 C++11 和 Qt5 暂时称为 Basixmo 的东西;所有都是 GPL 免费软件,但我没有编码但 Qt5 的东西)

例子

我有一个窗口,其中有一个按钮 say 和一个 QTextEdit 作为它的中央小部件。当我单击该按钮时,一个 "hello" 字符串被插入到文档中,我称之为 application 更改(您可以想象该按钮被替换为不相关的内容给用户,例如一些网络输入)。当我在文本编辑器中键入一些按键时,还会从该用户操作 更改中插入一些字符串。我想区分两者。

#include <QApplication>
#include <QMainWindow>
#include <QTextEdit>
#include <QToolBar>
#include <fstream>
#include <iostream>
int main(int argc, char**argv)
{
QApplication app(argc, argv);
auto win = new QMainWindow;
auto tb = win->addToolBar("Basile example");
auto ted = new QTextEdit;
win->setCentralWidget(ted);
tb->addAction("say",[=]{ted->insertPlainText("hello");});
auto doc = ted->document();
QObject::connect(doc,&QTextDocument::contentsChange,
[=](int pos, int removedchars, int addedchars)
{ std::clog << "contentChange: pos=" << pos
<< " removedchars=" << removedchars
<< " addedchars=" << addedchars
<< std::endl; });
win->show();
app.exec();
delete win;
}


//// Local Variables:
//// compile-command: "g++ -std=c++11 -Wall -g $(pkg-config --cflags Qt5Core Qt5Widgets Qt5Gui) -fPIC $(pkg-config --libs Qt5Core Qt5Widgets Qt5Gui) -o eqb eqb.cc"
//// End:

但是当我运行上面的代码时,contentsChange 信号(连接到我的 lambda 函数输出到 std::clog)被触发用于用户操作更改和应用程序更改。

我不关心在 QTextEditQTextDocumentQTextCursor 级别工作,但我想将用户操作更改分开(键入 QTextEdit 小部件,或使用鼠标单击和菜单粘贴等...)来自应用程序更改。我想避免在小部件事件级别工作(例如,在我自己的类中为 QWidget::keyPressEvent 重新定义一个虚拟成员函数,等等),特别是因为我不确定 所有影响QTextEdit实例的可能事件。

顺便说一句,我的问题可能过于笼统:如何设计和编码像 emacs 一样可编写脚本的编辑器正在使用 genuine Qt5 编码风格和 C 中的小部件++11(当然是通过嵌入一些可编写脚本的解释器 à la Guile)。

附言。如果那很重要,我的桌面系统运行 Debian/testing/x86-64。 Qt是5.6.1版本,我的代码是用GCC 6.2编译的;编译命令在最后的宽评里。

最佳答案

在您的特定情况下,您感兴趣的信号是在 QTextDocument 对象上发出的,该对象是 QTextEdit 的一部分。
您可以在 lambda 中使用 QSignalBlocker 来阻止发出这些信号:

#include <QSignalBlocker>

// ...

tb->addAction("say", [=]{
const QSignalBlocker blocker{ted->document()};
ted->insertPlainText("hello");
});

这样,当应用程序更改文档的上下文时,您将不会再收到contentsChange 信号。

参见 official documentation了解更多详情。

请注意,QTextEdit 上的信号未被禁止。
它们可能绑定(bind)到 QTextDocument 的那些并传播(如果您对这些细节感兴趣,可以查看类的代码)。
如果您想区分用户更改和应用程序更改,您现在可以扩展该类并添加要从您的 lambda 中发出的自定义信号(例如,internalContentChange)。
否则,直接调用一个方法就可以了。
要做什么主要取决于具体问题和软件的设计方式。


作为旁注和评论中提到的,更多细节可以更好地解释其工作原理。
QTextEdit(让我说)转发 insertPlainText 请求到内部 QTextDocument。因此,后者发出的信号被 QTextEdit捕获并传播
这就是为什么上述技巧通过抑制内部类上的信号而适用于特定情况。换句话说,QTextEdit 既有自己的信号,又充当其组件(主要是 QTextDocument)发出的某些信号的再发射器。

为了清楚起见,我尽量保持简单,但您可以通过查看存在的类来了解请求和信号的流程 here (公共(public)存储库)。
特别是,hereQTextEdit 组件将 insertPlainText 调用转发给内部 QTextEditControl 的地方组件,它本身就是一个 QWidgetTextControlforwards the call到内部游标...等等。
路径太长,无法在此处进行全面分析。

关于c++ - 使用 QTextEdit 检测用户输入(并将其与应用程序更改区分开来),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40332168/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com