<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[QUndoCommand Update UI]]></title><description><![CDATA[<p dir="auto">Hi,</p>
<p dir="auto">What's the correct way to update the UI from a QUndoCommand?</p>
<p dir="auto">I have a QImage which can be drawn on to using a custom QWidget class, it actually draws a 40x40 pixel rectangle but that's not important:</p>
<pre><code>void assetEditor::drawPoint(const QPoint &amp;scaledPoint)
{
    QPainter painter(&amp;foregroundImage);

    /* Set the fill colour and no border */
    painter.setBrush(currentEditorState.paint.penColour);
    painter.setPen(QPen(currentEditorState.paint.penColour, currentEditorState.paint.penSize, Qt::NoPen, Qt::RoundCap, Qt::RoundJoin));

    /* Draw a 40x40 rectangle as the pixel */
    painter.drawRect( QRect( QPoint( (scaledPoint.x() * 40), (scaledPoint.y() * 40) ), QSize(40, 40) ) );
    update();
}
</code></pre>
<p dir="auto">Then on the mouse release event, the undo command is called:</p>
<pre><code>/* Scale the foreground down to the correct size to reduce storage on the undo stack */
QImage scaledDownForeground = scaleDownImage(foregroundImage);

undoStack-&gt;push(new assetEditorImageChange(currentEditorConfig.imageSize, &amp;foregroundImage, scaledDownForeground, undoStoreImage, &amp;currentEditorState, preUndoStoreEditorState, postUndoStoreEditorState));
</code></pre>
<p dir="auto">Note the max size of an image will be 16x16 pixels, so I figured it won't kill the memory to store a copy of the image in the undo stack.</p>
<p dir="auto">Undo command is then defined here:</p>
<pre><code>assetEditorImageChange::assetEditorImageChange(
            int imageHeight,
            QImage *passForegroundImage,
            const QImage &amp;newImageState,
            const QImage &amp;oldImageState,
            assetEditor::editorState *passCurrentEditorConfig,
            const assetEditor::editorState &amp;newConfigState,
            const assetEditor::editorState &amp;oldConfigState,
            QUndoCommand *parent)
    : QUndoCommand(parent),
      editorImageHeight(imageHeight),
      foregroundImage(passForegroundImage),
      oldImage(oldImageState),
      newImage(newImageState),
      editorConfig(passCurrentEditorConfig),
      oldConfig(newConfigState),
      newConfig(oldConfigState),
{
}

QImage assetEditorImageChange::scaleUpImage(QImage originalImage) {

    QImage scaledUpImage;

    scaledUpImage = originalImage.scaledToHeight(( editorImageHeight * 40 ), Qt::FastTransformation);
    QPainter p(&amp;scaledUpImage);
    p.drawImage(QPoint(0, 0), scaledUpImage);

    return scaledUpImage;
}

void assetEditorImageChange::undo()
{
    /* Clear the editor foreground */
    foregroundImage-&gt;fill(qRgba(0, 0, 0, 0));

    /* Scale up the image to restore */
    QImage scaledUp = scaleUpImage(oldImage);

    /* Restore the image */
    QPainter painter(foregroundImage);
    painter.drawImage(QPoint(0, 0), scaledUp);

    /* Revert the editor config back */
    memcpy((void*)editorConfig, (void*)&amp;oldConfig, sizeof(assetEditor::editorState));

    /* Update the editor */
    qDebug() &lt;&lt; "Call update here";
}

void assetEditorImageChange::redo()
{
    /* Clear the editor foreground */
    foregroundImage-&gt;fill(qRgba(0, 0, 0, 0));

    /* Scale up the image to restore */
    QImage scaledUp = scaleUpImage(newImage);

    /* Restore the image */
    QPainter painter(foregroundImage);
    painter.drawImage(QPoint(0, 0), scaledUp);

    /* Revert the editor config back */
    memcpy((void*)editorConfig, (void*)&amp;newConfig, sizeof(assetEditor::editorState));

    /* Update the editor */
    qDebug() &lt;&lt; "Call update here";
}
</code></pre>
<p dir="auto">This all works fine if I create an undo action in mainWindow.cpp and call the undo function and the update function:</p>
<pre><code>void MainWindow::on_actionUndo_triggered()
{
    /* Perform the undo commands */
    undoStack-&gt;undo();

    /* Update the UI */
    ui-&gt;imageEditor-&gt;update();
}
</code></pre>
<p dir="auto">But the undo stack holds lots of commands that aren't related to the image editor, so it doesn't need to be updated for every undo/redo action.</p>
<p dir="auto">What's the correct way to update the UI once an undo/redo command is called?</p>
]]></description><link>https://forum.qt.io/topic/142764/qundocommand-update-ui</link><generator>RSS for Node</generator><lastBuildDate>Wed, 24 Jun 2026 20:26:40 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/142764.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 07 Feb 2023 21:48:38 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to QUndoCommand Update UI on Wed, 08 Feb 2023 20:41:00 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jonb">@<bdi>JonB</bdi></a></p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jonb">@<bdi>JonB</bdi></a> said in <a href="/post/746776">QUndoCommand Update UI</a>:</p>
<blockquote>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/gsephelec">@<bdi>gsephelec</bdi></a><br />
Then I can only guess you are asking to not always do <code>ui-&gt;imageEditor-&gt;update();</code> after <code>undoStack-&gt;undo();</code>, is that the question?</p>
</blockquote>
<p dir="auto">Yes exactly :)</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jonb">@<bdi>JonB</bdi></a> said in <a href="/post/746776">QUndoCommand Update UI</a>:</p>
<blockquote>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/gsephelec">@<bdi>gsephelec</bdi></a><br />
So, for example, make your <code>undo()</code> look at what it is undoing and return a result to the caller indicating whether the image editor still needs updating? Or, maybe, have the undo command which affects the image editor emit a signal/set a flag when it does so, so you will know the image needs updating?</p>
</blockquote>
<p dir="auto">Yes to both, which is the better practice and what would be the best way to implement it?</p>
<p dir="auto">I did also look at passing an "update ui" function from within the <code>assetEditor</code> class to the QUndoCommand, but I couldn't get this to work properly and I wasn't sure if that was a messy way to get round my issue?</p>
]]></description><link>https://forum.qt.io/post/746794</link><guid isPermaLink="true">https://forum.qt.io/post/746794</guid><dc:creator><![CDATA[gsephelec]]></dc:creator><pubDate>Wed, 08 Feb 2023 20:41:00 GMT</pubDate></item><item><title><![CDATA[Reply to QUndoCommand Update UI on Wed, 08 Feb 2023 18:11:02 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/gsephelec">@<bdi>gsephelec</bdi></a><br />
Then I can only guess you are asking to not always do <code>ui-&gt;imageEditor-&gt;update();</code> after <code>undoStack-&gt;undo();</code>, is that the question?  So, for example, make your <code>undo()</code> look at what it is undoing and return a result to the caller indicating whether the image editor still needs updating?  Or, maybe, have the undo command which affects the image editor emit a signal/set a flag when it does so, so you will know the image needs updating?</p>
]]></description><link>https://forum.qt.io/post/746776</link><guid isPermaLink="true">https://forum.qt.io/post/746776</guid><dc:creator><![CDATA[JonB]]></dc:creator><pubDate>Wed, 08 Feb 2023 18:11:02 GMT</pubDate></item><item><title><![CDATA[Reply to QUndoCommand Update UI on Wed, 08 Feb 2023 16:02:45 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jonb">@<bdi>JonB</bdi></a><br />
The <code>assetEditorImageChange</code> command is only for changes to the image in the image editor, like drawing/erasing pixels. I have other QUndoCommands for different things as well, but the <code>QUndoStack</code> takes commands from the entire application, not just the image editor, so when you click the undo/redo button, you might be performing commands on the image editor, or somewhere else in the main window, in which case the image editor doesn't need to be updated - especially since in some situations, the image editor may not be shown, in which case it can't be updated.</p>
]]></description><link>https://forum.qt.io/post/746765</link><guid isPermaLink="true">https://forum.qt.io/post/746765</guid><dc:creator><![CDATA[gsephelec]]></dc:creator><pubDate>Wed, 08 Feb 2023 16:02:45 GMT</pubDate></item><item><title><![CDATA[Reply to QUndoCommand Update UI on Wed, 08 Feb 2023 09:22:10 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/gsephelec">@<bdi>gsephelec</bdi></a><br />
If I understand you right: you have a custom <code>QUndoCommand</code>.  That has members for a number of things you might need to save for undo/redo, including a "large" image.  But not every undoable action needs to restore the image, and you would like to "save space" by not storing it when it won't be needed?  (Really <code>QImage</code>s are shared so space may not be as bad as you fear, but that's a different matter.)</p>
<p dir="auto">So your <code>QUndoCommand</code> should only need to store those items it really needs to for its undo action.  For example, you might store the <code>QImage</code> as a <em>pointer</em> to a <code>new</code>ed object.  Pass in <code>nullptr</code> where the image is not going to be needed.  Test for whether the <code>QUndoCommand</code>s <code>QImage</code> is <code>nullptr</code> before you attempt to restore it.</p>
<p dir="auto">Another possibility is to <em>subclass</em> your <code>assetEditorImageChange</code> so that that it has derived classes to handle, say, image changes separately from config changes.  Only the "image change" subclass holds a <code>QImage</code>.  Push to the undo stack only whichever subclass is appropriate to the action in question.  Now your stack holds subclassed objects which contain only whatever data they specifically need.</p>
]]></description><link>https://forum.qt.io/post/746633</link><guid isPermaLink="true">https://forum.qt.io/post/746633</guid><dc:creator><![CDATA[JonB]]></dc:creator><pubDate>Wed, 08 Feb 2023 09:22:10 GMT</pubDate></item></channel></rss>