PDA

View Full Version : QWizard creating objects dynamically



afflictedd2
19th March 2009, 02:32
Hi everyone,

I'm trying to build a wizard in which I specify a number of something, so that when I press next I should get that number of objects in the next screen. Problem is.. If I go back and change that number of objects and press next.. the number of objects will go unchanged. How do I tell QWizard to do this?

This is the simplified code, it runs:


#ifndef CLASSWIZARD_H
#define CLASSWIZARD_H

#include <QWizard>

QT_BEGIN_NAMESPACE
class QCheckBox;
class QGroupBox;
class QLabel;
class QSpinBox;
class QLineEdit;
class QRadioButton;
class QVector<QLineEdit>;
QT_END_NAMESPACE

//! [0]
class ClassWizard : public QWizard
{
Q_OBJECT

public:
ClassWizard(QWidget *parent = 0);
};

class NumObjectsPage : public QWizardPage
{
Q_OBJECT

public:
NumObjectsPage(QWidget *parent = 0);

private:
QLabel *lblNumObjs;
QSpinBox *leNumObjs;
};

class ObjectsPage : public QWizardPage
{
Q_OBJECT

public:
ObjectsPage(QWidget *parent = 0);

protected:
void initializePage();

private:
QVector<QSpinBox*> sbObjs;
QVector<QLabel*> lblObjs;
};

#endif



#include <QtGui>
#include "classwizard.h"

ClassWizard::ClassWizard(QWidget *parent)
: QWizard(parent)
{
addPage(new NumObjectsPage);
addPage(new ObjectsPage);

setWindowTitle(tr("Wizard"));
}


NumObjectsPage::NumObjectsPage(QWidget *parent)
: QWizardPage(parent)
{
lblNumObjs = new QLabel(tr("Number of Objects:"));
leNumObjs = new QSpinBox();
lblNumObjs->setBuddy(leNumObjs);

registerField("numObjs*", leNumObjs);

QGridLayout *layout = new QGridLayout;
layout->addWidget(lblNumObjs, 0, 0);
layout->addWidget(leNumObjs, 0, 1);

setLayout(layout);
}

ObjectsPage::ObjectsPage(QWidget *parent)
: QWizardPage(parent)
{
}

void ObjectsPage::initializePage()
{
QGridLayout *layout = new QGridLayout;
QSpinBox* sbVel = NULL;
QLabel* lblVel = NULL;

QString numLayers = field("numObjs").toString();
int num = numLayers.toInt();

for (int i = 0; i < num; ++i) {
sbVel = new QSpinBox();
lblVel = new QLabel;
lblVel->setText("Capa " + QString::number(i+1));
sbObjs.push_back(sbVel);
lblObjs.push_back(lblVel);
layout->addWidget(lblVel, i, 0);
layout->addWidget(sbVel, i, 1);
}

setLayout(layout);

}



#include <QApplication>
#include "classwizard.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ClassWizard wizard;
wizard.show();
return app.exec();
}

bangqianchen
19th March 2009, 07:56
You Should implement the virtual function cleanupPage() ,and remove all the widget for the first time, I test, It's OK!

initializePage() is called to initialize the page's contents when the user clicks the wizard's Next button. If you want to derive the page's default from what the user entered on previous pages, this is the function to reimplement.
cleanupPage() is called to reset the page's contents when the user clicks the wizard's Back button.
validatePage() validates the page when the user clicks Next or Finish. It is often used to show an error message if the user has entered incomplete or invalid information.
nextId() returns the ID of the next page. It is useful when creating non-linear wizards, which allow different traversal paths based on the information provided by the user.


void ObjectsPage::cleanupPage()
{
QLayout* playout = layout();
delete playout;
}

Lykurg
19th March 2009, 08:03
Hi,


use QWizard::initializePage ( int id ) to get the current QWizardPage via QWizard::page ( int id ).
Get your layout via children() if you use designer or use your pointer. (Don't create a new one!)
Remove/add widgets according to the number


Lykurg

afflictedd2
19th March 2009, 15:58
Hi,


use QWizard::initializePage ( int id ) to get the current QWizardPage via QWizard::page ( int id ).
Get your layout via children() if you use designer or use your pointer. (Don't create a new one!)
Remove/add widgets according to the number


Lykurg

Hmm do you have a snippet of code / example for this. I just can't picture what you're telling me in code.

Lykurg
19th March 2009, 19:31
Ok, i try.
You have 2 pages in an QWizard. Already full designed (in designer) and on the second page is an empty layout for the "something" which number gets defined on page1.


XYZ::initializePage(int id)
{
if (id==1) // page2
{
QWidget *w = page(id);
// finding the layout or when hand coded use the pointer
// to the layout direct
QLayout *layout = w->findChild<QLayout *>("nameSetInDesigner");
// and now populate the "something": cnt is the number;
if (cnt < layout->findChild<Something *>())
{
//remove
Something *smt = layout->findChild<Something *>().last();
layout->removeWidget(smt);
delete smt;
}
else
{
//add
layout->addWidget(new Something(layout));
}
}
}


Not proofed!

afflictedd2
24th March 2009, 16:43
Hi everyone,

This time I'm facing a new problem :\. When I register a field, in the initializePage() I cannot go back and forth again in the wizard because it will attempt to register that field again. Is it possible to unregister a field when I go back?


void ObjectsPage::initializePage()
{
layout = new QGridLayout;
QSpinBox* sbVel = NULL;
QLabel* lblVel = NULL;

QString numLayers = field("numObjs").toString();
int num = numLayers.toInt();

for (int i = 0; i < num; ++i) {
sbVel = new QSpinBox();
sbVel->setMinimum(500);
sbVel->setMaximum(20000);
sbVel->setSingleStep(500);
sbVel->setValue((i+1)*500);

lblVel = new QLabel;
lblVel->setText("Capa " + QString::number(i+1));
sbObjs.push_back(sbVel);
lblObjs.push_back(lblVel);
layout->addWidget(lblVel, i, 0);
layout->addWidget(sbVel, i, 1);
registerField("sbVel" + QString::number(i), sbObjs[i]);
}

setLayout(layout);
}