Seite 1 von 1
MainWindow UserEnabled deaktiveren bei Dialog aufruf
Verfasst: 17. Mai 2010 10:41
von mastershybby
Hallo, folgendes Problem habe ich.
Ich will ein Dialog aufrufen, der das MainWindow für den User deaktiviert.
Wird der Dialog mit exec() gestarted ist dies zwar wie gewünscht der Fall, jedoch ist dann das ganze MainWindow deaktiviret (d.h. timers etc. werden ebenfalls deaktiviert) dies sollte nicht sein.
Wird der Dialog mit show() gestarted, läuft das MainWindow weiter aber dann kann der user nicht deaktiviert werden (ich will nicht mit mainWin.setDisable / setEnable arbeiten.)
Hat jemand eine Idee wie ich dies erreichen kann?
Re: MainWindow UserEnabled deaktiveren bei Dialog aufruf
Verfasst: 17. Mai 2010 11:10
von franzf
mastershybby hat geschrieben:Wird der Dialog mit exec() gestarted ist dies zwar wie gewünscht der Fall, jedoch ist dann das ganze MainWindow deaktiviret (d.h. timers etc. werden ebenfalls deaktiviert) dies sollte nicht sein.
Das entspricht nicht der Wahrheit.
Das exec() startet eine neue eventLoop. Die alte läuft noch. Da du sagst Timer werden deaktiviert, hier ein kleiner schneller Test für dich:
win.h
Code: Alles auswählen
#include <QDialog>
#include <QMainWindow>
#include <QDebug>
#include <QPushButton>
class MainWin : public QMainWindow
{
Q_OBJECT
QPushButton *btn;
void timerEvent(QTimerEvent*) {
qDebug() << "Timer";
}
public:
MainWin() {
btn = new QPushButton("Dialog", this);
connect(btn, SIGNAL(clicked()), SLOT(openDlg()));
startTimer(1000);
}
private slots:
void openDlg() {
QDialog dlg;
dlg.exec();
}
};
main.cpp
Code: Alles auswählen
#include <QApplication>
#include "win.h"
int main(int argc, char** argv) {
QApplication app(argc, argv);
MainWin win;
win.show();
return app.exec();
}
Verfasst: 17. Mai 2010 11:26
von mastershybby
Interessant...
mein code sieht wie folg aus:
Code: Alles auswählen
connect(this, SIGNAL(disconnected()), this, SLOT(wait()));
void MainWin::HandlerChangeEvent(HandlerState_t HdlState){
// typedef enum{HdlDisconnected = 0x0, HdlConnecting = 0x1, HdlConnected = 0x2, HdlLineLost = 0x3, HdlError = 0x40} HandlerState_t;
switch(HdlState){
case HdlDisconnected: {
emit disconnected();
}
break;
....
}
void MainWin::wait(){
if(WaitDg == NULL) {
WaitDg = new WaitDialog(this);
WaitDg->exec();
}
}
sobald bei mir der emit kommt läuft die Routine HandlerChangeEvent nicht mehr ab bis ich das WaitDg wieder manuell schliesse.
Das ist für mich nicht ganz nachvollziehbar. Was müsste ich änders? oder wo ist meine Fehlüberlegung?
Verfasst: 17. Mai 2010 13:46
von franzf
Aus dem Codefetzen wird man leider nicht recht schlau...
Woher weißt du, dass HandlerChangeEvent nicht mehr läuft? Schonmal nen qDebug() reingemacht?
Kannst du deinen Code soweit reduzieren, bis ein kompilierbares minimalbeispiel rauskommt (so wie meines mit dem timerEvent()), welches deinen Fehler enthält? Also einfach den Aufbau skizzieren, und alles unnötige Drumherum (verarbeitende Klassen/Methoden, spezielle Widgets/layouts) was nichts mit dem Problem zu tun hat weglassen.
Verfasst: 17. Mai 2010 14:02
von mastershybby
ok hier dein code so abgeändert das der timer nicht mehr started bis der Dialog gschlossen wird.
win.hCode: Alles auswählen
#include <QDialog>
#include <QMainWindow>
#include <QDebug>
#include <QPushButton>
#include <QLineEdit>
class MainWin : public QMainWindow
{
Q_OBJECT
QPushButton *btn;
QLineEdit *le;
void timerEvent(QTimerEvent*) {
qDebug() << "Timer";
}
public:
MainWin() {
btn = new QPushButton("Dialog", this);
connect(btn, SIGNAL(clicked()), SLOT(init()));
}
private slots:
void openDlg() {
QDialog dlg;
dlg.exec();
}
void init(){
openDlg();
startTimer(1000);
}
};
Verfasst: 17. Mai 2010 14:33
von franzf
In wieweit ist der Code jetzt mit deinem Original zu vergleichen? Denn das Problem lässt sich ganz einfach lösen: timer VOR openDlg() starten

Das Problem hier ist, dass QDialog::exec() die aktuelle Funktion blockiert, das heißt alles was hinter dem exec() kommt wartet, bis exec() beendet ist - das passiert erst, wenn der Dialog per done/accept/reject geschlossen wurde. Die events werden aber weiterverarbeitet! Also alle Timer laufen weiter, wenn SIGNAL emitted werden, werden die entsprechend angeschlossenen SLOTS aufgerufen. Das wäre ja grauenhaft, wenn z.B. kein MainWindow::paintEvent mehr aufgerufen würde, und man beim Dialog Verschieben plötzlich nicht gezeichnete Stellen im MainWindow sehen könnte ^^
Lösung: Code umstellen, dass alles was weiter fuinktionieren muss VOR dem Starten des Dialogs angestoßen wird. Wenn du auf bestimmte Eingaben im Dialog warten musst, dann leite von QDialog ab (machst du wahrscheinlich eh schon), gib den Pointer auf dein MainWindow mit (also "this"), und wenn die Eingaben passend getätigt wurden, rufe vom Dialog aus die entsprechende Methode des MainWindow auf - z.B. mainWin->startTimer(1000).
Verfasst: 17. Mai 2010 14:46
von mastershybby
ok ist natürlich klar dass durch die umstellung das "Problem" gelöst wird was jedoch wenn der Aufruf in einem Switch case liegt? dann kann der Code nicht einfach umgestellt werden! Ich bin deshalb hingegangen und habe ein signal definert welches aufgerufen wird. also in etwa so
win.h
Code: Alles auswählen
#include <QDialog>
#include <QMainWindow>
#include <QDebug>
#include <QPushButton>
#include <QLineEdit>
class MainWin : public QMainWindow
{
Q_OBJECT
QPushButton *btn;
QLineEdit *le;
void timerEvent(QTimerEvent*) {
qDebug() << "Timer";
le->setText(le->text().append("a"));
}
public:
MainWin() {
btn = new QPushButton("Dialog", this);
le = new QLineEdit(this);
le->move(0,50);
connect(this, SIGNAL(DLGSIG()), this , SLOT(openDlg()));
connect(btn, SIGNAL(clicked()), this , SLOT(init()));
}
private slots:
void openDlg() {
QDialog dlg;
dlg.exec();
}
void init(){
emit DLGSIG();
startTimer(1000);
}
signals:
void DLGSIG();
};
aber auch dann blockiert das die Funktion! Und das ist für mich nicht logisch.
Das Problem mit der eingabe ist, dass ich eben eigentlich gar keine eingabe habe. Sondern das einzige was ich will: der Dialog soll solange sichtbar sein wie das Programm mit rechnen beschäftig ist. Der Dialog ist also eine "Bitte Warten..."-Dialog. In dieser Zeit darf der User jedoch nichts an den Programm einstellungen vornehmen können -> Userdisable.
Verfasst: 17. Mai 2010 15:12
von franzf
Code: Alles auswählen
connect(this, SIGNAL(DLGSIG()), this , SLOT(openDlg()), Qt::QueuedConnection);

Außerdem könntest du auch hier wieder vor dem "emit" den timer starten.
[Gelöst]
Verfasst: 18. Mai 2010 08:04
von mastershybby
connect(this, SIGNAL(DLGSIG()), this , SLOT(openDlg()), Qt::QueuedConnection);
genau das habe ich gesucht! Vielen Dank franzf!