My program has a long running thread that when finished, emits a signal
with the resulting data.  The signal handler method in the main app should
then clear the GUI's result display area of any existing data and display
the new result data.

However, I've encountered the issue where the existing data is not cleared
and the new data is overlaid on top of it.  I've managed to reproduce the
issue with a simple test program.  I found that if the 'new data' handler
is triggered by a button click signal, then the existing data is cleared
correctly as intended.  But, if the 'new data' handler is triggered by a
signal from a QThread, then the data is not cleared.  In addition, if the
QThread emits its signal first, clicking the button later will not clear
the data but if the button is clicked first, then subsequent clicks will
fix 'messy' paints by the QThread signal (sorry, that's confusing)

I've reproduced the issue on multiple environments:
   Win64 + Qt Jambi 4.5.2
   Linux x64 + Qt Jambi 4.5.2
   Linux x64 + Qt Jambi 4.6.3
   Linux x64 + Qt Jambi 4.7.0


Here's my test program with the 2 test scenarios and results documented at
the top:

import com.trolltech.qt.QSignalEmitter;
import com.trolltech.qt.QThread;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QFormLayout;
import com.trolltech.qt.gui.QGroupBox;
import com.trolltech.qt.gui.QLabel;
import com.trolltech.qt.gui.QLayout;
import com.trolltech.qt.gui.QLayoutItemInterface;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QPushButton;
import com.trolltech.qt.gui.QVBoxLayout;
import com.trolltech.qt.gui.QWidget;

/*
 * Test that shows how a signal handler triggered from a QThread cannot
remove widgets.
 *
 *  2 Test Scenarios:
 *    1) Replace using signal from button first:
 *       a) Click button "Replace Data By Button Signal". Result: 'init' is
replaced by 'button'
 *       b) Click button "Replace Data By Thread Signal". Result: 'button'
is not replaced, but overlaid with 'thread'
 *       c) Click button "Replace Data By Button Signal" again. Result:
'button'+'thread' is replaced by just 'button'
 *
 *     Conclusion: if the initial value is first replaced from the button
signal, then the signal from button can 'fix' the
 *       messy paint by the signal from thread.
 *
 *    2) Replace using signal from thread first:
 *       a) Click button "Replace Data By Thread Signal". Result: 'init' is
not replaced, but overlaid with 'thread' (similar to (1b) above)
 *       b) Click button "Replace Data By Button Signal". Result:
'init'+'thread' is not replaced but overlaid again with 'button'
 *
 *     Conclusion: if the initial value is first replaced from the thread
signal, then the
 *       signal from the button cannot fix the messy paint by the thread
like it does on path 1 above.
 */

public class ClearAreaTest extends QMainWindow
{
    private static ClearAreaTest app;
    private QGroupBox groupBox;

    public static void main(String[] args)
    {
        QApplication.initialize(args);
        app = new ClearAreaTest();
        app.show();
        QApplication.exec();
    }

    public ClearAreaTest()
    {
        super();
        setObjectName(this.getClass().getSimpleName());
        setWindowTitle(this.getClass().getSimpleName());

        QWidget mainWidget = new QWidget();
        QVBoxLayout vLayout = new QVBoxLayout();

        QFormLayout fLayout = new QFormLayout();
        fLayout.addRow("Field A", new QLabel("init"));

        groupBox = new QGroupBox("Data");
        groupBox.setLayout(fLayout);

        vLayout.addWidget(groupBox);

        QPushButton btn = new QPushButton("Replace Data By Thread Signal");
        btn.clicked.connect(this, "runThread()");
        vLayout.addWidget(btn);

        btn = new QPushButton("Replace Data By Button Signal");
        btn.clicked.connect(this, "replaceDataButton()");
        vLayout.addWidget(btn);

        mainWidget.setLayout(vLayout);
        setCentralWidget(mainWidget);
    }

    private void runThread()
    {
        LongRunningThread lrThread = new LongRunningThread();
        lrThread.newDataReady.connect(this, "replaceData(String)");

        QThread qThread = new QThread(lrThread);
        qThread.start();
    }

    private void replaceDataButton()
    {
        replaceData("button");
    }

    private void replaceData(String newData)
    {
        System.out.println("replaceData(): "+newData);

        clearArea(groupBox.layout());

        QFormLayout fLayout = new QFormLayout();
        fLayout.addRow("Field A", new QLabel(newData));
        groupBox.setLayout(fLayout);
    }

    public static void clearArea(QLayout layout)
    {
        if (layout == null) { return; }

        QLayoutItemInterface item;
        QLayout tmpL;
        QWidget tmpW;

        System.out.println("clearArea() layout.count(): "+layout.count());

        while (layout.count() > 0)
        {
            System.out.print("disposing item "+(layout.count()-1)+": ");
            item = layout.takeAt(layout.count()-1);

            if (item.widget() != null)
            {
                System.out.println("widget");
                tmpW = item.widget();

                if (tmpW.layout() != null)
                {
                    clearArea(tmpW.layout());
                }

                layout.removeWidget(tmpW);
                tmpW.disposeLater();
            }
            else if (item.layout() != null)
            {
                System.out.println("layout");
                tmpL = item.layout();
                clearArea(tmpL);
            }
            else if (item.spacerItem() != null)
            {
                System.out.println("spacerItem");
                item.spacerItem().dispose();
            }
            else { System.out.println("unknown layout item"); }
        }

        layout.dispose();
    }

    public class LongRunningThread extends QSignalEmitter implements
Runnable
    {
        public Signal1<String> newDataReady = new Signal1<String>();

        public void run()
        {
            try
            {
                Thread.sleep(100);
                newDataReady.emit("thread");
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}
_______________________________________________
Qt-jambi-interest mailing list
[email protected]
http://lists.qt.nokia.com/mailman/listinfo/qt-jambi-interest

Reply via email to