我正在使用C ++中的Qt在Windows上实现文本编辑器,并使用QWidget作为我使用OpenGL显示文本的表面。到目前为止,我有自己的布局引擎和文档模型,并且能够在窗口小部件上显示文本。
现在我正在尝试实现一个类似于Qt提供的文本游标,但QTextCursor与其QTextDocument模型密切相关,我无法使用我的模型将其子类化以便重用。有没有办法在没有模型的情况下重用光标?
如果没有,我如何使用Qt实现文本光标?
注意:我确实通过了Windows here提供的Caret方法,但我希望避免直接使用它们。
答案 0 :(得分:0)
TL; DR:你不能。这不是一个插入符号。
QTextCursor
是一个迭代器,它与屏幕上的光标无关。如果它作为迭代器很有用,你当然可以重用它,如果你自己的文本表示是在QTextDocument
之上构建的。但它不是一个插入符号。
可见光标控件由QTextEdit
实现提供。回想一下,QTextEdit
是QTextDocument
的视图 - 它完全用于文本的图形渲染,控制可见光标等。
没有可用于插入符号的公共Qt API。当您使用Qt进行渲染时,WINAPI插入符号方法完全没用。您需要自己的插入符号实现。鉴于你已经有了一个文本表示和一个渲染器,你可能有一个迭代器可以处理文本表示,所以实现插入符应该是一个微不足道的事情。
使用Qt的力量重新实现WINAPI插入非常简单和微不足道:
class Caret : public QWidget {
Q_OBJECT
Q_PROPERTY(int period READ period WRITE setPeriod)
QPicture m_shape;
BasicTimer m_timer;
int m_period;
void updateSize() {
auto size = m_shape.boundingRect().size();
setFixedSize(size);
resize(size);
}
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() != m_timer.timerId()) return;
if (isVisible()) hide(); else show();
}
public:
QPicture defaultShape(int w, int h) {
QPicture pic;
QPainter p(&pic);
p.fillRect(0, 0, w, h, Qt::black);
return pic;
}
Caret(QWidget * parent = 0, const QPicture & pic = defaultShape()) :
QWidget(parent), m_shape(pic), m_period(250) {
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_TranslucentBackground);
m_timer.start(m_period);
updateSize();
}
void setShape(const QPicture & pic) {
m_shape = pic;
updateSize();
update();
}
void setPeriod(int period) {
if (period < 1) {
m_timer.stop();
if (m_period > 0) show();
} else
m_timer.start(period);
m_period = period;
}
int period() const { return m_period; }
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE {
auto painter = QPainter(this);
painter.fillRect(rect(), Qt::transparent);
painter.drawPicture(QPoint(), m_shape);
}
};