【问题标题】:What is the difference between the "selection" and the "cursor" in QTextEdit?QTextEdit 中的“选择”和“光标”有什么区别?
【发布时间】:2019-07-16 18:17:32
【问题描述】:

在 QTextEdit 的文档中,我看到定义了两个信号:

void cursorPositionChanged()
void selectionChanged()

前者的文档只说“只要光标位置发生变化,就会发出这个信号。”后者的文档只说“只要选择发生变化,就会发出这个信号。”在 QTextEdit 文档的其他地方,听起来这两个概念是相同的;例如,“文本的选择由 QTextCursor 类处理,它提供了创建选择、检索文本内容或删除选择的功能。”那么这两个信号有什么区别呢?

【问题讨论】:

  • 我希望光标是文本中的“编辑位置”,即用户的文本光标当前所在的位置(如果他们键入,文本将添加到哪里)。我希望选择是当前选择的任何文本。见QTextCursor
  • 我似乎记得光标是插入任何键入的文本的位置,而选择是您选择的文本范围。你总是有一个光标,但你可能没有选择任何东西。我认为这两者是相关的,因为您移动光标来创建选择。

标签: c++ qt qtextedit


【解决方案1】:

游标是一个迭代器:它是您可以“指向”文档中某些内容的唯一方法。因此,要创建选择,您需要两个光标位置 - anchor() 位置和当前 position()。这就是为什么游标同时拥有它们的原因(它不是最简洁的 API,但可行的选择 API 会复制很多游标的 API)。由于光标用于指向文档,因此选择取决于它们,并且您无法在没有光标的情况下定义选择。为了清楚地表明光标是构建选择的基础,您只能将选择创建为光标的属性。

由于游标是一个迭代器,一个文档上可以有多个游标。 cursorPositionChanged() 仅在主光标上发出,表示可见的闪烁光标。因此,此信号仅在 QTextEdit 上可用,它维护自己的主光标。文档本身没有那个信号,因为没有单个光标是特殊的。这样你就有了QTextDocument::cursorPositionChanged(const QTextCursor &) 信号。

同样,一个文档可以有多个选择 - 一个选择是光标的属性,但只有主光标的选择是可见的,并且 selectionChanged() 仅在该主要选择更改时才会发出。可以存在其他选择,因为选择只是文档中的一个范围,并且有很多理由使用不必可见的选择。

您可以在没有QTextEdit 的情况下以编程方式对文档进行所有编辑,因此QTextDocument 甚至没有selectionChanged 信号,因为没有单一选择可以支持。但是,当光标的选择发生变化时,它会发出一个光标变化信号。

要理解这些概念,最好只看QTextDocument,看看它的API 和QTextEdit 的API 之间的区别。

【讨论】:

    【解决方案2】:

    我认为解释差异的最佳方式是展示一些最小但完整的示例。首先,让我们假设我们有一些 textEdit,并将其连接到提到的信号:

    connect(ui->textEdit, &QTextEdit::selectionChanged, this, []
    {
        qDebug() << "Selection Changed";
    });
    
    connect(ui->textEdit, &QTextEdit::cursorPositionChanged, this, []
    {
        qDebug() << "Cursor Position Changed";
    });
    

    现在可能有以下用例会导致信号被触发,因此输出将基于此而有所不同:

    1. 您可以通过键盘输入一些文本而无需选择它。在这种情况下,只有光标位置会改变,因此 &QTextEdit::cursorPositionChanged 将被触发,这将导致打印“光标位置已更改”文本。
    2. 您可以在 Windows 上使用 Ctrl+A 组合来选择所有文本。在这种情况下 &QTextEdit::selectionChanged 将被触发,但 &QTextEdit::cursorPositionChanged 不会。
    3. 在 Windows 上,您可以单击鼠标左键,然后以这样的方式移动它,使文本不会被实际选中。在这种情况下,您将多次触发 &QTextEdit::selectionChanged。不知道为什么(可能是 Qt 问题?)

    换句话说,我认为你应该试试这个例子,看看如何检索不同的输出,以便看到和感受不同之处。最后,这两个信号之间的主要区别在于,一个是关于文本光标在 QTextEdit 元素中移动的位置,另一个是关于通过键盘选择的文本,通过鼠标交互发生变化。此外,这两个信号都可能被触发,因为光标位置和所选文本都可能发生变化。

    【讨论】:

    • 我已将此作为公认的答案,因为这种行为似乎非常不一致和奇怪,以至于“试试看”是唯一似乎正确的答案。不幸的。我发现我必须同时聆听这两个信号才能真正获得有用的信息。
    【解决方案3】:

    QTextCursor 有两个与这些信号相关的位置,anchorposition

    selectionChanged 将在锚点或位置更改时发出1

    cursorPositionChanged 会在位置改变时发出。

    QTextCursor 以文本光标在文本编辑器中的行为方式为模型,提供通过用户界面执行标准操作的编程方式。可以将文档视为单个字符串。光标当前的position() 总是在字符串中的两个连续字符之间,或者在字符串的第一个字符之前或最后一个字符之后。

    QTextCursor 也有一个anchor() 位置。 anchor()position() 之间的文本是选择。如果anchor() == position() 没有选择。

    1. 除非“无选择”改变位置,即改变前后它们相等。

    【讨论】:

    • 我已经接受了这个答案,但不幸的是它似乎并不完全正确。例如,如果您有一个零宽度选择(只是一个插入点)并按向左箭头向左移动一个位置,则不会发出 selectionChanged (遵循此答案的脚注 1),但如果您 单击 将插入点移动到新位置, selectionChanged is 发出(与此答案的脚注 1 相矛盾)。这种行为似乎是不一致的、奇怪的,而且相当无用。我得出的结论是,我必须同时听取这两个信号才能获得有用的信息。
    猜你喜欢
    • 2012-11-14
    • 2014-06-04
    • 1970-01-01
    • 2011-08-02
    • 2013-06-27
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    相关资源
    最近更新 更多