Text Edit Example
文本编辑示例显示了Qt的富文本编辑功能的实际应用。
QTextEdit
QTextEdit小部件是一种高级编辑器,支持格式化的富文本格式。它可以用于显示HTML和其他丰富的文档格式。 在内部,QTextEdit使用QTextDocument类来描述两者每个文档的结构和段落的低级格式。
如果您正在textedit示例中查看此文档,则可以编辑此文档文档来探索Qt的RTF富文本编辑功能。 我们包括了一些以下各节中的注释可鼓励您进行实验。
字体和段落样式
QTextEdit 支持 粗体、单色和下划线字体样式,并且可以显示多色文本。字体系列,如 Times New Roman 和 Courier 也可以直接使用。如果将光标放在样式文本区域中,则工具栏中的控件将变换以反映当前样式。
段落可以设置格式,使文本保持左对齐、右对齐、居中或完全对齐。
尝试更改某些文本的对齐方式并调整编辑器的大小,以查看文本布局的变化情况。
列表
富文本文档中可以包含不同类型的列表。可以嵌套标准项目符号列表,对列表的每个级别使用不同的符号:
-
光盘符号通常用于顶级列表项。
-
圆形符号可用于区分较低级别列表中的项目。
-
方形符号为圆盘和圆提供了合理的替代。
可以创建可用于目录的有序列表。不同的字符可用于枚举项,我们可以在同一列表结构中同时使用罗马数字和阿拉伯数字:
-
介绍
-
Qt 工具
-
Qt 助手
-
Qt 设计器
- 表单编辑器
- 组件架构
-
Qt 语言学家
-
如果添加或删除项目,将自动重新编号列表。尝试将新部分添加到上述列表或删除现有项目以查看数字更改。
图像
内联图像被视为文本编辑器中的普通字符范围,因此它们与周围的文本一起流动。也可以以与文本相同的方式选择图像,以便于剪切、复制和粘贴它们。
尝试通过单击并拖动鼠标来选择此图像,或使用文本光标按住 Shift 并使用箭头键来选择它。然后,您可以剪切或复制它,并将其粘贴到本文档的不同部分。
表
QTextEdit 可以排列和格式化表,支持行和列范围、单元格中的文本格式以及列的大小限制等功能。
开发工具 | 编程技术 | 图形用户界面 | |
---|---|---|---|
9:00 - 11:00 | Qt简介 | ||
11:00 - 13:00 | 使用qmake | 面向对象的编程 | Qt中的布局 |
13:00 - 15:00 | Qt 设计器教程 | 极限编程 | 编写自定义样式 |
15:00 - 17:00 | Qt 语言学家与国际化 |
尝试向表中的单元格添加文本,并尝试段落的对齐方式。
链接
QTextEdit 旨在支持文档之间的超链接,此功能在 Qt 助手中广泛使用。当 HTML 文件导入编辑器时,将自动创建超链接。由于富文本框架支持本机超链接,因此也可以以编程方式创建超链接。
撤消和重做
对撤消和重做操作的完全支持内置于 QTextEdit 和基础富文本框架中。文档的操作可以打包在一起,使编辑功能对用户更舒适。
尝试对此文档进行更改,然后按 Ctrl+Z 撤消它们。您始终可以恢复文档的原始内容。
源代码
TextEdit的定义
class TextEdit : public QMainWindow
{
Q_OBJECT
public:
TextEdit(QWidget *parent = 0);
bool load(const QString &f);
public slots:
void fileNew();
protected:
void closeEvent(QCloseEvent *e) override;
private slots:
void fileOpen();
bool fileSave();
bool fileSaveAs();
void filePrint();
void filePrintPreview();
void filePrintPdf();
void textBold();
void textUnderline();
void textItalic();
void textFamily(const QString &f);
void textSize(const QString &p);
void textStyle(int styleIndex);
void textColor();
void textAlign(QAction *a);
void setChecked(bool checked);
void indent();
void unindent();
void currentCharFormatChanged(const QTextCharFormat &format);
void cursorPositionChanged();
void clipboardDataChanged();
void about();
void printPreview(QPrinter *);
private:
void setupFileActions();
void setupEditActions();
void setupTextActions();
bool maybeSave();
void setCurrentFileName(const QString &fileName);
void modifyIndentation(int amount);
void mergeFormatOnWordOrSelection(const QTextCharFormat &format);
void fontChanged(const QFont &f);
void colorChanged(const QColor &c);
void alignmentChanged(Qt::Alignment a);
QAction *actionSave;
QAction *actionTextBold;
QAction *actionTextUnderline;
QAction *actionTextItalic;
QAction *actionTextColor;
QAction *actionAlignLeft;
QAction *actionAlignCenter;
QAction *actionAlignRight;
QAction *actionAlignJustify;
QAction *actionIndentLess;
QAction *actionIndentMore;
QAction *actionToggleCheckState;
QAction *actionUndo;
QAction *actionRedo;
QAction *actionCut;
QAction *actionCopy;
QAction *actionPaste;
QComboBox *comboStyle;
QFontComboBox *comboFont;
QComboBox *comboSize;
QToolBar *tb;
QString fileName;
QTextEdit *textEdit;
};
TextEdit的实现
#include <QtWidgets>
#include <QtPrintSupport>
#include "TextEdit.h"
// 图片是从Qt的example里拷贝到工程文件夹下面的,需要自己定义
const QString rsrcPath = "E:/Project/QtProject/RichTextFormat/Text_Edit_Example/images/win";
TextEdit::TextEdit(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(QCoreApplication::applicationName());
textEdit = new QTextEdit(this);
connect(textEdit, &QTextEdit::currentCharFormatChanged,
this, &TextEdit::currentCharFormatChanged);
connect(textEdit, &QTextEdit::cursorPositionChanged,
this, &TextEdit::cursorPositionChanged);
setCentralWidget(textEdit);
setToolButtonStyle(Qt::ToolButtonFollowStyle);
setupFileActions();
setupEditActions();
setupTextActions();
{
QMenu *helpMenu = menuBar()->addMenu(tr("Help"));
helpMenu->addAction(tr("About"), this, &TextEdit::about);
helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
}
QFont textFont("Helvetica");
textFont.setStyleHint(QFont::SansSerif);
textEdit->setFont(textFont);
fontChanged(textEdit->font());
colorChanged(textEdit->textColor());
alignmentChanged(textEdit->alignment());
connect(textEdit->document(), &QTextDocument::modificationChanged,
actionSave, &QAction::setEnabled);
connect(textEdit->document(), &QTextDocument::modificationChanged,
this, &QWidget::setWindowModified);
connect(textEdit->document(), &QTextDocument::undoAvailable,
actionUndo, &QAction::setEnabled);
connect(textEdit->document(), &QTextDocument::redoAvailable,
actionRedo, &QAction::setEnabled);
setWindowModified(textEdit->document()->isModified());
actionSave->setEnabled(textEdit->document()->isModified());
actionUndo->setEnabled(textEdit->document()->isUndoAvailable());
actionRedo->setEnabled(textEdit->document()->isRedoAvailable());
actionCut->setEnabled(false);
connect(textEdit, &QTextEdit::copyAvailable, actionCut, &QAction::setEnabled);
actionCopy->setEnabled(false);
connect(textEdit, &QTextEdit::copyAvailable, actionCopy, &QAction::setEnabled);
connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &TextEdit::clipboardDataChanged);
textEdit->setFocus();
setCurrentFileName(QString());
}
void TextEdit::closeEvent(QCloseEvent *e)
{
if (maybeSave())
e->accept();
else
e->ignore();
}
void TextEdit::setupFileActions()
{
QToolBar *tb = addToolBar(tr("File Actions"));
QMenu *menu = menuBar()->addMenu(tr("&File"));
const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(rsrcPath + "/filenew.png"));
QAction *a = menu->addAction(newIcon, tr("&New"), this, &TextEdit::fileNew);
tb->addAction(a);
a->setPriority(QAction::LowPriority);
a->setShortcut(QKeySequence::New);
const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(rsrcPath + "/fileopen.png"));
a = menu->addAction(openIcon, tr("&Open..."), this, &TextEdit::fileOpen);
a->setShortcut(QKeySequence::Open);
tb->addAction(a);
menu->addSeparator();
const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(rsrcPath + "/filesave.png"));
actionSave = menu->addAction(saveIcon, tr("&Save"), this, &TextEdit::fileSave);
actionSave->setShortcut(QKeySequence::Save);
actionSave->setEnabled(false);
tb->addAction(actionSave);
a = menu->addAction(tr("Save &As..."), this, &TextEdit::fileSaveAs);
a->setPriority(QAction::LowPriority);
menu->addSeparator();
const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png"));
a = menu->addAction(printIcon, tr("&Print..."), this, &TextEdit::filePrint);
a->setPriority(QAction::LowPriority);
a->setShortcut(QKeySequence::Print);
tb->addAction(a);
const QIcon filePrintIcon = QIcon::fromTheme("fileprint", QIcon(rsrcPath + "/fileprint.png"));
menu->addAction(filePrintIcon, tr("Print Preview..."), this, &TextEdit::filePrintPreview);
const QIcon exportPdfIcon = QIcon::fromTheme("exportpdf", QIcon(rsrcPath + "/exportpdf.png"));
a = menu->addAction(exportPdfIcon, tr("&Export PDF..."), this, &TextEdit::filePrintPdf);
a->setPriority(QAction::LowPriority);
a->setShortcut(Qt::CTRL + Qt::Key_D);
tb->addAction(a);
menu->addSeparator();
a = menu->addAction(tr("&Quit"), this, &QWidget::close);
a->setShortcut(Qt::CTRL + Qt::Key_Q);
}
void TextEdit::setupEditActions()
{
QToolBar *tb = addToolBar(tr("Edit Actions"));
QMenu *menu = menuBar()->addMenu(tr("&Edit"));
const QIcon undoIcon = QIcon::fromTheme("edit-undo", QIcon(rsrcPath + "/editundo.png"));
actionUndo = menu->addAction(undoIcon, tr("&Undo"), textEdit, &QTextEdit::undo);
actionUndo->setShortcut(QKeySequence::Undo);
tb->addAction(actionUndo);
const QIcon redoIcon = QIcon::fromTheme("edit-redo", QIcon(rsrcPath + "/editredo.png"));
actionRedo = menu->addAction(redoIcon, tr("&Redo"), textEdit, &QTextEdit::redo);
actionRedo->setPriority(QAction::LowPriority);
actionRedo->setShortcut(QKeySequence::Redo);
tb->addAction(actionRedo);
menu->addSeparator();
const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(rsrcPath + "/editcut.png"));
actionCut = menu->addAction(cutIcon, tr("Cu&t"), textEdit, &QTextEdit::cut);
actionCut->setPriority(QAction::LowPriority);
actionCut->setShortcut(QKeySequence::Cut);
tb->addAction(actionCut);
const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(rsrcPath + "/editcopy.png"));
actionCopy = menu->addAction(copyIcon, tr("&Copy"), textEdit, &QTextEdit::copy);
actionCopy->setPriority(QAction::LowPriority);
actionCopy->setShortcut(QKeySequence::Copy);
tb->addAction(actionCopy);
const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon(rsrcPath + "/editpaste.png"));
actionPaste = menu->addAction(pasteIcon, tr("&Paste"), textEdit, &QTextEdit::paste);
actionPaste->setPriority(QAction::LowPriority);
actionPaste->setShortcut(QKeySequence::Paste);
tb->addAction(actionPaste);
if (const QMimeData *md = QApplication::clipboard()->mimeData())
actionPaste->setEnabled(md->hasText());
}
void TextEdit::setupTextActions()
{
QToolBar *tb = addToolBar(tr("Format Actions"));
QMenu *menu = menuBar()->addMenu(tr("F&ormat"));
const QIcon boldIcon = QIcon::fromTheme("format-text-bold", QIcon(rsrcPath + "/textbold.png"));
actionTextBold = menu->addAction(boldIcon, tr("&Bold"), this, &TextEdit::textBold);
actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B);
actionTextBold->setPriority(QAction::LowPriority);
QFont bold;
bold.setBold(true);
actionTextBold->setFont(bold);
tb->addAction(actionTextBold);
actionTextBold->setCheckable(true);
const QIcon italicIcon = QIcon::fromTheme("format-text-italic", QIcon(rsrcPath + "/textitalic.png"));
actionTextItalic = menu->addAction(italicIcon, tr("&Italic"), this, &TextEdit::textItalic);
actionTextItalic->setPriority(QAction::LowPriority);
actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I);
QFont italic;
italic.setItalic(true);
actionTextItalic->setFont(italic);
tb->addAction(actionTextItalic);
actionTextItalic->setCheckable(true);
const QIcon underlineIcon = QIcon::fromTheme("format-text-underline", QIcon(rsrcPath + "/textunder.png"));
actionTextUnderline = menu->addAction(underlineIcon, tr("&Underline"), this, &TextEdit::textUnderline);
actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U);
actionTextUnderline->setPriority(QAction::LowPriority);
QFont underline;
underline.setUnderline(true);
actionTextUnderline->setFont(underline);
tb->addAction(actionTextUnderline);
actionTextUnderline->setCheckable(true);
menu->addSeparator();
const QIcon leftIcon = QIcon::fromTheme("format-justify-left", QIcon(rsrcPath + "/textleft.png"));
actionAlignLeft = new QAction(leftIcon, tr("&Left"), this);
actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L);
actionAlignLeft->setCheckable(true);
actionAlignLeft->setPriority(QAction::LowPriority);
const QIcon centerIcon = QIcon::fromTheme("format-justify-center", QIcon(rsrcPath + "/textcenter.png"));
actionAlignCenter = new QAction(centerIcon, tr("C&enter"), this);
actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E);
actionAlignCenter->setCheckable(true);
actionAlignCenter->setPriority(QAction::LowPriority);
const QIcon rightIcon = QIcon::fromTheme("format-justify-right", QIcon(rsrcPath + "/textright.png"));
actionAlignRight = new QAction(rightIcon, tr("&Right"), this);
actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R);
actionAlignRight->setCheckable(true);
actionAlignRight->setPriority(QAction::LowPriority);
const QIcon fillIcon = QIcon::fromTheme("format-justify-fill", QIcon(rsrcPath + "/textjustify.png"));
actionAlignJustify = new QAction(fillIcon, tr("&Justify"), this);
actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J);
actionAlignJustify->setCheckable(true);
actionAlignJustify->setPriority(QAction::LowPriority);
const QIcon indentMoreIcon = QIcon::fromTheme("format-indent-more", QIcon(rsrcPath + "/format-indent-more.png"));
actionIndentMore = menu->addAction(indentMoreIcon, tr("&Indent"), this, &TextEdit::indent);
actionIndentMore->setShortcut(Qt::CTRL + Qt::Key_BracketRight);
actionIndentMore->setPriority(QAction::LowPriority);
const QIcon indentLessIcon = QIcon::fromTheme("format-indent-less", QIcon(rsrcPath + "/format-indent-less.png"));
actionIndentLess = menu->addAction(indentLessIcon, tr("&Unindent"), this, &TextEdit::unindent);
actionIndentLess->setShortcut(Qt::CTRL + Qt::Key_BracketLeft);
actionIndentLess->setPriority(QAction::LowPriority);
// Make sure the alignLeft is always left of the alignRight
QActionGroup *alignGroup = new QActionGroup(this);
connect(alignGroup, &QActionGroup::triggered, this, &TextEdit::textAlign);
if (QApplication::isLeftToRight()) {
alignGroup->addAction(actionAlignLeft);
alignGroup->addAction(actionAlignCenter);
alignGroup->addAction(actionAlignRight);
} else {
alignGroup->addAction(actionAlignRight);
alignGroup->addAction(actionAlignCenter);
alignGroup->addAction(actionAlignLeft);
}
alignGroup->addAction(actionAlignJustify);
tb->addActions(alignGroup->actions());
menu->addActions(alignGroup->actions());
tb->addAction(actionIndentMore);
tb->addAction(actionIndentLess);
menu->addAction(actionIndentMore);
menu->addAction(actionIndentLess);
menu->addSeparator();
QPixmap pix(16, 16);
pix.fill(Qt::black);
actionTextColor = menu->addAction(pix, tr("&Color..."), this, &TextEdit::textColor);
tb->addAction(actionTextColor);
menu->addSeparator();
const QIcon checkboxIcon = QIcon::fromTheme("status-checkbox-checked", QIcon(rsrcPath + "/checkbox-checked.png"));
actionToggleCheckState = menu->addAction(checkboxIcon, tr("Chec&ked"), this, &TextEdit::setChecked);
actionToggleCheckState->setShortcut(Qt::CTRL + Qt::Key_K);
actionToggleCheckState->setCheckable(true);
actionToggleCheckState->setPriority(QAction::LowPriority);
tb->addAction(actionToggleCheckState);
tb = addToolBar(tr("Format Actions"));
tb->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
addToolBarBreak(Qt::TopToolBarArea);
addToolBar(tb);
comboStyle = new QComboBox(tb);
tb->addWidget(comboStyle);
comboStyle->addItem("Standard");
comboStyle->addItem("Bullet List (Disc)");
comboStyle->addItem("Bullet List (Circle)");
comboStyle->addItem("Bullet List (Square)");
comboStyle->addItem("Task List (Unchecked)");
comboStyle->addItem("Task List (Checked)");
comboStyle->addItem("Ordered List (Decimal)");
comboStyle->addItem("Ordered List (Alpha lower)");
comboStyle->addItem("Ordered List (Alpha upper)");
comboStyle->addItem("Ordered List (Roman lower)");
comboStyle->addItem("Ordered List (Roman upper)");
comboStyle->addItem("Heading 1");
comboStyle->addItem("Heading 2");
comboStyle->addItem("Heading 3");
comboStyle->addItem("Heading 4");
comboStyle->addItem("Heading 5");
comboStyle->addItem("Heading 6");
connect(comboStyle, QOverload<int>::of(&QComboBox::activated), this, &TextEdit::textStyle);
comboFont = new QFontComboBox(tb);
tb->addWidget(comboFont);
connect(comboFont, &QComboBox::textActivated, this, &TextEdit::textFamily);
comboSize = new QComboBox(tb);
comboSize->setObjectName("comboSize");
tb->addWidget(comboSize);
comboSize->setEditable(true);
const QList<int> standardSizes = QFontDatabase::standardSizes();
for (int size : standardSizes)
comboSize->addItem(QString::number(size));
comboSize->setCurrentIndex(standardSizes.indexOf(QApplication::font().pointSize()));
connect(comboSize, &QComboBox::textActivated, this, &TextEdit::textSize);
}
bool TextEdit::load(const QString &f)
{
if (!QFile::exists(f))
return false;
QFile file(f);
if (!file.open(QFile::ReadOnly))
return false;
QByteArray data = file.readAll();
QTextCodec *codec = Qt::codecForHtml(data);
QString str = codec->toUnicode(data);
if (Qt::mightBeRichText(str)) {
QUrl baseUrl = (f.front() == QLatin1Char(':') ? QUrl(f) : QUrl::fromLocalFile(f)).adjusted(QUrl::RemoveFilename);
textEdit->document()->setBaseUrl(baseUrl);
textEdit->setHtml(str);
} else {
QMimeDatabase db;
if (db.mimeTypeForFileNameAndData(f, data).name() == QLatin1String("text/markdown"))
textEdit->setMarkdown(QString::fromUtf8(data));
else
textEdit->setPlainText(QString::fromUtf8(data));
}
setCurrentFileName(f);
return true;
}
bool TextEdit::maybeSave()
{
if (!textEdit->document()->isModified())
return true;
const QMessageBox::StandardButton ret =
QMessageBox::warning(this, QCoreApplication::applicationName(),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
if (ret == QMessageBox::Save)
return fileSave();
else if (ret == QMessageBox::Cancel)
return false;
return true;
}
void TextEdit::setCurrentFileName(const QString &fileName)
{
this->fileName = fileName;
textEdit->document()->setModified(false);
QString shownName;
if (fileName.isEmpty())
shownName = "untitled.txt";
else
shownName = QFileInfo(fileName).fileName();
setWindowTitle(tr("%1[*] - %2").arg(shownName, QCoreApplication::applicationName()));
setWindowModified(false);
}
void TextEdit::fileNew()
{
if (maybeSave()) {
textEdit->clear();
setCurrentFileName(QString());
}
}
void TextEdit::fileOpen()
{
QFileDialog fileDialog(this, tr("Open File..."));
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setFileMode(QFileDialog::ExistingFile);
fileDialog.setMimeTypeFilters(QStringList()
#if QT_CONFIG(texthtmlparser)
<< "text/html"
#endif
#if QT_CONFIG(textmarkdownreader)
<< "text/markdown"
#endif
<< "text/plain");
if (fileDialog.exec() != QDialog::Accepted)
return;
const QString fn = fileDialog.selectedFiles().first();
if (load(fn))
statusBar()->showMessage(tr("Opened \"%1\"").arg(QDir::toNativeSeparators(fn)));
else
statusBar()->showMessage(tr("Could not open \"%1\"").arg(QDir::toNativeSeparators(fn)));
}
bool TextEdit::fileSave()
{
if (fileName.isEmpty())
return fileSaveAs();
if (fileName.startsWith(QStringLiteral(":/")))
return fileSaveAs();
QTextDocumentWriter writer(fileName);
bool success = writer.write(textEdit->document());
if (success) {
textEdit->document()->setModified(false);
statusBar()->showMessage(tr("Wrote \"%1\"").arg(QDir::toNativeSeparators(fileName)));
} else {
statusBar()->showMessage(tr("Could not write to file \"%1\"")
.arg(QDir::toNativeSeparators(fileName)));
}
return success;
}
bool TextEdit::fileSaveAs()
{
QFileDialog fileDialog(this, tr("Save as..."));
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
QStringList mimeTypes;
mimeTypes << "text/plain"
<< "application/vnd.oasis.opendocument.text"
<< "text/markdown"
<< "text/html";
fileDialog.setMimeTypeFilters(mimeTypes);
fileDialog.setDefaultSuffix("odt");
if (fileDialog.exec() != QDialog::Accepted)
return false;
const QString fn = fileDialog.selectedFiles().first();
setCurrentFileName(fn);
return fileSave();
}
void TextEdit::filePrint()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
QPrinter printer(QPrinter::HighResolution);
QPrintDialog *dlg = new QPrintDialog(&printer, this);
if (textEdit->textCursor().hasSelection())
dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection);
dlg->setWindowTitle(tr("Print Document"));
if (dlg->exec() == QDialog::Accepted)
textEdit->print(&printer);
delete dlg;
#endif
}
void TextEdit::filePrintPreview()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
QPrinter printer(QPrinter::HighResolution);
QPrintPreviewDialog preview(&printer, this);
connect(&preview, &QPrintPreviewDialog::paintRequested, this, &TextEdit::printPreview);
preview.exec();
#endif
}
void TextEdit::printPreview(QPrinter *printer)
{
textEdit->print(printer);
}
void TextEdit::filePrintPdf()
{
QFileDialog fileDialog(this, tr("Export PDF"));
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
fileDialog.setMimeTypeFilters(QStringList("application/pdf"));
fileDialog.setDefaultSuffix("pdf");
if (fileDialog.exec() != QDialog::Accepted)
return;
QString fileName = fileDialog.selectedFiles().first();
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(fileName);
textEdit->document()->print(&printer);
statusBar()->showMessage(tr("Exported \"%1\"")
.arg(QDir::toNativeSeparators(fileName)));
}
void TextEdit::textBold()
{
QTextCharFormat fmt;
fmt.setFontWeight(actionTextBold->isChecked() ? QFont::Bold : QFont::Normal);
mergeFormatOnWordOrSelection(fmt);
}
void TextEdit::textUnderline()
{
QTextCharFormat fmt;
fmt.setFontUnderline(actionTextUnderline->isChecked());
mergeFormatOnWordOrSelection(fmt);
}
void TextEdit::textItalic()
{
QTextCharFormat fmt;
fmt.setFontItalic(actionTextItalic->isChecked());
mergeFormatOnWordOrSelection(fmt);
}
void TextEdit::textFamily(const QString &f)
{
QTextCharFormat fmt;
fmt.setFontFamily(f);
mergeFormatOnWordOrSelection(fmt);
}
void TextEdit::textSize(const QString &p)
{
qreal pointSize = p.toFloat();
if (p.toFloat() > 0) {
QTextCharFormat fmt;
fmt.setFontPointSize(pointSize);
mergeFormatOnWordOrSelection(fmt);
}
}
void TextEdit::textStyle(int styleIndex)
{
QTextCursor cursor = textEdit->textCursor();
QTextListFormat::Style style = QTextListFormat::ListStyleUndefined;
QTextBlockFormat::MarkerType marker = QTextBlockFormat::MarkerType::NoMarker;
switch (styleIndex) {
case 1:
style = QTextListFormat::ListDisc;
break;
case 2:
style = QTextListFormat::ListCircle;
break;
case 3:
style = QTextListFormat::ListSquare;
break;
case 4:
if (cursor.currentList())
style = cursor.currentList()->format().style();
else
style = QTextListFormat::ListDisc;
marker = QTextBlockFormat::MarkerType::Unchecked;
break;
case 5:
if (cursor.currentList())
style = cursor.currentList()->format().style();
else
style = QTextListFormat::ListDisc;
marker = QTextBlockFormat::MarkerType::Checked;
break;
case 6:
style = QTextListFormat::ListDecimal;
break;
case 7:
style = QTextListFormat::ListLowerAlpha;
break;
case 8:
style = QTextListFormat::ListUpperAlpha;
break;
case 9:
style = QTextListFormat::ListLowerRoman;
break;
case 10:
style = QTextListFormat::ListUpperRoman;
break;
default:
break;
}
cursor.beginEditBlock();
QTextBlockFormat blockFmt = cursor.blockFormat();
if (style == QTextListFormat::ListStyleUndefined) {
blockFmt.setObjectIndex(-1);
int headingLevel = styleIndex >= 11 ? styleIndex - 11 + 1 : 0; // H1 to H6, or Standard
blockFmt.setHeadingLevel(headingLevel);
cursor.setBlockFormat(blockFmt);
int sizeAdjustment = headingLevel ? 4 - headingLevel : 0; // H1 to H6: +3 to -2
QTextCharFormat fmt;
fmt.setFontWeight(headingLevel ? QFont::Bold : QFont::Normal);
fmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment);
cursor.select(QTextCursor::LineUnderCursor);
cursor.mergeCharFormat(fmt);
textEdit->mergeCurrentCharFormat(fmt);
} else {
blockFmt.setMarker(marker);
cursor.setBlockFormat(blockFmt);
QTextListFormat listFmt;
if (cursor.currentList()) {
listFmt = cursor.currentList()->format();
} else {
listFmt.setIndent(blockFmt.indent() + 1);
blockFmt.setIndent(0);
cursor.setBlockFormat(blockFmt);
}
listFmt.setStyle(style);
cursor.createList(listFmt);
}
cursor.endEditBlock();
}
void TextEdit::textColor()
{
QColor col = QColorDialog::getColor(textEdit->textColor(), this);
if (!col.isValid())
return;
QTextCharFormat fmt;
fmt.setForeground(col);
mergeFormatOnWordOrSelection(fmt);
colorChanged(col);
}
void TextEdit::textAlign(QAction *a)
{
if (a == actionAlignLeft)
textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
else if (a == actionAlignCenter)
textEdit->setAlignment(Qt::AlignHCenter);
else if (a == actionAlignRight)
textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
else if (a == actionAlignJustify)
textEdit->setAlignment(Qt::AlignJustify);
}
void TextEdit::setChecked(bool checked)
{
textStyle(checked ? 5 : 4);
}
void TextEdit::indent()
{
modifyIndentation(1);
}
void TextEdit::unindent()
{
modifyIndentation(-1);
}
void TextEdit::modifyIndentation(int amount)
{
QTextCursor cursor = textEdit->textCursor();
cursor.beginEditBlock();
if (cursor.currentList()) {
QTextListFormat listFmt = cursor.currentList()->format();
// See whether the line above is the list we want to move this item into,
// or whether we need a new list.
QTextCursor above(cursor);
above.movePosition(QTextCursor::Up);
if (above.currentList() && listFmt.indent() + amount == above.currentList()->format().indent()) {
above.currentList()->add(cursor.block());
} else {
listFmt.setIndent(listFmt.indent() + amount);
cursor.createList(listFmt);
}
} else {
QTextBlockFormat blockFmt = cursor.blockFormat();
blockFmt.setIndent(blockFmt.indent() + amount);
cursor.setBlockFormat(blockFmt);
}
cursor.endEditBlock();
}
void TextEdit::currentCharFormatChanged(const QTextCharFormat &format)
{
fontChanged(format.font());
colorChanged(format.foreground().color());
}
void TextEdit::cursorPositionChanged()
{
alignmentChanged(textEdit->alignment());
QTextList *list = textEdit->textCursor().currentList();
if (list) {
switch (list->format().style()) {
case QTextListFormat::ListDisc:
comboStyle->setCurrentIndex(1);
break;
case QTextListFormat::ListCircle:
comboStyle->setCurrentIndex(2);
break;
case QTextListFormat::ListSquare:
comboStyle->setCurrentIndex(3);
break;
case QTextListFormat::ListDecimal:
comboStyle->setCurrentIndex(6);
break;
case QTextListFormat::ListLowerAlpha:
comboStyle->setCurrentIndex(7);
break;
case QTextListFormat::ListUpperAlpha:
comboStyle->setCurrentIndex(8);
break;
case QTextListFormat::ListLowerRoman:
comboStyle->setCurrentIndex(9);
break;
case QTextListFormat::ListUpperRoman:
comboStyle->setCurrentIndex(10);
break;
default:
comboStyle->setCurrentIndex(-1);
break;
}
switch (textEdit->textCursor().block().blockFormat().marker()) {
case QTextBlockFormat::MarkerType::NoMarker:
actionToggleCheckState->setChecked(false);
break;
case QTextBlockFormat::MarkerType::Unchecked:
comboStyle->setCurrentIndex(4);
actionToggleCheckState->setChecked(false);
break;
case QTextBlockFormat::MarkerType::Checked:
comboStyle->setCurrentIndex(5);
actionToggleCheckState->setChecked(true);
break;
}
} else {
int headingLevel = textEdit->textCursor().blockFormat().headingLevel();
comboStyle->setCurrentIndex(headingLevel ? headingLevel + 10 : 0);
}
}
void TextEdit::clipboardDataChanged()
{
if (const QMimeData *md = QApplication::clipboard()->mimeData())
actionPaste->setEnabled(md->hasText());
}
void TextEdit::about()
{
QMessageBox::about(this, tr("About"), tr("This example demonstrates Qt's "
"rich text editing facilities in action, providing an example "
"document for you to experiment with."));
}
void TextEdit::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
{
QTextCursor cursor = textEdit->textCursor();
if (!cursor.hasSelection())
cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeCharFormat(format);
textEdit->mergeCurrentCharFormat(format);
}
void TextEdit::fontChanged(const QFont &f)
{
comboFont->setCurrentIndex(comboFont->findText(QFontInfo(f).family()));
comboSize->setCurrentIndex(comboSize->findText(QString::number(f.pointSize())));
actionTextBold->setChecked(f.bold());
actionTextItalic->setChecked(f.italic());
actionTextUnderline->setChecked(f.underline());
}
void TextEdit::colorChanged(const QColor &c)
{
QPixmap pix(16, 16);
pix.fill(c);
actionTextColor->setIcon(pix);
}
void TextEdit::alignmentChanged(Qt::Alignment a)
{
if (a & Qt::AlignLeft)
actionAlignLeft->setChecked(true);
else if (a & Qt::AlignHCenter)
actionAlignCenter->setChecked(true);
else if (a & Qt::AlignRight)
actionAlignRight->setChecked(true);
else if (a & Qt::AlignJustify)
actionAlignJustify->setChecked(true);
}
总结
该例子就是一个富文本编辑器。但是没有表格的按钮,用起来也不是那么方便。先当做源码库保存。在Qt的example下,有html和md文件可以阅读,本文就是翻译的这个资料。