Seite 1 von 2
Kann man in einem Thread auf ein Edit-Feld zugreifen?
Verfasst: 30. November 2009 23:51
von Frezee
Hi,
das hier ist mein erster Beitrag in eurem Forum; ich hoffe ich poste in der richtigen Section.
Mein Problem ist fogendes: ich möchte in einer Qt4 Application einen Thread erstellen und mit diesem auf ein EditFeld in meinem Fenster zugreifen.
mainwindow.h
Code: Alles auswählen
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
#include <QThread>
class MyThread : public QThread {
Q_OBJECT
public:
virtual void run();
class MainWindow;
};
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void button1clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
Code: Alles auswählen
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qthread.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MyThread::run()
{
QTime timeNow = QTime::currentTime();
ui->timeEdit->setTime(timeNow);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::button1clicked()
{
MyThread a;
a.start();
a.wait();
}
Ich erhalte als Error:
`ui' was not declared in this scope
In einem anderen Thread habe ich folgenen Satz gelesen:
Christian81 hat geschrieben:Vom Thread auf die GUI zugreifen geht nicht.
Stimmt das überhaupt? Und gibt es dann auf mein Problem gar keine Lösung?
Ich hoffe ihr könnt mir weiterhelfen.
mfg Frezee
Re: Kann man in einem Thread auf ein Edit-Feld zugreifen?
Verfasst: 1. Dezember 2009 08:10
von franzf
Frezee hat geschrieben:Ich erhalte als Error:
`ui' was not declared in this scope
In einem anderen Thread habe ich folgenen Satz gelesen:
Christian81 hat geschrieben:Vom Thread auf die GUI zugreifen geht nicht.
Stimmt das überhaupt? Und gibt es dann auf mein Problem gar keine Lösung?
Also, wenn der Christian81 sowas sagt, kannst du davon ausgehen, dass es auch stimmt...
Dein Problem ist ein anderes. Wenn man versucht, von einem Thread auf den GUI-Thread zuzugreifen, kompiliert das Programm. Es verhält sich nur zur Laufzeit anders als erwartet und spuckt Fehlermeldungen auf der Konsole aus.
Du versuchst auf ein privates Element "ui" aus der MainWindow-Klasse einfach so von deiner Thread-Klasse aus zuzugreifen, als wäre das ne globale Variable.
Sowas funktioniert prinzipiell und auch ohne Verwendung verschiedener Threads oder Qt oder GUI nicht...
Um dein Problem zu lösen, müssten wir erst wissen was du vor hast.
Verfasst: 1. Dezember 2009 08:28
von AuE
Ein gängiger Ratschlag ist immer: Schick aus deinen Thread heraus Signale die in dem GUI Thread in den Slots landen!
Verfasst: 1. Dezember 2009 09:45
von nando
Moin...
Aus der Qt Doku:
Note that QCoreApplication::exec() must always be called from the main thread (the thread that executes main()), not from a QThread. In GUI applications, the main thread is also called the GUI thread because it's the only thread that is allowed to perform GUI-related operations.
Gruss,
Nando
Verfasst: 1. Dezember 2009 12:00
von RHBaum
ich möchte in einer Qt4 Application einen Thread erstellen und mit diesem auf ein EditFeld in meinem Fenster zugreifen.
Warum willst du denn den eigenen Thread ?
Normal lagert man zeugs aus (in andere Threads, prozesse), was rechenintensiv ist, oder lange laeuft ohne unterbrechen zu koennen, um die Anwendung ned zu blockieren.
Eine ausgabe in ein editfeld iss weder rechenintesiv, noch dauert es lange genug als das sich nen thread lohnen wird.
In der Anwendungsentwicklung, also so zeugs was sich mit Steuerelementen / eingabemasken usw beschaeftigt, kommt man zu 99.999999999999999999999999999999999999 % mit einem qui thread aus + kein bis mehere workerthreads aus. Von daher iss die Limitation der qt ok.
2d kann man so fix malen, das kaum verzoegerungen fuer den user entstehen.
Trotzdem, wenn du multithreaded arbeiten willst, und sich fenster unabhaengig zeichnen sollen, ohne sich zu beeinflussen ... dann wirst wohl direkt auf die winapi / alternativ X runter.
Das einzigste wo das malen wirklich ein erheblicher Anteil der prozessorlast ausmacht, iss 3D und da macht multithreading auch mehr sin ... da malst aber eher aufn 3D context und da gelten anderere regeln.
Ciao ...
Verfasst: 1. Dezember 2009 19:28
von Frezee
Danke erstmal für eure Antworten.
RHBaum hat geschrieben:
Warum willst du denn den eigenen Thread ?
Normal lagert man zeugs aus (in andere Threads, prozesse), was rechenintensiv ist, oder lange laeuft ohne unterbrechen zu koennen, um die Anwendung ned zu blockieren.
Ich habe auch vor in den Thread noch andere Dinge hineinzupacken.
Ich habe halt im Sticky gelesen, dass ein guter Beitrag nur den nötigsten Quellcode enthalten sollte und ich dachte für mein Problem brauch ich nicht so viel Quellcode.
AuE hat geschrieben:Ein gängiger Ratschlag ist immer: Schick aus deinen Thread heraus Signale die in dem GUI Thread in den Slots landen!
Ich glaube ich werde es mal damit versuchen, falls jemand andere Vorschläge hat kann er die ja posten.
Wenn ich eine Lösung gefunden habe poste ich sie auf jeden Fall hier.
lg
Verfasst: 2. Dezember 2009 07:16
von AuE
Andere (wie ich finde) geile Möglichkeit: Lass deine GUI Klasse von QRunnable erben, schreib in der Klasse die run Funktion...
Das empfiehlt sich wenns zB was immerwiederkehrendes ist was du in nen Thread auslagern möchtest.
Aber auch hier wieder: Signals und Slots!
Denn sowohl in Thread also auch in ner Runnable ist die Thread != GUI Thread. Und somit kannst du keine Objekte verändern ( evtl ginge es mit moveToThread() was aber totaler bullshit ist da du die Objekte danach wieder in den GUI Thread moven müsstest)
Verfasst: 2. Dezember 2009 10:54
von RHBaum
Ich habe halt im Sticky gelesen, dass ein guter Beitrag nur den nötigsten Quellcode enthalten sollte und ich dachte für mein Problem brauch ich nicht so viel Quellcode
Neee um quellcode ging es auch ned ...
Du hasst dich nur etwas unpräzise ausgedrueckt.
DU hasst geschrieben, das du das Befuellen eines GUI elements in nen Thread auslagern willst ! das macht IMHO keinen Sinn.
Richtiger waere: Du willst irgendwas in einen thread auslagern, und dieses irgendwas soll staendig / oder am ende, ein GUI element updaten.
Das macht Sinn und fast jeder hier kann dir bei der Lösung helfen. -> Threadwechsel ( Signale / Slots , Events .... )
Ciao ...
Verfasst: 3. Dezember 2009 16:49
von Frezee
RHBaum hat geschrieben:Ich habe halt im Sticky gelesen, dass ein guter Beitrag nur den nötigsten Quellcode enthalten sollte und ich dachte für mein Problem brauch ich nicht so viel Quellcode
Neee um quellcode ging es auch ned ...
Du hasst dich nur etwas unpräzise ausgedrueckt.
DU hasst geschrieben, das du das Befuellen eines GUI elements in nen Thread auslagern willst ! das macht IMHO keinen Sinn.
Richtiger waere: Du willst irgendwas in einen thread auslagern, und dieses irgendwas soll staendig / oder am ende, ein GUI element updaten.
Das macht Sinn und fast jeder hier kann dir bei der Lösung helfen. -> Threadwechsel ( Signale / Slots , Events .... )
Ciao ...
Ok, ich werd es mir merken. (:
btw. kann vielleicht mal jemand ein Beispiel geben, oder eine kleine Hilfe für die Signals/Slots? Ich habe jetzt schon auf einigen Internetseiten vorbeigeschaut (unter anderem z.B. hier:
http://doc.trolltech.com/4.5/signalsandslots.html), aber irgendwie weiß ich nicht wie ich das in meinen Thread einbauen kann.
Vielleicht weiß von euch ja jemand weiter.

Verfasst: 3. Dezember 2009 16:54
von RHBaum
Iss dein Thread ein QThread ... oder hasst den selbst erzeugt ?
Ciao ...
Verfasst: 3. Dezember 2009 17:04
von Frezee
RHBaum hat geschrieben:Iss dein Thread ein QThread ... oder hasst den selbst erzeugt ?
Ciao ...
ein QThread:
Code: Alles auswählen
class MyThread : public QThread {
Q_OBJECT
public:
virtual void run();
};
Wenn es damit aber nicht funktioniert, geht auch ein selbst erzeugter. Ist mir eientlich egal.

Verfasst: 3. Dezember 2009 17:30
von RHBaum
Es geht immer mit allen, iss nur ne Frage des Aufwandes.
was hindert dich an:
Code: Alles auswählen
class MyThread : public QThread {
Q_OBJECT
public:
virtual void run();
signals:
void fillEditField(QString strNewText);
};
und in deiner runMethode dann da wo Das Edit feld befuellst,
einach ein emit fillEditField(Irgendeinstring);
ausfuehren.
Dann kannst aber das Signal vom thread (fillEditField) leider nicht gleich mit dem EditFeld Slot Settext verbinden QString und const QString & sind nun mal unterschiedliche parameter, sondern du muestest es in nem eigenen slot, mit QString als param, auffangen und einfach editfeld->setText(StringParam) aufrufen.
Das einzig "knifflige" is wirklich das QString als parameter nimmst. Weil das ding ja kopiert werden muss wegen der queued connection, da muss es ein impliziet kopierbarer datentyp sein (das QMETACLASS gerödel).
Aber ehrlich das sind echt QT grundlagen.
Falls mit der Onlinehilfe von qt ned zurande kommst, bzw englisch ned so magst, empfiehlt sich echt Literatur die einen an das Thema heranfuehrt.
Also ned nur Buecher die die qt Klassen, funktionen und methoden listen (nachschlagewerk) weil da ist die onlinehilfe eh unangefochten spitze.
Qt4 Einführung in die Applicationsentwicklung / Daniel Molkentin z.b. würd ich empfehlen .
Ciao ...
Verfasst: 12. Dezember 2009 00:33
von Frezee
Sry für Doppelpost..

Kann den Post nicht mehr löschen.
Verfasst: 12. Dezember 2009 00:37
von Frezee
RHBaum hat geschrieben:Es geht immer mit allen, iss nur ne Frage des Aufwandes.
was hindert dich an:
Code: Alles auswählen
class MyThread : public QThread {
Q_OBJECT
public:
virtual void run();
signals:
void fillEditField(QString strNewText);
};
und in deiner runMethode dann da wo Das Edit feld befuellst,
einach ein emit fillEditField(Irgendeinstring);
ausfuehren.
Dann kannst aber das Signal vom thread (fillEditField) leider nicht gleich mit dem EditFeld Slot Settext verbinden QString und const QString & sind nun mal unterschiedliche parameter, sondern du muestest es in nem eigenen slot, mit QString als param, auffangen und einfach editfeld->setText(StringParam) aufrufen.
Das einzig "knifflige" is wirklich das QString als parameter nimmst. Weil das ding ja kopiert werden muss wegen der queued connection, da muss es ein impliziet kopierbarer datentyp sein (das QMETACLASS gerödel).
Aber ehrlich das sind echt QT grundlagen.
Falls mit der Onlinehilfe von qt ned zurande kommst, bzw englisch ned so magst, empfiehlt sich echt Literatur die einen an das Thema heranfuehrt.
Also ned nur Buecher die die qt Klassen, funktionen und methoden listen (nachschlagewerk) weil da ist die onlinehilfe eh unangefochten spitze.
Qt4 Einführung in die Applicationsentwicklung / Daniel Molkentin z.b. würd ich empfehlen .
Ciao ...
Danke erstmal für deine Hilfe..
Seit meinem letzten Post ist jetzt schon ne Woche vergangen, aber ich hab mein Problem immer noch nicht gelöst. :/ Hört sich jetzt vielleicht blöd an, aber ich krieg das einfach ned hin.. Ich will mir auch ned zu etwas ein Buch kaufen, wenn ich nicht mal weiß ob ich mit diesem Programm länger arbeiten werde.

Vielleicht sollte ich euch mein Problem etwas genauer beschreiben. Ich habe vor, eine Benutzeroberfläche zu erstellen, die etwa so aussieht:
->> Bild <<-
Man gibt erst eine Zeit an und drückt dann auf Start. Dann aktiviert sich ein Countdown und die Zeit zählt im Sekundentakt herunter. Beim Klick auf Stopp wird der Countdown angehalten.
Ich habe mir das dann folgendermaßen vorgestellt:
- beim Klick auf Start wird ein Thread erstellt, der den Countdown macht
- beim Klick auf Stopp wird der Thread wieder beendet
Bei MFC ging das ganz einfach mit CreateThread() und TerminateThread().. In Qt muss das doch auch irgendwie gehen, dass ich von meinem Thread aus auf das GUI zugreifen kann, oder?

Naja, vielleicht hat ja jemand von euch eine Idee, wie ich meine Idee umsetzen kann.
mfg Frezee

Verfasst: 12. Dezember 2009 07:43
von franzf
*** HUST HUST ***
Da ist ein neuer Thread ja so was von Overkill...
Ein normaler QTimer reicht. Du kannst dir auch das timerEvent() mal anschauen...