[gelöst] QClipboard funktioniert nicht in QThread?

Alles rund um die Programmierung mit Qt
Antworten
forgoden
Beiträge: 120
Registriert: 10. Februar 2008 17:52

[gelöst] QClipboard funktioniert nicht in QThread?

Beitrag 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?
Zuletzt geändert von forgoden am 21. Mai 2009 19:56, insgesamt 1-mal geändert.
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag 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 ;-)
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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
forgoden
Beiträge: 120
Registriert: 10. Februar 2008 17:52

Beitrag 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?
Antworten