Overview of Qt Text Editing Widgets
Qt provides three primary text editing components, each designed for specific use cases:
- QLineEdit – A single-line text input widget suitable for forms, search boxes, and simple data entry.
- QTextEdit – A multi-line rich text editor supporting formatted text, images, tables, and other embedded content.
- QPlainTextEdit – A multi-line plain text editor optimized for handling large amounts of unformatted text.
Inheritance Hierarchy
All three components inherit from QWidget. Both QTextEdit and QPlainTextEdit derive from QAbstractScrollArea, providing built-in scrolling capabilities.
Feature Comparison
| Component | Line Support | Content Type | Rich Text | Performance |
|---|---|---|---|---|
| QLineEdit | Single line | Plain text | No | High |
| QTextEdit | Multi-line | Rich text | Yes | Medium |
| QPlainTextEdit | Multi-line | Plain text | No | High |
Practical Demonstration
The following example illustrates how each component handles text and embedded content differently:
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, m_singleLineEditor(this)
, m_plainTextEditor(this)
, m_richTextEditor(this)
{
setupUi();
}
void MainWindow::setupUi()
{
setWindowSize(600, 420);
configureSingleLineEdit();
configurePlainTextEdit();
configureRichTextEdit();
}
void MainWindow::setWindowSize(int width, int height)
{
resize(width, height);
}
void MainWindow::configureSingleLineEdit()
{
m_singleLineEditor.setGeometry(20, 20, 560, 100);
m_singleLineEditor.setText("QLineEdit Demo");
}
void MainWindow::configurePlainTextEdit()
{
m_plainTextEditor.setGeometry(20, 130, 560, 130);
m_plainTextEditor.appendPlainText("QPlainTextEdit Example");
m_plainTextEditor.appendPlainText("<img src=\"image.png\" />");
}
void MainWindow::configureRichTextEdit()
{
m_richTextEditor.setGeometry(20, 270, 560, 130);
m_richTextEditor.appendPlainText("QTextEdit Example");
m_richTextEditor.appendHtml("<img src=\"image.png\" />");
}The key difference is that QTextEdit renders HTML content as actual images, while QPlainTextEdit displays the HTML markup as literal text.
Building a Simple Notepad Application
A practical text editor requires menu bars, toolbars, and status bars. Below is a complete implementation:
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPlainTextEdit>
#include <QLabel>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QToolBar>
#include <QStatusBar>
class NotepadWindow : public QMainWindow
{
Q_OBJECT
public:
static NotepadWindow* create();
~NotepadWindow();
private:
NotepadWindow(QWidget *parent = nullptr);
bool initializeComponents();
bool setupMenuBar();
bool setupToolBar();
bool setupStatusBar();
bool setupEditorArea();
bool createFileMenu(QMenuBar* menuBar);
bool createEditMenu(QMenuBar* menuBar);
bool createFormatMenu(QMenuBar* menuBar);
bool createViewMenu(QMenuBar* menuBar);
bool createHelpMenu(QMenuBar* menuBar);
bool createToolBarActions(QToolBar* toolBar);
bool createAction(QAction*& action, const QString& label, int shortcutKey);
bool createAction(QAction*& action, const QString& tooltip, const QString& iconPath);
QPlainTextEdit* m_editor;
QLabel* m_cursorPositionLabel;
};
#endifMainWindow.cpp
#include "MainWindow.h"
NotepadWindow::NotepadWindow(QWidget *parent)
: QMainWindow(parent)
, m_editor(new QPlainTextEdit(this))
, m_cursorPositionLabel(new QLabel(this))
{
}
NotepadWindow* NotepadWindow::create()
{
NotepadWindow* window = new NotepadWindow();
if (!window || !window->initializeComponents()) {
delete window;
return nullptr;
}
return window;
}
bool NotepadWindow::initializeComponents()
{
return setupMenuBar() &&
setupToolBar() &&
setupStatusBar() &&
setupEditorArea();
}
bool NotepadWindow::setupMenuBar()
{
QMenuBar* menuBar = this->menuBar();
return createFileMenu(menuBar) &&
createEditMenu(menuBar) &&
createFormatMenu(menuBar) &&
createViewMenu(menuBar) &&
createHelpMenu(menuBar);
}
bool NotepadWindow::setupToolBar()
{
QToolBar* toolBar = addToolBar("MainToolbar");
toolBar->setMovable(false);
toolBar->setFloatable(false);
toolBar->setIconSize(QSize(16, 16));
return createToolBarActions(toolBar);
}
bool NotepadWindow::setupStatusBar()
{
QStatusBar* status = statusBar();
m_cursorPositionLabel->setMinimumWidth(200);
m_cursorPositionLabel->setAlignment(Qt::AlignHCenter);
m_cursorPositionLabel->setText("Ln: 1 Col: 1");
QLabel* authorLabel = new QLabel("Notepad Demo", this);
authorLabel->setMinimumWidth(200);
authorLabel->setAlignment(Qt::AlignHCenter);
status->addPermanentWidget(new QLabel());
status->addPermanentWidget(m_cursorPositionLabel);
status->addPermanentWidget(authorLabel);
return true;
}
bool NotepadWindow::setupEditorArea()
{
setCentralWidget(m_editor);
return true;
}
bool NotepadWindow::createFileMenu(QMenuBar* menuBar)
{
QMenu* fileMenu = new QMenu("File(&F)");
QAction* act = nullptr;
if (!createAction(act, "New(&N)", Qt::CTRL + Qt::Key_N)) return false;
fileMenu->addAction(act);
fileMenu->addSeparator();
if (!createAction(act, "Open(&O)...", Qt::CTRL + Qt::Key_O)) return false;
fileMenu->addAction(act);
fileMenu->addSeparator();
if (!createAction(act, "Save(&S)", Qt::CTRL + Qt::Key_S)) return false;
fileMenu->addAction(act);
fileMenu->addSeparator();
if (!createAction(act, "Save As(&A)...", 0)) return false;
fileMenu->addAction(act);
fileMenu->addSeparator();
if (!createAction(act, "Print(&P)...", Qt::CTRL + Qt::Key_P)) return false;
fileMenu->addAction(act);
fileMenu->addSeparator();
if (!createAction(act, "Exit(&X)", 0)) return false;
fileMenu->addAction(act);
menuBar->addMenu(fileMenu);
return true;
}
bool NotepadWindow::createEditMenu(QMenuBar* menuBar)
{
QMenu* editMenu = new QMenu("Edit(&E)");
QAction* act = nullptr;
if (!createAction(act, "Undo(&U)", Qt::CTRL + Qt::Key_Z)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Redo(&R)", Qt::CTRL + Qt::Key_Y)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Cut(&T)", Qt::CTRL + Qt::Key_X)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Copy(&C)", Qt::CTRL + Qt::Key_C)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Paste(&P)", Qt::CTRL + Qt::Key_V)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Delete(&L)", Qt::Key_Delete)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Find(&F)...", Qt::CTRL + Qt::Key_F)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Replace(&R)...", Qt::CTRL + Qt::Key_H)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Go To(&G)", Qt::CTRL + Qt::Key_G)) return false;
editMenu->addAction(act);
editMenu->addSeparator();
if (!createAction(act, "Select All(&A)", Qt::CTRL + Qt::Key_A)) return false;
editMenu->addAction(act);
menuBar->addMenu(editMenu);
return true;
}
bool NotepadWindow::createFormatMenu(QMenuBar* menuBar)
{
QMenu* formatMenu = new QMenu("Format(&O)");
QAction* act = nullptr;
if (!createAction(act, "Word Wrap(&W)", 0)) return false;
formatMenu->addAction(act);
formatMenu->addSeparator();
if (!createAction(act, "Font(&F)...", 0)) return false;
formatMenu->addAction(act);
menuBar->addMenu(formatMenu);
return true;
}
bool NotepadWindow::createViewMenu(QMenuBar* menuBar)
{
QMenu* viewMenu = new QMenu("View(&V)");
QAction* act = nullptr;
if (!createAction(act, "Toolbar(&T)", 0)) return false;
viewMenu->addAction(act);
viewMenu->addSeparator();
if (!createAction(act, "Status Bar(&S)", 0)) return false;
viewMenu->addAction(act);
menuBar->addMenu(viewMenu);
return true;
}
bool NotepadWindow::createHelpMenu(QMenuBar* menuBar)
{
QMenu* helpMenu = new QMenu("Help(&H)");
QAction* act = nullptr;
if (!createAction(act, "User Guide", 0)) return false;
helpMenu->addAction(act);
helpMenu->addSeparator();
if (!createAction(act, "About Notepad...", 0)) return false;
helpMenu->addAction(act);
menuBar->addMenu(helpMenu);
return true;
}
bool NotepadWindow::createToolBarActions(QToolBar* toolBar)
{
QAction* act = nullptr;
if (!createAction(act, "New", ":/icons/new.png")) return false;
toolBar->addAction(act);
if (!createAction(act, "Open", ":/icons/open.png")) return false;
toolBar->addAction(act);
if (!createAction(act, "Save", ":/icons/save.png")) return false;
toolBar->addAction(act);
if (!createAction(act, "Save As", ":/icons/saveas.png")) return false;
toolBar->addAction(act);
if (!createAction(act, "Print", ":/icons/print.png")) return false;
toolBar->addAction(act);
if (!createAction(act, "Undo", ":/icons/undo.png")) return false;
toolBar->addAction(act);
if (!createAction(act, "Redo", ":/icons/redo.png")) return false;
toolBar->addAction(act);
return true;
}
bool NotepadWindow::createAction(QAction*& action, const QString& label, int shortcutKey)
{
action = new QAction(label, this);
if (!action) return false;
if (shortcutKey != 0) {
action->setShortcut(QKeySequence(shortcutKey));
}
return true;
}
bool NotepadWindow::createAction(QAction*& action, const QString& tooltip, const QString& iconPath)
{
action = new QAction(this);
if (!action) return false;
action->setToolTip(tooltip);
action->setIcon(QIcon(iconPath));
return true;
}
NotepadWindow::~NotepadWindow()
{
}main.cpp
#include <QApplication>
#include "MainWindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
NotepadWindow* window = NotepadWindow::create();
if (!window) {
return -1;
}
window->show();
return app.exec();
}Key Characteristics of Qt Text Widgets
QLineEditis ideal for simple input fields such as usernames, passwords, and search queries.QTextEditsupports rich text formatting including HTML tags, making it suitable for document editors and chat applications.QPlainTextEditoffers superior performance for large plain text files, making it the preferred choice for code editors and log viewers.
All three widgets provide built-in support for standard editing operations including cut, copy, paste, undo, redo, and drag-and-drop functionality.