質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

受付中

QTアプリケーションでのUndo/Redo

退会済みユーザー

退会済みユーザー

総合スコア0

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1回答

0評価

0クリップ

1190閲覧

投稿2020/02/27 11:43

前提・実現したいこと

QTアプリケーション上でUndo/Redoの機能を実装するためにQUndoStack,QUndoCommandクラスを使用し練習を行っています。

試しにChangeボタンを押した際にSpinBoxの数値の値をlineEditに反映するといったアプリケーションを作成し、Undoボタンを押下した際に前の値に戻りRedoボタンを押下した際には後の値に戻るといったプログラムを作成したのですが、私が作成したアプリケーションではUndo/Redoボタンを2回押下しないと値の変更がされないといった不具合が発生しています。

イメージ説明
①のスピンボックスで値を変更し③のChangeボタンを押下した際に②のlineEditのスピンボックスで選択した値が変更されるといったプログラムとなっております。
図の状態でUndoボタンを1度押下した際に4の値がlineEditに判明されてほしいのですが、2回押下しないと反映されずRedoする際にも2回押下しないと反映されないといった問題が発生しています。

どうにかして、1回のボタン押下で反映されるように修正したいのですがどうすれば良いのでしょうか。
ご指南頂けると幸甚に存じます。

該当のソースコード

C++

[main.cpp] #include "widget.h" #include <QApplication> #include <QUndoStack> int main(int argc, char *argv[]) { QApplication a(argc, argv); QUndoStack *m_undoStack = new QUndoStack; Widget w(m_undoStack); w.show(); return a.exec(); }

C++

[Widget.h] #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QUndoStack> #include <QUndoView> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QUndoStack *undoStack,QWidget *parent = 0); ~Widget(); protected: void closeEvent(QCloseEvent *) Q_DECL_OVERRIDE; public: void onChangeButtonClicked(); void changeDisplay(int value); public slots: void changeValueSpinBox(int value); private: Ui::Widget *ui; QUndoStack *m_undoStack; QUndoView *m_undoView; int m_value; QList<int> m_valueList; }; #endif // WIDGET_H

C++

[Widget.cpp] #include "widget.h" #include "ui_widget.h" #include "command.h" Widget::Widget(QUndoStack *undoStack,QWidget *parent) : QWidget(parent), ui(new Ui::Widget), m_undoStack(undoStack), m_undoView(new QUndoView(m_undoStack)) { ui->setupUi(this); connect(ui->undoButton,&QPushButton::clicked,m_undoStack,&QUndoStack::undo); connect(ui->redoButton,&QPushButton::clicked,m_undoStack,&QUndoStack::redo); connect(ui->changeButton,&QPushButton::clicked,this,&Widget::onChangeButtonClicked); connect(ui->spinBox,SIGNAL(valueChanged(int)),this,SLOT(changeValueSpinBox(int))); m_undoView->setWindowFlags(Qt::Dialog); m_undoView->show(); } Widget::~Widget() { delete ui; } void Widget::closeEvent(QCloseEvent *) { m_undoView->close(); } void Widget::onChangeButtonClicked() { qInfo("Click"); command *Command = new command(this,m_value,&m_valueList); m_undoStack->push(Command); } void Widget::changeValueSpinBox(int value) { qInfo("Value Change"); m_value = value; } void Widget::changeDisplay(int value) { ui->lineEdit->setText(QString::number(value)); }

C++

[command.h] #ifndef COMMAND_H #define COMMAND_H #include <QUndoCommand> class Widget; class command : public QUndoCommand { public: command(Widget *widget,const int value,QList<int> *valueList,QUndoCommand *parent = 0); public: void undo() Q_DECL_OVERRIDE; void redo() Q_DECL_OVERRIDE; private: Widget *m_widget; int m_value; QList<int> *m_valueList; }; #endif // COMMAND_H

C++

[command.cpp] #include "command.h" #include "widget.h" command::command(Widget *widget,const int value,QList<int> *valueList,QUndoCommand *parent): QUndoCommand(parent), m_widget(widget), m_value(value), m_valueList(valueList) { } void command::undo() { qInfo("UNDO"); if(m_valueList->isEmpty()) { return; } m_widget->changeDisplay(m_valueList->takeLast()); } void command::redo() { qInfo("REDO"); m_valueList->push_back(m_value); setText(QString("Value:%1").arg(m_value)); m_widget->changeDisplay(m_value); }
[widget.ui] <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Widget</class> <widget class="QWidget" name="Widget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>400</width> <height>300</height> </rect> </property> <property name="windowTitle"> <string>Widget</string> </property> <widget class="QPushButton" name="redoButton"> <property name="geometry"> <rect> <x>220</x> <y>120</y> <width>158</width> <height>32</height> </rect> </property> <property name="text"> <string>Redo</string> </property> </widget> <widget class="QPushButton" name="undoButton"> <property name="geometry"> <rect> <x>220</x> <y>60</y> <width>158</width> <height>32</height> </rect> </property> <property name="text"> <string>Undo</string> </property> </widget> <widget class="QLineEdit" name="lineEdit"> <property name="geometry"> <rect> <x>30</x> <y>140</y> <width>113</width> <height>21</height> </rect> </property> </widget> <widget class="QSpinBox" name="spinBox"> <property name="geometry"> <rect> <x>70</x> <y>70</y> <width>48</width> <height>24</height> </rect> </property> </widget> <widget class="QPushButton" name="changeButton"> <property name="geometry"> <rect> <x>230</x> <y>180</y> <width>113</width> <height>32</height> </rect> </property> <property name="text"> <string>Change</string> </property> </widget> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui>

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。