4

我有兴趣创建一个行为类似于代码区域的文本对象类型(继承QTextObjectInterface ):

  • 独特的背景
  • 边界
  • 固定宽度字体
  • 可编辑的内容
  • 实例需要可识别代码,以便可以提取其中的内容(将代码与周围内容分开)
  • 保存/加载(来自常规 html 文件)
  • 语法高亮将是一个加号,但并不是真正需要的

文档的其他区域需要以通常的方式运行(字体属性可编辑、颜色可编辑等)。


Qt 提供了一个使用QTextEdit实现自定义文本对象的示例。这看起来很难,因为新的文本对象不能利用 QTextEdit / QTextDocument中的现有基础设施。

QTextObject

可以将QTextDocument的各个部分组合在一起的不同类型对象的基类

所以继承它可能是一种选择,但它在 Qt SDK 包中的源文件和谷歌搜索都没有显示有用的信息。

QTextFrame继承QTextObject因此,如果要找到有关此路径的一些提示,它可能是一个可行的基类。


在一个简单的 HTML 文件中,所有这些(语法高亮除外)都很容易。QTextEdit以 html 作为输入,并且能够导出 html,但在此过程中结构丢失。

<code class="code-sample">
  int i = 0;
</code>

顺便说一下, QWebView是只读的。它宣传说:

HTML 文档的一部分可以通过 HTML 元素的 contenteditable 属性进行编辑。


可能还有其他平台可以随时使用,但文本编辑器需要在 Qt Creator 中作为插件使用,因此使用 Qt 框架是有意义的。

底线:如何在QTextEdit小部件中实现代码区域?


后期编辑:

  • 使用来自主干的 Qt sdk(将自身标识为 4.8.4)
  • 来自主干的 Qt Creator (Qt Creator 2.6.81)
4

1 回答 1

5

我发现使用 QTextEdit / QTextDocument 可以实现这一点。我能想到的最简单的实现在这个答案中提供,以供未来的寻求者参考。

请注意,需要自定义保存/加载,因为常规 .toHtml() 不会保留所需的信息。

插入代码块很简单:

QTextFrame * frame;

frame = cursor.insertFrame( code_block_format_ );
connect( frame, SIGNAL( destroyed() ),
  this, SLOT( codeBlockDeleted() ) );
code_blocks_.append( frame );

请注意您可以在类中保存的两个变量:

QTextFrameFormat code_block_format_;
QList<const QTextFrame*> code_blocks_;

我们需要框架的格式保持一致和独特。它可以在构造函数中初始化为:

code_block_format_.setBackground( QBrush( Qt::yellow ) );
code_block_format_.setBorder( 1 );
code_block_format_.setBorderStyle( QTextFrameFormat::BorderStyle_Inset);
code_block_format_.setMargin( 10 );
code_block_format_.setPadding( 4 );

我们需要该列表,以便我们可以判断某个帧是否是代码框。由于所有继承 QTextObject 的对象都需要由 QTextDocument::createObject() 创建,因此我们不能简单地将 QTextFrame 子类化(实际上我认为我们可以,但还不确定)。

现在可以按照通常的方式将代码内容与其他内容分开:

for ( it = frame->begin(); !(it.atEnd()); ++it ) {
  child_frame = it.currentFrame();
  child_block = it.currentBlock();
  if ( child_frame != NULL )
  {
    if ( code_blocks_.contains( frame ) )
    {
      /* ... */
    }
  }
} /* for ( it = frame->begin(); !(it.atEnd()); ++it ) */

但请注意,为了简洁起见,这被过度简化了。需要考虑嵌套框架。

如果您对完整实施感兴趣,请查看git 存储库(正在进行中,2012 年 11 月)。

于 2012-11-23T20:00:04.083 回答