cosas de qt10

Upload: grissgs

Post on 02-Mar-2018

223 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/26/2019 Cosas de Qt10

    1/6

    Stacked Layouts

    The QStackedLayoutclass lays out a set of child widgets, or "pages", and shows only one at a time, hiding the others from theuser. The QStackedLayoutitself is invisible and provides no intrinsic means for the user to change the page. The small arrowsand the dark gray frame in Figure 6.5are provided by Qt Designer to make the layout easier to design with. For convenience, Qtalso includes QStackedWidget, which provides a QWidgetwith a built-in QStackedLayout.

    Figure 6.5. QStackedLayout

    The pages are numbered from 0. To make a specific child widget visible, we can call setCurrentIndex()with a pagenumber. The page number for a child widget is available using indexOf().

    The Preferences dialog shown in Figure 6.6is an example that uses QStackedLayout. The dialog consists of aQListWidgeton the left and a QStackedLayouton the right. Each item in the QListWidgetcorresponds to a different

    page in the QStackedLayout. Here's the relevant code from the dialog's constructor:

    PreferenceDialog::PreferenceDialog(QWidget *parent) : QDialog(parent){ ... listWidget = new QListWidget; listWidget->addItem(tr("Appearance")); listWidget->addItem(tr("Web Browser")); listWidget->addItem(tr("Mail & News")); listWidget->addItem(tr("Advanced"));

    stackedLayout = new QStackedLayout; stackedLayout->addWidget(appearancePage); stackedLayout->addWidget(webBrowserPage); stackedLayout->addWidget(mailAndNewsPage); stackedLayout->addWidget(advancedPage); connect(listWidget, SIGNAL(currentRowChanged(int)), stackedLayout, SLOT(setCurrentIndex(int)));

    ... listWidget->setCurrentRow(0);}

    Figure 6.6. Two pages of the Preferences dialog

    We create a QListWidgetand populate it with the page names. Then we create a QStackedLayoutand calladdWidget()for each page. We connect the list widget's currentRowChanged(int)signal to the stacked layout'ssetCurrentIndex(int)to implement the page switching and call setCurrentRow()on the list widget at the end of theconstructor to start on page 0.

    150

  • 7/26/2019 Cosas de Qt10

    2/6

    Forms such as this are also very easy to create using Qt Designer:

    1. Create a new form based on one of the "Dialog" templates or on the "Widget" template.

    2. Add a QListWidgetand a QStackedWidgetto the form.

    3. Fill each page with child widgets and layouts.

    (To create a new page, right-click and choose Insert Page; to switch pages, click the tiny left or right arrow located at the topright of the QStackedWidget.)

    4. Lay out the widgets side by side using a horizontal layout.

    5. Connect the list widget's currentRowChanged(int)signal to the stacked widget's setCurrentIndex(int)slot.

    6. Set the value of the list widget's currentRowproperty to 0.

    Since we have implemented page switching using predefined signals and slots, the dialog will exhibit the correct behavior whenpreviewed in Qt Designer.

    For cases where the number of pages is small and likely to remain small, a simpler alternative to using a QStackedWidgetandQListWidgetis to use a QTabWidget.

    151

  • 7/26/2019 Cosas de Qt10

    3/6

    Splitters

    A QSplitteris a widget that contains other widgets. The widgets in a splitter are separated by splitter handles. Users canchange the sizes of a splitter's child widgets by dragging the handles. Splitters can often be used as an alternative to layoutmanagers, to give more control to the user.

    The child widgets of a QSplitterare automatically placed side by side (or one below the other) in the order in which they arecreated, with splitter bars between adjacent widgets. Here's the code for creating the window depicted in Figure 6.7:

    int main(int argc, char *argv[]){ QApplication app(argc, argv);

    QTextEdit *editor1 = new QTextEdit; QTextEdit *editor2 = new QTextEdit; QTextEdit *editor3 = new QTextEdit;

    QSplitter splitter(Qt::Horizontal); splitter.addWidget(editor1); splitter.addWidget(editor2); splitter.addWidget(editor3); ... splitter.show(); return app.exec();}

    Figure 6.7. The Splitter application

    The example consists of three QTextEdits laid out horizontally by a QSplitterwidget this is shown schematically inFigure 6.8. Unlike layout managers, which simply lay out a form's child widgets and have no visual representation, QSplitteris derived from QWidgetand can be used like any other widget.

    Figure 6.8. The Splitter application's widgets

    Complex layouts can be achieved by nesting horizontal and vertical QSplitters. For example, the Mail Client applicationshown in Figure 6.9, consists of a horizontal QSplitterthat contains a vertical QSplitteron its right side. The layout isshown schematically in Figure 6.10.

    Figure 6.9. The Mail Client application

    152

  • 7/26/2019 Cosas de Qt10

    4/6

    Figure 6.10. The Mail Client's splitter layout

    Here's the code in the constructor of the Mail Client application's QMainWindowsubclass:

    MailClient::MailClient(){ ... rightSplitter = new QSplitter(Qt::Vertical); rightSplitter->addWidget(messagesTreeWidget); rightSplitter->addWidget(textEdit); rightSplitter->setStretchFactor(1, 1);

    mainSplitter = new QSplitter(Qt::Horizontal); mainSplitter->addWidget(foldersTreeWidget); mainSplitter->addWidget(rightSplitter);

    mainSplitter->setStretchFactor(1, 1); setCentralWidget(mainSplitter);

    setWindowTitle(tr("Mail Client")); readSettings();}

    After creating the three widgets that we want to display, we create a vertical splitter, rightSplitter, and add the two widgetswe want on the right. Then we create a horizontal splitter, mainSplitter, and add the widget we want it to display on the leftand rightSplitterwhose widgets we want shown on the right. We make mainSplitterthe QMainWindow's centralwidget.

    153

  • 7/26/2019 Cosas de Qt10

    5/6

    When the user resizes a window, QSplitternormally distributes the space so that the relative sizes of the child widgets staythe same. In the Mail Client example, we don't want this behavior; instead, we want the QTreeWidgetand theQTableWidgetto keep their sizes and we want to give any extra space to the QTextEdit. This is achieved by the twosetStretchFactor()calls. The first argument is the 0-based index of the splitter's child widget, and the second argument isthe stretch factor we want to set; the default is 0.

    The first setStretchFactor()call is on rightSplitter, and it sets the widget at position 1 (textEdit) to have astretch factor of 1. The second setStretchFactor()call is on mainSplitter, and it sets the widget at position 1(rightSplitter) to have a stretch factor of 1. This ensures that the textEditwill get any additional space that is available.

    When the application is started, QSplittergives the child widgets appropriate sizes based on their initial sizes (or based ontheir size hint if no initial size is specified). We can move the splitter handles programmatically by calling

    QSplitter::setSizes(). The QSplitterclass also provides a means of saving and restoring its state the next time theapplication is run. Here's the writeSettings()function that saves the Mail Client's settings:

    void MailClient::writeSettings(){ QSettings settings("Software Inc.", "Mail Client");

    settings.beginGroup("mainWindow"); settings.setValue("geometry", saveGeometry()); settings.setValue("mainSplitter", mainSplitter->saveState()); settings.setValue("rightSplitter", rightSplitter->saveState()); settings.endGroup();}

    Here's the corresponding readSettings()function:

    void MailClient::readSettings(){ QSettings settings("Software Inc.", "Mail Client");

    settings.beginGroup("mainWindow"); restoreGeometry(settings.value("geometry").toByteArray()); mainSplitter->restoreState( settings.value("mainSplitter").toByteArray()); rightSplitter->restoreState( settings.value("rightSplitter").toByteArray()); settings.endGroup();}

    Qt Designer fully supports QSplitter. To put widgets into a splitter, place the child widgets approximately in their desiredpositions, select them, and click Form|Lay Out Horizontally in Splitter or Form|Lay Out Vertically in Splitter.

    154

  • 7/26/2019 Cosas de Qt10

    6/6

    Scrolling Areas

    The QScrollAreaclass provides a scrollable viewport and two scroll bars. If we want to add scroll bars to a widget, it is muchsimpler to use a QScrollAreathan to instantiate our own QScrollBars and implement the scrolling functionality ourselves.

    The way to use QScrollAreais to call setWidget()with the widget to which we want to add scroll bars. QScrollAreaautomatically reparents the widget to make it a child of the viewport (accessible through QScrollArea::viewport()) if itisn't already. For example, if we want scroll bars around the IconEditorwidget we developed in Chapter 5(as shown inFigure 6.11), we can write this:

    int main(int argc, char *argv[]){

    QApplication app(argc, argv); IconEditor *iconEditor = new IconEditor; iconEditor->setIconImage(QImage(":/images/mouse.png"));

    QScrollArea scrollArea; scrollArea.setWidget(iconEditor); scrollArea.viewport()->setBackgroundRole(QPalette::Dark); scrollArea.viewport()->setAutoFillBackground(true); scrollArea.setWindowTitle(QObject::tr("Icon Editor"));

    scrollArea.show(); return app.exec();}

    Figure 6.11. Resizing a QScrollArea

    The QScrollArea(shown schematically in Figure 6.12) presents the widget at its current size or uses the size hint if the widgethasn't been resized yet. By calling setWidgetResizable(true), we can tell QScrollAreato automatically resize thewidget to take advantage of any extra space beyond its size hint.

    Figure 6.12. QScrollArea's constituent widgets

    155