[gelöst] Eigener QDialog -> Texte aktualisieren
[gelöst] Eigener QDialog -> Texte aktualisieren
Hallo,
was ich machen will, ist ein eigener Dialog, der aus 3 Texten besteht (QLabels, die mit Hilfe von setText mit verschiedenen Werten belegt sind), und aus 2 ProgressBars.
Jetzt ist es so, dass ich während die ProgressBars durchlaufen (was wunderbar funktioniert) an bestimmten Stellen die Texte der Labels ändern will.
Ich erzeuge mir an den Stellen eine neue QString Variable und möchte das Label mit dem neuen Text belegen. Leider zeigt der Dialog aber durchgehend den ersten Text an, obwohl ich zwischendurch mit setText einen neuen Text für das Label festlege.
Woran könnte das liegen?
Danke schonmal,
Viele Grüße,
Dani
was ich machen will, ist ein eigener Dialog, der aus 3 Texten besteht (QLabels, die mit Hilfe von setText mit verschiedenen Werten belegt sind), und aus 2 ProgressBars.
Jetzt ist es so, dass ich während die ProgressBars durchlaufen (was wunderbar funktioniert) an bestimmten Stellen die Texte der Labels ändern will.
Ich erzeuge mir an den Stellen eine neue QString Variable und möchte das Label mit dem neuen Text belegen. Leider zeigt der Dialog aber durchgehend den ersten Text an, obwohl ich zwischendurch mit setText einen neuen Text für das Label festlege.
Woran könnte das liegen?
Danke schonmal,
Viele Grüße,
Dani
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
Das liegt daran, das die Funktionen alle nach einander durchlaufen.
Eine Funktion fängt an und läuft bis sie zu Ende ist. Ein Progressbar läuft bis er zu Ende ist. Die einzigste Klasse, die ich auswendig weiß ist die HTTP Klasse von Qt, die nicht nach diesen Regeln arbeitet. Die Dokumentation sagt dazu async oder so ähnlich.
Da helfen die Threads, was gerade für einen Progressbar sehr sinnvoll ist. Ein Thread ist ein Unterprozess deines Programmes der unabhängig von dem Hauptprogramm läuft.
QThread name;
name.start();
und vererben um run() eine Funktion zu geben, das steht nochmal ein bischen detaillierter in der Dokumentation zu QThread drin.
Eine Funktion fängt an und läuft bis sie zu Ende ist. Ein Progressbar läuft bis er zu Ende ist. Die einzigste Klasse, die ich auswendig weiß ist die HTTP Klasse von Qt, die nicht nach diesen Regeln arbeitet. Die Dokumentation sagt dazu async oder so ähnlich.
Da helfen die Threads, was gerade für einen Progressbar sehr sinnvoll ist. Ein Thread ist ein Unterprozess deines Programmes der unabhängig von dem Hauptprogramm läuft.
QThread name;
name.start();
und vererben um run() eine Funktion zu geben, das steht nochmal ein bischen detaillierter in der Dokumentation zu QThread drin.
Vielen Dank, das werd ich mir mal anschauen.
Vielleicht kannst du mir folgendes Phänomen erklären:
Wenn ich statt QDialog QProgressDialog nehme und diesem dann die gewünschten Labels und Progressbars hinzufüge, so dass der eigentlich ProgressBar, der schon im QProgressDialog enthalten ist und der Cancel-Button gar nicht angezeigt werden.
Wenn ich dann in diesem "unsichtbaren" ProgressBar setTotalSteps(0) aufrufe, und in den Schritten, wo ich die Texte verändern will mit setProgress diesen "unsichtbaren" ProgressBar einen Fortschritt zuweise, funktioniert es, dass sich die Texte verändern an dieser Stelle.
Deswegen dachte ich, dass es doch mit einem normalen QDialog auch irgendiwe funktionieren müsste.
Danke für deine Hilfe,
viele Grüße,
Dani
Vielleicht kannst du mir folgendes Phänomen erklären:
Wenn ich statt QDialog QProgressDialog nehme und diesem dann die gewünschten Labels und Progressbars hinzufüge, so dass der eigentlich ProgressBar, der schon im QProgressDialog enthalten ist und der Cancel-Button gar nicht angezeigt werden.
Wenn ich dann in diesem "unsichtbaren" ProgressBar setTotalSteps(0) aufrufe, und in den Schritten, wo ich die Texte verändern will mit setProgress diesen "unsichtbaren" ProgressBar einen Fortschritt zuweise, funktioniert es, dass sich die Texte verändern an dieser Stelle.
Deswegen dachte ich, dass es doch mit einem normalen QDialog auch irgendiwe funktionieren müsste.
Danke für deine Hilfe,
viele Grüße,
Dani
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
Nochmal:
Muss ich dann die Abläufe, in denen ich die Texte verändere und neu setzen möchte als Threads deklarieren. Blick da noch nicht ganz durch.
Ich hab hier auch nochmal nen Teil Code, mit dem es nicht funktioniert. (der ohne QThreads)
Und diesen neu zugewiesenen Text möchte ich sofort sichtbar machen. Aber ich verstehe noch nicht ganz, weshalb das an dieser Stelle nicht möglich ist.
Aber dazu habe ich mich vielleicht auch nur zu wenig mit den Eigenschaften von Threads etc. beschäftigt.
Trotzdem danke für Erklärungsversuche.

