从 QML 获得对文本光标的更多控制
Get more control over text cursor from QML
在源代码中,我注意到有相当全面的光标控制操作集:
enum MoveOperation {
NoMove,
Start,
Up,
StartOfLine,
StartOfBlock,
StartOfWord,
PreviousBlock,
PreviousCharacter,
PreviousWord,
Left,
WordLeft,
End,
Down,
EndOfLine,
EndOfWord,
EndOfBlock,
NextBlock,
NextCharacter,
NextWord,
Right,
WordRight,
NextCell,
PreviousCell,
NextRow,
PreviousRow
};
相比之下,来自 QtQuick.Controls 1.4
的最新 TextField
,光标位置显示为一个简单的整数,可以设置,但不指定任何这些移动操作。仅此而已。
在较旧的 TextEdit
中有一些额外的东西,例如 selectWord()
和 moveCursorSelection(int position, SelectionMode mode)
,但是 mode
仅限于选择字符或单词。
更糟糕的是,稀疏的现有 API 并没有真正提供必要的功能来手动重新实现其中的大多数模式。
所以,这让我想到了一个问题,即如何以最直接、最不突兀的方式在 QML 中获得所有这些功能?
更新:
实际上有一种更明显且侵入性更小的方法来获得该功能,它是通过将虚假事件发布到所需的文本编辑。这样做的好处是不需要使用私有 APIs,从而避免了所有潜在的构建和兼容性并发症:
void postKeyEvent(Qt::Key k, QObject * o, bool sh = false, bool ct = false, bool al = false) {
uint mod = Qt::NoModifier;
if (sh) mod |= Qt::ShiftModifier;
if (ct) mod |= Qt::ControlModifier;
if (al) mod |= Qt::AltModifier;
QCoreApplication::postEvent(o, new QKeyEvent(QEvent::KeyPress, k, (Qt::KeyboardModifier)mod));
QTimer::singleShot(50, [=]() { QCoreApplication::postEvent(o, new QKeyEvent(QEvent::KeyRelease, k, (Qt::KeyboardModifier)mod)); });
}
现在我终于可以在触摸设备上使用我的自定义虚拟键盘获得所有需要的光标控制内容了。
这是一个实际可行的简单解决方案...如果您设法构建它,则有一些 odd problems with building it:
#include <QtQuick/private/qquicktextedit_p.h>
#include <QtQuick/private/qquicktextedit_p_p.h>
#include <QtQuick/private/qquicktextcontrol_p.h>
class CTextEdit : public QQuickTextEdit {
Q_OBJECT
public:
CTextEdit(QQuickItem * p = 0) : QQuickTextEdit(p) {}
public slots:
void cursorOp(int mode) {
QQuickTextEditPrivate * ep = reinterpret_cast<QQuickTextEditPrivate *>(d_ptr.data());
QTextCursor c = ep->control->textCursor();
c.movePosition((QTextCursor::MoveOperation)mode);
ep->control->setTextCursor(c);
}
};
显然它使用私有headers,这有两个含义:
- 您必须将
quick-privte
模块添加到 PRO 文件
- 私人内容可能会发生变化,包括重大变化,因为这条友好的消息不断提醒:
_
Project MESSAGE: This project is using private headers and will therefore be tied to this specific Qt module build version.
Project MESSAGE: Running this project against other versions of the Qt modules may crash at any arbitrary point.
Project MESSAGE: This is not a bug, but a result of using Qt internals. You have been warned!
从好的方面来说,它就像一个魅力。 IMO 该功能应该作为 public API 的一部分开始提供,它非常有用,当然没有必要隐藏起来。
在源代码中,我注意到有相当全面的光标控制操作集:
enum MoveOperation {
NoMove,
Start,
Up,
StartOfLine,
StartOfBlock,
StartOfWord,
PreviousBlock,
PreviousCharacter,
PreviousWord,
Left,
WordLeft,
End,
Down,
EndOfLine,
EndOfWord,
EndOfBlock,
NextBlock,
NextCharacter,
NextWord,
Right,
WordRight,
NextCell,
PreviousCell,
NextRow,
PreviousRow
};
相比之下,来自 QtQuick.Controls 1.4
的最新 TextField
,光标位置显示为一个简单的整数,可以设置,但不指定任何这些移动操作。仅此而已。
在较旧的 TextEdit
中有一些额外的东西,例如 selectWord()
和 moveCursorSelection(int position, SelectionMode mode)
,但是 mode
仅限于选择字符或单词。
更糟糕的是,稀疏的现有 API 并没有真正提供必要的功能来手动重新实现其中的大多数模式。
所以,这让我想到了一个问题,即如何以最直接、最不突兀的方式在 QML 中获得所有这些功能?
更新:
实际上有一种更明显且侵入性更小的方法来获得该功能,它是通过将虚假事件发布到所需的文本编辑。这样做的好处是不需要使用私有 APIs,从而避免了所有潜在的构建和兼容性并发症:
void postKeyEvent(Qt::Key k, QObject * o, bool sh = false, bool ct = false, bool al = false) {
uint mod = Qt::NoModifier;
if (sh) mod |= Qt::ShiftModifier;
if (ct) mod |= Qt::ControlModifier;
if (al) mod |= Qt::AltModifier;
QCoreApplication::postEvent(o, new QKeyEvent(QEvent::KeyPress, k, (Qt::KeyboardModifier)mod));
QTimer::singleShot(50, [=]() { QCoreApplication::postEvent(o, new QKeyEvent(QEvent::KeyRelease, k, (Qt::KeyboardModifier)mod)); });
}
现在我终于可以在触摸设备上使用我的自定义虚拟键盘获得所有需要的光标控制内容了。
这是一个实际可行的简单解决方案...如果您设法构建它,则有一些 odd problems with building it:
#include <QtQuick/private/qquicktextedit_p.h>
#include <QtQuick/private/qquicktextedit_p_p.h>
#include <QtQuick/private/qquicktextcontrol_p.h>
class CTextEdit : public QQuickTextEdit {
Q_OBJECT
public:
CTextEdit(QQuickItem * p = 0) : QQuickTextEdit(p) {}
public slots:
void cursorOp(int mode) {
QQuickTextEditPrivate * ep = reinterpret_cast<QQuickTextEditPrivate *>(d_ptr.data());
QTextCursor c = ep->control->textCursor();
c.movePosition((QTextCursor::MoveOperation)mode);
ep->control->setTextCursor(c);
}
};
显然它使用私有headers,这有两个含义:
- 您必须将
quick-privte
模块添加到 PRO 文件 - 私人内容可能会发生变化,包括重大变化,因为这条友好的消息不断提醒:
_
Project MESSAGE: This project is using private headers and will therefore be tied to this specific Qt module build version.
Project MESSAGE: Running this project against other versions of the Qt modules may crash at any arbitrary point.
Project MESSAGE: This is not a bug, but a result of using Qt internals. You have been warned!
从好的方面来说,它就像一个魅力。 IMO 该功能应该作为 public API 的一部分开始提供,它非常有用,当然没有必要隐藏起来。