QTextEdit 總結
1. HTML形式操縱QTextedit
QTextEdit支援HTML的一個子集, 所以對於簡單的使用, 可以直接插入HTML程式碼
editor->append("<img src=\"mydata://image.png\" />");
通過插入html程式碼, 可以實現圖片, 字型, 字號, 顏色等功能 ps: QTextEdit中img標籤僅支援src, width, height三個屬性, 使用其他屬性會自動被Qt過濾掉, 即editor->toHtml()中無法找到
可以通過正則來過濾toHtml()生成的程式碼
2. 在QTextEdit中播放gif
QTextEdit雖然直接img標籤, 但預設不播放gif, 也不會顯示gif的第一幀 (如果你不需要編輯功能的話, 其實可以用QWebView來檢視)
所以在QTextEdit中播放gif需要手動換幀.
QMovie內建了gif解析和定時器功能.
QTextDocument 使用addResource 把圖片資源載入進來, 然後通過QMovie->start啟動定時器, 不斷更新圖片資源
QString g_fileName = ":/test.gif";
QUrl g_url("TestImageTag");
void MyClass::InsertImage() { QMovie* movie = new QMovie(this); movie->setFileName(g_fileName); movie->setCacheMode(QMovie::CacheNone); //換幀時重新整理 connect(movie, SIGNAL(frameChanged(int)), this, SLOT(OnAnimate(int))); movie->start(); }
g_url 是自定義的標籤, 用來標記QTextDocument 中的resource
void MyClass::OnAnimate(int a) { if (QMovie* movie = qobject_cast<QMovie*>(sender())) { document()->addResource(QTextDocument::ImageResource, //替換圖片為當前幀 g_url, movie->currentPixmap()); setLineWrapColumnOrWidth(lineWrapColumnOrWidth()); // 重新整理顯示 } }
addResource 指定ImageResource, 然後根據url, 若url已存在, 則更新資源, 若url不存在, 則新增資源
這樣就實現重新整理gif的幀. 這樣, QTextEdit就會顯示gif動畫了
最後是新增gif圖片:可以插入HTML
editor->append("<img src=\"TestImageTag\" />");
即img中指定為我們自定義的url即可
也可以使用QTextCursor插入:
QTextCursor cursor = editor->textCursor();
QTextImageFormat imageFormat;
imageFormat.setName("TestImageTag");
cursor.insertImage(imageFormat);
PS: 可以使用兩個陣列來儲存自定義的URL和QMOVIE, 以便管理資源釋放等問題
PS2: 在我的測試中, 即使呼叫了Qtextedit和QTextDocument的clear也無法釋放addResource圖片資源的記憶體. 只有把QTextEdit整個delete掉, 才會釋放所有圖片資源佔據的記憶體. 這是個問題, 可能需要看原始碼來解決. 不過如果圖片不多的話, 這個問題也可以忽略
3. 如何遍歷QTextEdit中的內容
QTextEdit中的內容實際上是由QTextDocument維護
可以簡單的理解: QTextDocument 包含 N個QTexBlock(段落), 每個QTexBlock包含N個QTextFragment
QColor _GetRamdomColor()
{
QColor col;
int RamdomNum = rand() % 0xffffff;
char strCol[8];
sprintf(strCol, "#%06x", RamdomNum);
col.setNamedColor(QString::fromLocal8Bit(strCol, 8));
return col;
}
void MyClass::OnTest()
{
QTextDocument *document = ui.textEdit->document();
QTextBlock ¤tBlock = document->begin();
QTextBlock::iterator it;
QTextCursor cursor = ui.textEdit->textCursor();
while( true)
{
// 在修改chatformat時會改變當前Block的fragment
// 所以++it的處理類似std::map中的erase操作
for (it = currentBlock.begin(); !(it.atEnd()); )
{
QTextFragment currentFragment = it.fragment();
QTextImageFormat newImageFormat = currentFragment.charFormat().toImageFormat();
if (newImageFormat.isValid()) {
// 判斷出這個fragment為image
++it;
continue;
}
if (currentFragment.isValid())
{
++it;
int pos = currentFragment.position();
QString strText = currentFragment.text();
for(int i = 0; i < strText.length(); i++)
{
// 選擇一個字, 隨機設定顏色
QTextCharFormat fmt;
fmt.setForeground(_GetRamdomColor());
QTextCursor helper = cursor;
helper.setPosition(pos++);
helper.setPosition(pos, QTextCursor::KeepAnchor);
helper.setCharFormat(fmt);
}
}
}
currentBlock = currentBlock.next();
if(!currentBlock.isValid())
break;
}
// 游標移動到最後, 並設定擁有焦點
QTextCursor c = ui.textEdit->textCursor();
c.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
ui.textEdit->setTextCursor(c);
ui.textEdit->setFocus(Qt::MouseFocusReason);
}
這段程式碼用於渲染QTextEdit為炫彩, 每個字隨機分配一種顏色
遍歷的時候, 判斷是圖片還是文字. 並作相應的處理
同時, 處理下QTextDocument的contentChange事件, 即可在鍵盤輸入時, 就改變字的顏色
connect(document, SIGNAL(contentsChange( int , int , int )),
this, SLOT(OnContentChange( int , int , int )));
void MyClass::OnContentChange( int position, int charsRemoved, int charsAdded )
{
if(charsAdded == 0)
return;
QTextCursor cursor = ui.textEdit->textCursor();
for (int i = 0; i < charsAdded; i++ )
{
int pos = position + i;
// 選擇一個字, 隨機設定顏色
QTextCharFormat fmt;
fmt.setForeground(_GetRamdomColor());
QTextCursor helper = cursor;
helper.setPosition(pos);
helper.setPosition(pos+1, QTextCursor::KeepAnchor);
helper.setCharFormat(fmt);
}
}
PS: 對某段文字執行setCharFormat也會觸發contentChange訊號, 並且charsRemoved == charsAdded; 可以處理一下這個case 這樣一般來說滿足了大部分需求, 做出類似QQ的聊天輸入框只需要再處理下複製黏貼圖片之類就行了. 至於Qt的rich edit中frame table list等, 需要的話, 就看看文件吧, 感覺功能不是很必要