[gelöst] Verständnisproblem QCustomEvent

Alles rund um die Programmierung mit Qt
Antworten
heikob
Beiträge: 81
Registriert: 23. März 2005 23:20

[gelöst] Verständnisproblem QCustomEvent

Beitrag von heikob »

Hallo,

irgendwie habe ich ein massives Verständnisproblem mit QCustomEvents und hoffe, dass ihr das Brett vor dem Kopf entfernen könnt. Ich habe die Threads hier in dem Forum gelesen, Bücher gewälzt, die Doku gelesen, aber ich kriege es irgendwie nicht hin.

Ich habe folgenden Sachverhalt:
Eine KLasse ist bei mir für die GUI zuständig. (MainWindow) Dazu gesellt sich eine weitere Klasse, die als QThread Werte von der seriellen Schnittstelle abfragt. Soweit funktioniert das alles ohne Probleme. Jetzt möchte ich die eingelesenen Werte dazu benutzen, den GUI-Thread zu verändern. Konkret möchte ich die entsprechenden Slider und LCDs verändern.

Dazu habe ich mir exemplarisch im MainWindow eine QCustomEvent Funktion erzeugt.

Code: Alles auswählen

void MainWindow::customEvent(QCustomEvent *ev)
{
	if(ev->type()==20000)
	{
		SliderProgramming[1]->setValue((int)ev->data());
	}
}
Also wenn das Event 20000 auftritt, soll er den Slider 1 auf den Wert aus data setzen. Das lässt sich auch anstandslos übersetzen.

Meine Probleme betreffen den Sender. Unter run() wollte ich den Sender folgendermaßen implementieren:

Code: Alles auswählen

QCustomEvent *event = new QCustomEvent(20000);
	//event->setData(255);
	//QApplication::postEvent(window,event);
Zum einen verstehe ich im Moment nicht, wie ich meinen int in das nötige void* kriege. Aber was ich noch viel unverständlicher finde, ist, wie ich aus der Thread-Klasse das QObject * window vom MainWindow erhalten soll.
Irgendwie stehe ich gerade voll im Wald und sehe die Lösung nicht, obwohl sie vermutlich trivial ist. Ich hoffe, hier kann mir jemand auf die Sprünge helfen.
Qoyanisque
Beiträge: 3
Registriert: 16. Mai 2005 20:46
Kontaktdaten:

Beitrag von Qoyanisque »

Hi,

so wie ich dein posting verstehe, handelt es sich um ein Producer-Consumer-Pattern.
Wie das mit Qt umgesetzt wird, zeigt das Beispiel $QTDIR/doc/examples/thread/prodcons/
Das Beispiel arbeitet uebrigens auch mit QCustomEvent Sub-Klassen, du soltest es also fast "kopieren" koennen.

hilft dir hoffentlich weiter,
qoyanisque
heikob
Beiträge: 81
Registriert: 23. März 2005 23:20

Beitrag von heikob »

Vielen Danke für die schnelle Antwort. Ich werde mir das mal in aller Ruhe zu gemüte führen.
heikob
Beiträge: 81
Registriert: 23. März 2005 23:20

Beitrag von heikob »

Nochmal vielen Dank. Jetzt habe ich es hinbekommen. Du hast mir wirklich den Abend gerettet :D

Aber nochmal eine kleine Frage die damit nicht wirklich was zu tun hat. Wenn ich bei einem Slider setValue ( int ) aufrufe, verändert er in der GUI nicht seine Stellung. Ist das normal? Müsste ich dafür noch etwas anderes aufrufen? Eventuell neu Zeichnen oder etwas in der Art?
FlorianBecker
Beiträge: 1213
Registriert: 2. Dezember 2004 10:54
Kontaktdaten:

Beitrag von FlorianBecker »

Also, wenn du setValue aufrufst sollte Qt das alles selbstständig machen und zumindest bei mir geht es.
Qoyanisque
Beiträge: 3
Registriert: 16. Mai 2005 20:46
Kontaktdaten:

Beitrag von Qoyanisque »

heikob hat geschrieben:Nochmal vielen Dank. Jetzt habe ich es hinbekommen. Du hast mir wirklich den Abend gerettet :D

Aber nochmal eine kleine Frage die damit nicht wirklich was zu tun hat. Wenn ich bei einem Slider setValue ( int ) aufrufe, verändert er in der GUI nicht seine Stellung. Ist das normal? Müsste ich dafür noch etwas anderes aufrufen? Eventuell neu Zeichnen oder etwas in der Art?
Du kannst mal folgendes Beispiel versuchen, welches bei mir (Qt 3.1.1) funktioniert. Sollte es damit gehen, muesste ich den Code sehen, um sagen zu koennen woran es evtl liegt.

Code: Alles auswählen

#include <qapplication.h>
#include <qslider.h>
#include <qhbox.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qvalidator.h>

class MyWidget: public QHBox {
  Q_OBJECT
private:
  QSlider     *slider;
  QPushButton *button;
  QLineEdit   *edit;
  
public:
  MyWidget (QWidget *parent, const char *name=(char*)0) : QHBox (parent, name) {
    QString s;
    slider = new QSlider (Qt::Horizontal, this);
    edit   = new QLineEdit (this);
    edit->setValidator (new QIntValidator (0, 100, this));
    edit->setText (s.setNum (0));
    button = new QPushButton (this);
    button->setText ("Set slider value");
    connect (button, SIGNAL (clicked()), this, SLOT (adjustSlider()));
  }

public slots:
  void adjustSlider() {
    QString s = edit->text();
    if ((s) && (!s.isNull())) {
      int val = s.toInt();
      slider->setValue (val);
    }
  }
};

