PDA

View Full Version : Open subwindow from parent window ctor



olidem
13th May 2009, 12:51
Hi!
I have a widget (or QDialog, does not matter) that should in some cases open a getOpenFilename dialog immediately.

But if I do this getOpenFIlename call in the constructor, I get an error... WA_state_created or so.

One Way aroud it i found already is to call

QTimer::singleShow(200, this, SLOT(openFile())

in the end of the constructor but I know that this can make problems and is jsut a hack.

How can I solve this in a stable way?

Is there an event or signal that informs me about when the dialog is ready to execute openFile() slot?

Thanks for your help in advance!

spirit
13th May 2009, 13:10
works fine


Test::Test(QWidget *parent)
: QWidget(parent)
{
QFileDialog::getOpenFileName();
}

another example


Test::Test(QWidget *parent)
: QWidget(parent)
{
QWidget *w = new QWidget();
w->setAttribute(Qt::WA_DeleteOnClose);
w->show();
}

without setting a parent.

talk2amulya
13th May 2009, 13:20
the reason why it doesnt work is that you are providing the constructor class as parent, right? if the dialog's parent isnt created, following assert fails:
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
dont set a parent and it'll work

olidem
13th May 2009, 13:27
Great!
Thanks!
For me it does not make a difference, but as expected, now *before* the parent dialog pops up, the fileopen diag shows, and just after it has been closed, the parent diag is shown.

Just because I am interested:

Would it also be possible to first pop up the parent, and to overlay the fileopen diage then?

This is how it would happen by using my QTimer::singleShot workaround..

spirit
13th May 2009, 13:30
show in main() main window and then show a dialog. e.g.


int main(int argc, char **argv)
{
...
MainWindow mw;
mw.show();
Dialog d;
d.show();
...
}

olidem
13th May 2009, 14:16
Hmm, I think I didn't explain prcisely enough what I mean.

After your first replies, my (working) code looks as follows:



class EditCustomerImageDialog : public QDialog
{
Q_OBJECT

public:
EditCustomerImageDialog(Customer * c, QWidget * parent = 0, Qt::WindowFlags f = 0)
: QDialog(parent, f)
{
//...
openFile();
}
public slots:
void openFile()
{
QString filename = QFileDialog::getOpenFileName(
NULL, tr("Open face image"), "",
tr("Image Files (*.jpg)"));
//...
}
}


If I now open such a dialog from somewhere via


EditCustomerImageDialog d (new Customer);
d.exec();


what happens is that *first*, the openFileName Dialog pops up, nothing else.

*After* having chosen a file, and after the openfilediag has disappeared, then the EditCustomerDialog pops up.

Question:
Can I realise that the EditCustomerDialog pops up, and directly after that, the open FIle diag should pop up ???

spirit
13th May 2009, 14:23
did you try something like this?
main.cpp


...
int main(int argc, char **argv)
{
QApplication app(argc, argv);
EditCustomerImageDialog ecid;
ecid.show();
const QString fileName(QFileDialog::getOpenFileName(
NULL, tr("Open face image"), "",
tr("Image Files (*.jpg)")));
ecid.openFile(fileName);
return app.exec();
}

EditCustomerImageDialog.cpp


class EditCustomerImageDialog : public QDialog
{
Q_OBJECT

public:
EditCustomerImageDialog(Customer * c, QWidget * parent = 0, Qt::WindowFlags f = 0)
: QDialog(parent, f)
{
//...
//openFile();
}
public slots:
void openFile(const QString &fileName = QString())
{
QString tmpFileName = fileName;
if (tmpFileName.isEmpty())
tmpFileName = QFileDialog::getOpenFileName(
NULL, tr("Open face image"), "",
tr("Image Files (*.jpg)"));
//...
}
}

olidem
13th May 2009, 14:28
I know what you mean, but QDialog::show() returns immediately, while my ::exec() realisation blocks the caller. Ok, one can discuss for hours about this, it is a matter of taste, but I like the blocking thing more, also because this is just a modal dialog on top of my app, which is blocked while the dialog is shown.

Thanks again for your support, great people out here!

spirit
13th May 2009, 14:34
ok, another solution
cpp


Test::Test(QWidget *parent)
: QDialog(parent)
{
...
QMetaObject::invokeMethod(this, "showDialog", Qt::QueuedConnection);
...
}

void Test::showDialog()
{
QFileDialog::getOpenFileName(this);
}

h


private slots:
void showDialog();

fifth
13th May 2009, 15:03
For this situation is usually use a single shot timer, put something like


QTimer::singleShot(0, this, SLOT(openFile()));

at the end of your constructor for the main window. A time of zero will fire the slot after your window is visible.

ps Hopefully the above code is correct ;) i don't do much (any?) C++ put I think you'll get the idea.

spirit
13th May 2009, 15:21
For this situation is usually use a single shot timer, put something like


QTimer::singleShot(0, this, SLOT(openFile()));

at the end of your constructor for the main window. A time of zero will fire the slot after your window is visible.

ps Hopefully the above code is correct ;) i don't do much (any?) C++ put I think you'll get the idea.
your code has the same behavior as my, because


The default value for this property is 0. A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.

but I don't use a timer. :)

fifth
13th May 2009, 15:52
but I don't use a timer. :)

You win :p I didn't know about QMetaObject but will probably use your method now. It is more obvious in the code what is happening. ;)

For PyQt, just need to make sure you include the signature for the slot.


class MainWindow(QWidget):
def __init__(self, parent = None):
super(MainWindow, self).__init__(parent)

QMetaObject.invokeMethod(self, "showDialog", Qt.QueuedConnection);

@pyqtSignature("showDialog()")
def showDialog(self):
QFileDialog.getOpenFileName(self)