MainWindow UserEnabled deaktiveren bei Dialog aufruf
-
mastershybby
- Beiträge: 31
- Registriert: 24. Dezember 2008 23:10
MainWindow UserEnabled deaktiveren bei Dialog aufruf
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?
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
Das entspricht nicht der Wahrheit.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 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();
}
};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();
}-
mastershybby
- Beiträge: 31
- Registriert: 24. Dezember 2008 23:10
Interessant...
mein code sieht wie folg aus:
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?
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();
}
}
Das ist für mich nicht ganz nachvollziehbar. Was müsste ich änders? oder wo ist meine Fehlüberlegung?
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.
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.
-
mastershybby
- Beiträge: 31
- Registriert: 24. Dezember 2008 23:10
ok hier dein code so abgeändert das der timer nicht mehr started bis der Dialog gschlossen wird.
win.h
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";
}
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);
}
};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).
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).
-
mastershybby
- Beiträge: 31
- Registriert: 24. Dezember 2008 23:10
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
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.
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();
};
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.
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.
-
mastershybby
- Beiträge: 31
- Registriert: 24. Dezember 2008 23:10
[Gelöst]
genau das habe ich gesucht! Vielen Dank franzf!connect(this, SIGNAL(DLGSIG()), this , SLOT(openDlg()), Qt::QueuedConnection);