Muss ich dann die Abläufe, in denen ich die Texte verändere und neu setzen möchte als Threads deklarieren. Blick da noch nicht ganz durch.
Ich hab hier auch nochmal nen Teil Code, mit dem es nicht funktioniert. (der ohne QThreads)
Code: Alles auswählen
.....
prog_dialog=new QProgressDialog(this,"progress",TRUE);
prog_dialog->setGeometry(200,200,300,200);
prog_layout=new QVBoxLayout(prog_dialog);
titel = new QLabel(prog_dialog);
sequenz_titel=new QLabel(prog_dialog);
titel->setText("Fortschrittsanzeige:");
prog_layout->addWidget(titel);
prog_layout->addWidget(sequenz_titel);
sequenz_titel->setText("Gesamtfortschritt:");
int size=filenames.size();
int size_dirs=dirs.size();
if (size!=0) {
bar1=new QProgressBar(3*size+1,prog_dialog);
}
else {
bar1=new QProgressBar(3*size_dirs+1,prog_dialog);
}
prog_layout->addWidget(bar1);
sequenz_index=0;
bar1->show();
schritt_titel=new QLabel(prog_dialog);
prog_layout->addWidget(schritt_titel);
schritt_titel->setText("Aktuelle Sequenz:");
bar2=new QProgressBar(prog_dialog);
prog_layout->addWidget(bar2);
bar2->show();
prog_layout->activate();
prog_dialog->show();
..........
QString s2="Name";
schritt_titel->setText("Aktuelle Sequenz:"+s2);
Und diesen neu zugewiesenen Text möchte ich sofort sichtbar machen. Aber ich verstehe noch nicht ganz, weshalb das an dieser Stelle nicht möglich ist.
Aber dazu habe ich mich vielleicht auch nur zu wenig mit den Eigenschaften von Threads etc. beschäftigt.
Trotzdem danke für Erklärungsversuche.
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
Hi, dein Code sieht umständlicher aus, als er sein könnte. Kommentare im Code.
Code: Alles auswählen
.....
prog_dialog=new QProgressDialog(this,"progress",TRUE);
prog_dialog->setGeometry(200,200,300,200);
prog_layout=new QVBoxLayout(prog_dialog);
titel = new QLabel(prog_dialog);
sequenz_titel=new QLabel(prog_dialog);
titel->setText("Fortschrittsanzeige:");
prog_layout->addWidget(titel);
prog_layout->addWidget(sequenz_titel);
sequenz_titel->setText("Gesamtfortschritt:");
int size=filenames.size();
int size_dirs=dirs.size();
/* if ( !size ) und ohne Klammern? - Naja, das ist wie eine Krankheit immer alles zu verbessern :D */
if (size!=0) {
bar1=new QProgressBar(3*size+1,prog_dialog);
}
else {
bar1=new QProgressBar(3*size_dirs+1,prog_dialog);
}
prog_layout->addWidget(bar1);
sequenz_index=0;
/* Nicht nötig */
// bar1->show();
schritt_titel=new QLabel(prog_dialog);
prog_layout->addWidget(schritt_titel);
schritt_titel->setText("Aktuelle Sequenz:");
bar2=new QProgressBar(prog_dialog);
prog_layout->addWidget(bar2);
/* Ebenfalls nicht nötig */
// bar2->show();
/* Mh, wozu genau ist das? Ich glaube ebenfalls nicht nötig, lass es aber erstmal stehen. */
prog_layout->activate();
/* Wenn du einen Dialog mit exec ausführst, wird der modal=true, was eigentlich der Sinn eines Dialoges ist. Sonst kann man auch gleich ein normales Widget nehmen. */
prog_dialog->show();
/* Was genau passiert denn hier? So wie das aussieht läuft das doch alles prima, wo werden denn die ProgressBars gestartet? */
..........
/* Also wenn das all dein Code ist, sind die ProgressBars still und bewegen sich nicht. Hier kann keines der beschriebenen Probleme liegen... */
QString s2="Name";
/* siehe auch QString::arg() */
schritt_titel->setText("Aktuelle Sequenz:"+s2);
Ok, also da sind ein paar überflüssige Sachen drin. Gut, aber das worauf es mir ankam waren die letzten Zeilen, wo der Text gesetzt wird.
Die ProgressBars laufen eben auch einwandfrei, nur die Texte nicht:
Außerdem hatte ich das Beispiel gepostet, wo es es bei mir funktioniert, weil es das mit QProgressDialog war.
Hier das eigentliche Problem (Sorry):
und hier der relevante Teil der Methode DJPEG, die aufgerufen wird:
Ich gehe in dieser Methode noch durch 3 For-Schleifen, in denen die Prgressbars weiterlaufen und jeweils ein neuer Text angezeigt werden soll.
Ich hoffe, das war jetzt alles ein bisschen verständlicher....
Danke,
viele Grüße,
Dani
Die ProgressBars laufen eben auch einwandfrei, nur die Texte nicht:
Außerdem hatte ich das Beispiel gepostet, wo es es bei mir funktioniert, weil es das mit QProgressDialog war.
Hier das eigentliche Problem (Sorry):
Code: Alles auswählen
/*Mit diesem QProgressDIalog gehts*/
//prog_dialog=new QProgressDialog(this,"progress",TRUE);
prog_dialog=new QDialog(this,"myDialog",TRUE);
prog_dialog->setGeometry(200,200,300,200);
prog_layout=new QVBoxLayout(prog_dialog);
titel = new QLabel(prog_dialog);
sequenz_titel=new QLabel(prog_dialog);
titel->setText("Fortschrittsanzeige:");
prog_layout->addWidget(titel);
prog_layout->addWidget(sequenz_titel);
sequenz_titel->setText("Gesamtfortschritt:");
int size=filenames.size();
bar1=new QProgressBar(3*size+1,prog_dialog);
prog_layout->addWidget(bar1);
sequenz_index=0;
schritt_titel=new QLabel(prog_dialog);
prog_layout->addWidget(schritt_titel);
schritt_titel->setText("Aktuelle Sequenz:");
bar2=new QProgressBar(prog_dialog);
prog_layout->addWidget(bar2);
prog_layout->activate();
prog_dialog->show();
for ( QStringList::Iterator it = filenames.begin(); it != filenames.end(); ++it ) {
D2JPEG(*it,i,1);
}
bar1->setProgress(3*size+1);
Code: Alles auswählen
.........
int p=0;
QString s2="Name Sequenz";
QString text="Aktuelle Sequenz: "+s_2;
DicomImage *image = new DicomImage(eingabe_datei);
int x = image->getFrameCount();
bar2->setTotalSteps(2*x+anzahl-1);
//Dieser Text erscheint nicht, es steht immer noch der alte Wert im LAbel
schritt_titel->setText(text);
HImageArray sequenz;
sequenz_index++;
for (int a=0; a<=x-1; a++) {
bar2->setProgress(p);
bar1->setProgress(sequenz_index);
QString text2=text+"\nFrames werden extrahiert";
//Dieser Text erscheint auch nicht, sondern immer der alte
schritt_titel->setText(text2);
}
.................
Ich hoffe, das war jetzt alles ein bisschen verständlicher....
Danke,
viele Grüße,
Dani
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
Ja, ziemlich klar, hier wird solange gearbeitet, bis es abgelaufen ist:
Und warum er den Text nicht setzt, weil du nicht wartest bis die ProgressBars fertig sind. Du kannst das umgehen wenn du folgendes machst:
Code: Alles auswählen
for ( QStringList::Iterator it = filenames.begin(); it != filenames.end(); ++it ) {
D2JPEG(*it,i,1);
}
Code: Alles auswählen
for (int a=0; a<=x-1; a++) {
bar2->setProgress(p);
bar1->setProgress(sequenz_index);
QString text2=text+"\nFrames werden extrahiert";
//Dieser Text erscheint auch nicht, sondern immer der alte
schritt_titel->setText(text2);
--> qApp -> processEvents();
}
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
Das processEvents ist dafür, dass die GUI flexibel bleibt und ausstehende Abläufe weiterlaufen und wirklich ausgeführt werden, bis der nächste Ablauf kommt. Das processEvents ist eigentlich eine Funktion um Thread Programmierung zu umgehen, allerdings stößt man auf Grenzen, in deinem Beispiel z.B. wenn du einen Abbruch Knopf hättest, der den dialog abbricht, wäre dieser nicht drückbar, bzw. nur mich sehr sehr langer Verzögerung und meistens ist bis dahin der Dialog bereits abgelaufen. Da helfen nur noch Threads, damit die Anwendung benutzbar bleibt, während der Main/Neben Process läuft.