#include "meta_slider.cpp"

/**
 * The obligate main
 */
int main (int argc, char *argv[]) {
  QApplication app (argc, argv);

  MyWidget *widget = new MyWidget ((QWidget*)0);
  widget->setCaption ("Qt Slider Sample");
  widget->show();
  app.connect (&app, SIGNAL (lastWindowClosed()), &app, SLOT (quit()));
  
  return app.exec();
}
hoffe, dass hilft dir weiter,
qoyanisque
heikob
Beiträge: 81
Registriert: 23. März 2005 23:20

Beitrag von heikob »

Hallo,

vielen Danke für das Beispiel. Leider ist die Situation bei mir etwas anders gelagert. Ich fange das Event aus meinem thread wie folgt ab:

Code: Alles auswählen

void MainWindow::customEvent(QCustomEvent *e)
{
	if(e->type()==QEvent::User+200)
	{
		ValueChangeEvent *ce = (ValueChangeEvent *) e;
		if(!ce->status())
		{
		SliderProgramming[ce->ID()]->setValue(ce->size());
	      std::cout<<SliderProgramming[ce->ID()]->value()<<std::endl;
		//LCDNumberProgramming[ce->ID()]->display(ce->size());
		//std::cout<<"Event empfangen"<<std::endl;
		}
		else
		{
		LCDNumberPlayingStageA[ce->ID()]->display(ce->size());
		//std::cout<<"Event empfangen Playing"<<std::endl;
		}
	}
}
Wie man sieht, habe ich versucht hieraus direkt den Wert der Slider zu verändern. Dies schlägt leider fehl. Die Events kommen korrekt an und ich kann auch die LCDs direkt hieraus aktualisieren. Nur bei den Sliders klappt das nicht, da die Werte nicht bei den Sliders ankommen. Die bleiben bei 0 stehen, gleich was aus dem Thread geschickt wird.

Dieses Verhalten wundert mich sehr, da ja display(int) genauso ein Slot ist wie auch setValue(int), dass das es einmal funktioniert und das andere Mal nicht. Mir würde als mögliche Lösung jetzt eigentlich nur noch einfallen, dass ich aus customEvent ein Signal an die Slider schicke um den Wert zu ändern anstatt es direkt zu tun. Allerdings sehe ich im Moment noch nicht, wie ich das bewerkstelligen könnte.

Vielleicht kann sich hier jemand dieses Verhalten erklären (Qt 3.3.4) und mir nochmal einen Tipp für die Lösung geben.

Vielen Dank
Heiko Berberich
Qoyanisque
Beiträge: 3
Registriert: 16. Mai 2005 20:46
Kontaktdaten:

Beitrag von Qoyanisque »

Hi,

Falls Du unter Unix arbeitest, hast Du mit -DQT_THREAD_SUPPORT uebersetzt?

Code: Alles auswählen

void MainWindow::customEvent(QCustomEvent *e) {...}
laeuft im main thread?

IMHO liegt es an der Methode ValueChangedEvent::size(), da QSlider::setValue(int) prinzipiell ja funktioniert und ich keinen Grund sehe warum das bei Dir nicht der Fall sein sollte. Wuerde ValueChangedEvent::ID() ungueltige Werte liefern, waere die Auswirkung wohl fataler oder es wuered sich zumindest immer derselbe Slider aendern.
Hast Du statt

Code: Alles auswählen

std::cout<<SliderProgramming[ce->ID()]->value()<<std::endl;
schonmal

Code: Alles auswählen

std::cout << ce->ID() << ", " << ce->size() << std::endl;
ausgegeben.
Falls ja, stimmen diese Werte?

Was passiert, wenn du QSlider::setValue(int) einfach mal mit hard-coded Werten aufrufst?

qoyanisque
heikob
Beiträge: 81
Registriert: 23. März 2005 23:20

Beitrag von heikob »

Hallo,

deine Vorschläge habe ich bereits alle probiert. Es gelingt mir nicht, die Slider zu verändern. Das die Zuordnung ID->Wert stimmt, habe ich durch die auskommentierte Anweisung zur Ausgabe auf die LCDs überprüft. Dies stimmt alles. Auch hard coded Werte werden nicht übernommen.

Ich verstehe es ja selbst nicht, wieso es einmal funktioniert (LCDs) und einmal nicht (Slider). Achja, da der Thread einwandfrei funktioniert, wurde Qt von SuSE wohl mit Thread-Support übersetzt ;)

Heiko
heikob
Beiträge: 81
Registriert: 23. März 2005 23:20

Beitrag von heikob »

Jetzt ist das Problem wirklich gelöst. Es lag lediglich an meiner Dummheit. Ich habe die Sliders, die vertikal angeordnet sind, mit negativen Werten belegt, damit die 0 unten ist. In Qt kann man das ja sonst nicht machten, oder ich habe zumindest keine andere Lösung gefunden ;)

Also war das ganze Problem mit einem simplen
SliderProgramming[ce->ID()]->setValue(ce->size()*-1);
erledigt. Es könnte manchmal so einfach sein. Dennoch vielen Dank für eure Hilfe

Heiko
Antworten