【初心者向け】Qt GUI プログラミング:QTextDocument::undoRedoEnabled で簡単に元に戻す/やり直す機能を実装


QTextDocument::undoRedoEnabled は、Qt GUI におけるテキスト編集において重要な役割を果たすプロパティです。このプロパティは、テキストドキュメントにおける元に戻す/やり直す機能を有効化/無効化するために使用されます。

機能

  • false に設定すると、元に戻す/やり直す機能が無効化されます。
  • true に設定すると、テキストドキュメントに対する編集操作を元に戻したりやり直したりすることができます。

利点

  • 複雑な編集作業を効率化します。
  • エラー時の修正を容易にします。
  • ユーザー操作の柔軟性を高めます。

使用方法

QTextDocument *document = new QTextDocument;

// 元に戻す/やり直す機能を有効化する
document->setUndoRedoEnabled(true);

// テキスト編集を行う
document->setText("Hello, World!");

// 編集を元に戻す
document->undo();

// 編集をやり直す
document->redo();

注意点

  • 特定の編集操作は、元に戻す/やり直す機能の対象にならない場合があります。
  • 元に戻す/やり直す機能は、メモリ容量を消費します。そのため、大量の編集操作を行う場合は、パフォーマンスに影響を与える可能性があります。
  • コードエディタ
  • ワープロソフト
  • リッチテキストエディタ


例1:元に戻す/やり直す機能の有効化/無効化

#include <QApplication>
#include <QTextDocument>
#include <QTextEdit>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // テキストドキュメントを作成
  QTextDocument document;

  // テキスト編集を行う
  document.setText("Hello, World!");

  // テキストエディタを作成
  QTextEdit textEdit;

  // テキストドキュメントをテキストエディタに設定
  textEdit.setDocument(&document);

  // 元に戻す/やり直す機能を有効化
  document.setUndoRedoEnabled(true);

  // テキストエディタを表示
  textEdit.show();

  return app.exec();
}
#include <QApplication>
#include <QTextDocument>
#include <QTextEdit>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // テキストドキュメントを作成
  QTextDocument document;

  // テキスト編集を行う
  document.setText("Hello, World!");

  // テキストエディタを作成
  QTextEdit textEdit;

  // テキストドキュメントをテキストエディタに設定
  textEdit.setDocument(&document);

  // 元に戻す/やり直す機能を有効化
  document.setUndoRedoEnabled(true);

  // テキストエディタを表示
  textEdit.show();

  // 編集を元に戻す
  document.undo();

  // 編集をやり直す
  document.redo();

  return app.exec();
}
  • コードを実行するには、Qt ライブラリをインストールする必要があります。
  • 上記のコードは、Qt Creator 4.15.2 を使用してコンパイルおよび実行することを想定しています。


以下に、QTextDocument::undoRedoEnabled の代替方法として検討すべきいくつかの方法をご紹介します。

QHistory クラスの使用

QHistory クラスは、過去の操作履歴を保存および管理するためのクラスです。このクラスを使用して、テキスト編集操作を個別に追跡し、元に戻す/やり直す機能を実装することができます。

#include <QApplication>
#include <QHistory>
#include <QTextDocument>
#include <QTextEdit>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // テキストドキュメントを作成
  QTextDocument document;

  // テキスト編集を行う
  document.setText("Hello, World!");

  // テキストエディタを作成
  QTextEdit textEdit;

  // テキストドキュメントをテキストエディタに設定
  textEdit.setDocument(&document);

  // 操作履歴を作成
  QHistory history;

  // テキスト編集操作を履歴に追加
  connect(&textEdit, &QTextEdit::textChanged, &history, &QHistory::add);

  // 元に戻す/やり直す機能を実装
  QPushButton *undoButton = new QPushButton("元に戻す");
  QPushButton *redoButton = new QPushButton("やり直す");

  connect(undoButton, &QPushButton::clicked, [&]() {
    if (history.canGoBack()) {
      history.goBack();
      textEdit.document()->setPlainText(history.current().data().toString());
    }
  });

  connect(redoButton, &QPushButton::clicked, [&]() {
    if (history.canGoForward()) {
      history.goForward();
      textEdit.document()->setPlainText(history.current().data().toString());
    }
  });

  // ボタンをレイアウト
  QHBoxLayout *buttonLayout = new QHBoxLayout;
  buttonLayout->addWidget(undoButton);
  buttonLayout->addWidget(redoButton);

  // テキストエディタとボタンをレイアウト
  QVBoxLayout *mainLayout = new QVBoxLayout;
  mainLayout->addWidget(&textEdit);
  mainLayout->addLayout(buttonLayout);

  // ウィジェットを作成
  QWidget widget;
  widget.setLayout(mainLayout);

  // ウィジェットを表示
  widget.show();

  return app.exec();
}

カスタムスタックの使用

カスタムスタックを使用して、過去のテキスト状態を保存することができます。編集操作ごとにスタックに新しい状態を追加し、元に戻す/やり直す操作によってスタック内の状態を上下に移動することができます。

#include <QApplication>
#include <QStack>
#include <QTextDocument>
#include <QTextEdit>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // テキストドキュメントを作成
  QTextDocument document;

  // テキスト編集を行う
  document.setText("Hello, World!");

  // テキストエディタを作成
  QTextEdit textEdit;

  // テキストドキュメントをテキストエディタに設定
  textEdit.setDocument(&document);

  // カスタムスタックを作成
  QStack<QString> textStack;
  textStack.push(document.toPlainText());

  // テキスト編集操作をスタックに保存
  connect(&textEdit, &QTextEdit::textChanged, [&]() {
    textStack.push(document.toPlainText());
  });

  // 元に戻す/やり直す機能を実装
  QPushButton *undoButton = new QPushButton("元に戻す");
  QPushButton *redoButton = new QPushButton("やり直す");

  connect(undoButton, &QPushButton::clicked, [&]() {
    if (!textStack.empty()) {
      textStack.pop();
      document.setPlainText(textStack.top());
    }
  });

  connect(redoButton, &QPushButton::clicked, [&]() {
    if (!textStack.empty()) {
      textStack.push(document.toPlainText());
      document.setPlainText(textStack.top());
    }
  });

  // ボタンをレイアウト
  QHBoxLayout *buttonLayout = new QHBoxLayout;
  button