QTextEdit中的自定义文本(代码)区域

时间:2012-11-22 17:48:00

标签: c++ qt custom-controls qtextedit qtextdocument

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

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

文档的其他区域需要采用通常的方式(字体属性可编辑,颜色可编辑等)。


Qt提供了an example来实现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窗口小部件中实现代码区域?


后期编辑:

  • 使用来自trunk的Qt sdk(将自己标识为4.8.4)
  • Qt Creator from trunk(Qt Creator 2.6.81)

1 个答案:

答案 0 :(得分:4)

我发现使用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 repository(正在进行的工作,2012年11月)。