Seite 1 von 1

[gelöst] QClipboard funktioniert nicht in QThread?

Verfasst: 20. Mai 2009 14:55
von forgoden
also folgende Befehle stehen in thread run();

Code: Alles auswählen

	QClipboard *clipboard = QApplication::clipboard();
	clipboard->setText("test");
Wenn ich diesen thread starte, stürzt das Programm mit der Fehlermeldung ab:
Module: 4.5.1
File: global\qglobal.cpp
Line: 2005

ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel\qwidget.cpp, line 1062
lasse ich diesen Befehl raus clipboard->setText("test");
passiert erst mal nix. Dennoch stürzt das Programm erst beim beenden (nicht beim Beenden des threads!) ab mit der folgenden Fehlermeldung:
Module: 4.5.1
File: global\qglobal.cpp
Line: 2005

ASSERT failure in QCoreApplication::sentEvent: "Cannot send events to objects owned by a different thread. Current thread 3b6628. Receiver "(of type 'QClipboard') was created in thread b9a8f0", file kernel\qcoreapplication.cpp, line 305
Die Aussage mag offensichtlich sein, aber wo in Doku musst ich darauf achten, dass es so ist?

In QClipboard steht nix von threads und in QThread nix von clipboard. Und wie gehe ich damit am besten um? Über signal und slot kann ich keine strings kopieren. Also ein Zeiger, der auf diesen QString in thread zeigt?

Verfasst: 20. Mai 2009 15:24
von AuE
Die Fehlermeldungen sind korrekt ;-) Wo genau es in der Doku steht kann ich dir nicht sagen aber mit sicherheit wer anders ;-)

Zu deinem eig. Problem: SIGNAL/SLOT gehen wunderbar mit Threads ;-)

Verfasst: 20. Mai 2009 15:36
von franzf
QClipboard scheint nur im Gui-Thread richtig zu funktionieren.
Leider ist "Clipboard::setText()" kein Slot, sonst könnte man es direkt per QMetaObject::invokeMethod() machen.
Ansonsten schreib dir eine Wrapper-Klasse.
Folgendes geht hier ohne Abstürze und Fehlermeldungen:

Code: Alles auswählen

#include <QObject>
#include <QThread>
#include <QApplication>
#include <QClipboard>
#include <QDateTime>
#include <QMetaObject>

// ClipboardWrapper
class CLW : public QObject
{
    Q_OBJECT
    public:
        CLW()
        {
            moveToThread( qApp->thread() );
        }
    public slots:
        void setText( const QString& text )
        {
            QApplication::clipboard()->setText(text);
        }
};

class Thread : public QThread
{
    Q_OBJECT
    public:
        Thread(QObject *parent=0)
         : QThread(parent)
        {}
    protected:
        void run()
        {
            CLW *c = new CLW;
            QString s = "Hello from another Thread" + QDateTime::currentDateTime().toString();
            QMetaObject::invokeMethod(c, "setText", Qt::QueuedConnection,
                                       Q_ARG(QString,s) );
            c->deleteLater();
        }
};
main.cpp

Code: Alles auswählen

#include <QtGui>
#include "objects.h"

int main( int argc, char **argv )
{
    QApplication app( argc, argv );
    Thread t;
    t.start();
    QLabel l("A small Gui Element...");
    l.show();
    return app.exec();
}
Grüße
Franz

Verfasst: 20. Mai 2009 17:12
von forgoden
danke für den ganzen code, das funktioniert wirklich!

Einige Befehle wären neu für mich und ich wär wahrscheinlich nie auf diese Idee gekommen. Ich werd nachlesen soviel es mit der Anstrengung geht.
SIGNAL/SLOT gehen wunderbar mit Threads
Mit Strings? Zumindest nicht wenn zur Laufzeit jedes mal ein anderer String ist?