如何在我的C ++应用程序中重用Qt的QTextCursor?

时间:2015-08-11 04:58:49

标签: c++ qt text-editor

我正在使用C ++中的Qt在Windows上实现文本编辑器,并使用QWidget作为我使用OpenGL显示文本的表面。到目前为止,我有自己的布局引擎和文档模型,并且能够在窗口小部件上显示文本。

现在我正在尝试实现一个类似于Qt提供的文本游标,但QTextCursor与其QTextDocument模型密切相关,我无法使用我的模型将其子类化以便重用。有没有办法在没有模型的情况下重用光标?

如果没有,我如何使用Qt实现文本光标?

注意:我确实通过了Windows here提供的Caret方法,但我希望避免直接使用它们。

1 个答案:

答案 0 :(得分:0)

TL; DR:你不能。这不是一个插入符号。

QTextCursor是一个迭代器,它与屏幕上的光标无关。如果它作为迭代器很有用,你当然可以重用它,如果你自己的文本表示是在QTextDocument之上构建的。但它不是一个插入符号。

可见光标控件由QTextEdit实现提供。回想一下,QTextEditQTextDocument的视图 - 它完全用于文本的图形渲染,控制可见光标等。

没有可用于插入符号的公共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);
  }
};