As a workaround, I found that using a single shot QTimer in between the
thread's signal handler and the display update method will resolve the
issue. The timer method can't accept any parameters, but that's can
usually be dealt with. For example
String mLastestData;
private void handleNewDataReadySignalFromThread(String newData)
{
mLatestData = newData;
QTimer.singleShot(0, this, "displayResult()");
}
private void displayResult()
{
// clear existing data and display mLatestData
}
On Thu, May 24, 2012 at 1:13 PM, Josh Highley <[email protected]> wrote:
> 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