views:

569

answers:

2

I managed to get a QPushButton to open a new window when pressed by using the following code (just snippets of code):

AppDialog::AppDialog(QWidget *parent)
        : QDialog(parent)
{
    QPushButton *button3 = new QPushButton(tr("Apps"));
    QHBoxLayout *hLayout = new QHBoxLayout;
    hLayout->addWidget(button3);
    setLayout(hLayout);
}


MainWindow::MainWindow()
{
mainMenu = new MainMenu;
setCentralWidget(mainMenu);

app = 0;
readSettings();
}


void MainWindow::AppMenu()
{
    app = new AppDialog(this);
    app->show();
}

This opens in a new window with an "App" button in it. Can anyone let me know if it's possible and how to open the new app dialog in the same window as the original main menu? It should cover the whole window and look like a normal window with the new menu on it. Ideally after this I could add a "back" button of some sort. I guess this is similar to creating a "wizard" type of interface that is used a lot on the installation wizards and stuff like that.

Bryce

EDIT

This is the source code for implementing QStackedWidgets()

MainMenu::MainMenu(QWidget *parent)
        : QDialog(parent)
{
    QStackedLayout *stackedLayout = new QStackedLayout;

    AppDialog *app = new AppDialog;
    progWidget *program = new ProgWidget;

    QStackedWidget *stackedWidget = new QStackedWidget;
    stackedWidget->addWidget(app);
    stackedWidget->addWidget(program);

    stackedWidget->setCurrentIndex(0);

    QVBoxLayout *vLayout = new QVBoxLayout;
    vLayout->addWidget(stackedWidget);

    setLayout(vLayout);
}

Where would I put the signals and slots to change the index? Imaging that the app and program widgets are just a few widgets with some QPushButtons on them. I can get them to display separately but haven't figure out how to change them yet.

+1  A: 

Don't subclass QDialog. Just create a new QWidget, set it up, and replace the widget you want with it. That way a "back" button is trivial: just do another replace.

You could also call QMainWindow::setCentralWidget() with it, if it's appropriate.

Jurily
So that would be something like MainMenu::AppDialog(QWidget *parent) : QDialog(parent)Is that on the right track?
bryce
A `QDialog` creates a new window for itself. You probably want something like `AppDialog(QWidget *parent) : QWidget(parent)`.
Jurily
Yes thank you that worked for the most part. I now have the new button that pops into the window however the other buttons stay where they are. Would I use something like delete to get rid of the old buttons?
bryce
+3  A: 

You might want to look at this question. My answer here is the same... use a QStackedWidget as your main widget, and the stuff you want to be different on each page inside it. (If that is the whole dialog, then make the stacked widget cover the whole dialog). Then you can set the current page of the stacked widget based on whatever logic you want to use, such as clicking a button, and it will hide everything from the previous page and show the new current page.

==EDIT==

To clarify based on your example, you could do something like this:

enum Pages { FIRST, SECOND, LAST };

MainMenu::MainMenu(QWidget *parent)
        : QDialog(parent)
{
    // Create widgets to populate the pages
    QWidget* widgets[3];
    widgets[FIRST] = new QWidget;
    widgets[SECOND] = new QWidget;
    widgets[LAST] = new QWidget;

    // Create buttons to navigate between the pages
    QPushButton* buttons[3];
    buttons[FIRST] = new QPushButton(widgets[FIRST]);
    buttons[FIRST]->setText("Next");
    buttons[FIRST]->setSize(100, 100);
    buttons[FIRST]->show();

    buttons[SECOND] = new QPushButton(widgets[SECOND]);
    buttons[SECOND]->setText("Next");
    buttons[SECOND]->setSize(100, 100);
    buttons[SECOND]->show();

    buttons[LAST] = new QPushButton(widgets[LAST]);
    buttons[LAST]->setText("Start Again");
    buttons[LAST]->setSize(100, 100);
    buttons[LAST]->show();

    // Create stacked widget for the pages
    QStackedWidget *stackedWidget = new QStackedWidget;
    stackedWidget->addWidget(widgets[FIRST]);
    stackedWidget->addWidget(widgets[SECOND]);
    stackedWidget->addWidget(widgets[LAST]);

    stackedWidget->setCurrentIndex(0);

    QVBoxLayout *vLayout = new QVBoxLayout;
    vLayout->addWidget(stackedWidget);

    setLayout(vLayout);

    // Changes a bunch of signals into one signal with an index.
    QSignalMapper *mapper(this);
    for(int i = 0; i < 3; ++i)
    {
        // Each button maps to the next id, with the last one wrapping around.
        mapper->setMapping(buttons[i], (i + 1) % 3);
        // Make the button click connect to the mapper.
        connect(buttons[i], SIGNAL(clicked()), mapper, SLOT(map()));
    }
    // Connect the collected (and slightly transformed) signal to change the page.
    connect(mapper, SIGNAL(mapped(int)), stackedWidget, SLOT(setCurrentIndex(int)));
}
Caleb Huitt - cjhuitt
This looks like it's the exact answer to my problem. Now, how can I implement this. The example in the C++ GUI Programming with Qt4 as well as in the documentation both don't cover much beyond basic implementation. How would I add images or test or buttons to each QStackedWidget?
bryce
@bryce: If you are using designer, it is pretty straightforward. If you are adding via code directly, you would want to make a widget for each page of the stacked widget. Add the objects to the appropriate page as if you were adding them to the main widget. Then add each page to the stacked widget. Note that you only want 1 stacked widget, with multiple pages in the widget.
Caleb Huitt - cjhuitt
Ok thanks, I am straight up coding this so no designer. Will try your suggestions and let you know how it goes, this looks very promising.
bryce
OK I am having a bunch of trouble getting SIGNALs and SLOTs working with this. I managed to figure out the stacked widgets, both can be displayed one and a time by hard-coding setCurrentIndex(). I will try and add the source code to my question above.
bryce
Thank you really helped me out way more than I thought would happen. If you could just help one more time haha. I noticed that with the arrays of buttons (learned about this here.... neat!) I cannot put a button such as the "back" button to go to the main menu on more than one page. If I do the button is ONLY put onto the page where is was last put in order in the source code.
bryce
@bryce: A widget can only be contained in one other widget. For you, that means you either need to design your main window so that the back button isn't in the stack at all, or have a different button on each back that all do the same thing. If you take the second route, you might want to make your own custom base class to use for those widgets, inheriting from QWidget, that has a backToMain() signal in the base widget which could be connected to the back button inside the base class.
Caleb Huitt - cjhuitt