Kann man in einem Thread auf ein Edit-Feld zugreifen?

Alles rund um die Programmierung mit Qt
Frezee
Beiträge: 8
Registriert: 30. November 2009 18:31

Kann man in einem Thread auf ein Edit-Feld zugreifen?

Beitrag von Frezee »

Hi,

das hier ist mein erster Beitrag in eurem Forum; ich hoffe ich poste in der richtigen Section. :D

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

Re: Kann man in einem Thread auf ein Edit-Feld zugreifen?

Beitrag 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.
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Ein gängiger Ratschlag ist immer: Schick aus deinen Thread heraus Signale die in dem GUI Thread in den Slots landen!
nando
Beiträge: 321
Registriert: 28. Oktober 2004 13:16

Beitrag 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
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag 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 ...
Frezee
Beiträge: 8
Registriert: 30. November 2009 18:31

Beitrag 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. :D

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. :wink:

lg
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag 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)
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag 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 ...
Frezee
Beiträge: 8
Registriert: 30. November 2009 18:31

Beitrag 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. :D
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Iss dein Thread ein QThread ... oder hasst den selbst erzeugt ?

Ciao ...
Frezee
Beiträge: 8
Registriert: 30. November 2009 18:31

Beitrag 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. :wink:
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag 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 ...
Frezee
Beiträge: 8
Registriert: 30. November 2009 18:31

Beitrag von Frezee »

Sry für Doppelpost.. :(
Kann den Post nicht mehr löschen.
Zuletzt geändert von Frezee am 12. Dezember 2009 00:38, insgesamt 2-mal geändert.
Frezee
Beiträge: 8
Registriert: 30. November 2009 18:31

Beitrag 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.. :D

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

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