diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 3b63028a2e4bc0ce930eb0a0cd9457ec57c2ec14..62ed5e0c859bc794900cd1e38a5ee60a9494289e 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -3857,7 +3857,7 @@ void QQuickItem::polish()
     Q_D(QQuickItem);
     if (!d->polishScheduled) {
         d->polishScheduled = true;
-        if (d->window) {
+        if (d->window && (isVisible() || (d->extra.isAllocated() && d->extra->effectRefCount>0))) {
             QQuickWindowPrivate *p = QQuickWindowPrivate::get(d->window);
             bool maybeupdate = p->itemsToPolish.isEmpty();
             p->itemsToPolish.insert(this);
@@ -5241,6 +5241,8 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
         QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
         if (windowPriv->mouseGrabberItem == q)
             q->ungrabMouse();
+        if (polishScheduled)
+            windowPriv->itemsToPolish.insert(q);
     }
 
     bool childVisibilityChanged = false;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index bc8558e1d8580048bc7b221f28dbae02dd991128..7f62267859d90e28b9f898a7c1621d1824c97489 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -258,23 +258,16 @@ void QQuickWindowPrivate::polishItems()
 {
     int maxPolishCycles = 100000;
 
-    int removedItems;
-    do {
-        removedItems = 0;
+    while (!itemsToPolish.isEmpty() && --maxPolishCycles > 0) {
         QSet<QQuickItem *> itms = itemsToPolish;
+        itemsToPolish.clear();
 
         for (QSet<QQuickItem *>::iterator it = itms.begin(); it != itms.end(); ++it) {
             QQuickItem *item = *it;
-            QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
-            if (item->isVisible() || (itemPrivate->extra.isAllocated() && itemPrivate->extra->effectRefCount>0)) {
-                itemPrivate->polishScheduled = false;
-                itemsToPolish.remove(item);
-                item->updatePolish();
-                ++removedItems;
-            }
+            QQuickItemPrivate::get(item)->polishScheduled = false;
+            item->updatePolish();
         }
-    } while (removedItems > 0 && --maxPolishCycles > 0);
+    }
 
     if (maxPolishCycles == 0)
         qWarning("QQuickWindow: possible QQuickItem::polish() loop");
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index f4f237418353caa84e9f98bdd069285a9164de64..efe9266d0a53d50672b22e380fbd2b9a27dfd612 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -40,11 +40,13 @@
 ****************************************************************************/
 
 #include <qtest.h>
+#include <qsignalspy.h>
 
 #include <QtQuick/qquickitem.h>
 #include <QtQuick/qquickwindow.h>
 #include <QtQuick/qquickview.h>
 #include "private/qquickfocusscope_p.h"
+#include "private/qquickwindow_p.h"
 #include "private/qquickitem_p.h"
 #include <qpa/qwindowsysteminterface.h>
 #include <QDebug>
@@ -156,6 +158,8 @@ private slots:
     void touchEventAcceptIgnore();
     void polishOutsideAnimation();
     void polishOnCompleted();
+    void polishLaterWhenVisible();
+    void polishWhenOtherHidden();
 
     void wheelEvent_data();
     void wheelEvent();
@@ -1396,6 +1400,63 @@ void tst_qquickitem::polishOnCompleted()
     QTRY_VERIFY(item->wasPolished);
 }
 
+void tst_qquickitem::polishLaterWhenVisible()
+{
+    QQuickWindow window;
+    QQuickWindowPrivate *wp = QQuickWindowPrivate::get(&window);
+    window.resize(200, 200);
+    window.show();
+    QTest::qWaitForWindowExposed(&window);
+
+    TestPolishItem *item = new TestPolishItem(window.contentItem());
+    item->setSize(QSizeF(200, 100));
+    item->setVisible(false);
+    item->polish();
+
+    QVERIFY(!wp->itemsToPolish.contains(item));
+    window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+    QVERIFY(!item->wasPolished);
+
+    item->setVisible(true);
+    QVERIFY(wp->itemsToPolish.contains(item));
+    window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+    QVERIFY(item->wasPolished);
+    QVERIFY(!wp->itemsToPolish.contains(item));
+}
+
+void tst_qquickitem::polishWhenOtherHidden()
+{
+    QQuickWindow window;
+    QQuickWindowPrivate *wp = QQuickWindowPrivate::get(&window);
+    window.resize(200, 200);
+    window.show();
+    QTest::qWaitForWindowExposed(&window);
+
+    // a hidden item pending for polish...
+    TestPolishItem *hiddenItem = new TestPolishItem(window.contentItem());
+    hiddenItem->setSize(QSizeF(200, 100));
+    hiddenItem->setVisible(false);
+    hiddenItem->polish();
+
+    QVERIFY(!wp->itemsToPolish.contains(hiddenItem));
+    window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+    QVERIFY(!hiddenItem->wasPolished);
+
+    // ...should not block a visible item from being polished
+    TestPolishItem *visibleItem = new TestPolishItem(window.contentItem());
+    visibleItem->setSize(QSizeF(200, 100));
+    visibleItem->setVisible(true);
+    visibleItem->polish();
+
+    QVERIFY(wp->itemsToPolish.contains(visibleItem));
+    QVERIFY(!wp->itemsToPolish.contains(hiddenItem));
+    window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+    QVERIFY(visibleItem->wasPolished);
+    QVERIFY(!hiddenItem->wasPolished);
+    QVERIFY(!wp->itemsToPolish.contains(visibleItem));
+    QVERIFY(!wp->itemsToPolish.contains(hiddenItem));
+}
+
 void tst_qquickitem::wheelEvent_data()
 {
     QTest::addColumn<bool>("visible");