|  | Home · Overviews · Examples

# Qt Jambi Tutorial 6 - Building Blocks Galore!

This example shows how to encapsulate two widgets into a new component and how easy it is to use many widgets. For the first time, we use a custom widget as a child widget.

    public class BlocksGalore extends QWidget
    {
        public BlocksGalore()
        {
            QPushButton quit = new QPushButton(tr("Quit"));
            quit.setFont(new QFont("Times", 18, QFont.Weight.Bold.value()));

            quit.clicked.connect(QApplication.instance(), "quit()");

            QGridLayout grid = new QGridLayout();
            QVBoxLayout layout = new QVBoxLayout();
            layout.addWidget(quit);
            layout.addLayout(grid);
            setLayout(layout);
            setWindowTitle(tr("Building Blocks Galore"));

            for (int row = 0; row < 3; ++row) {

                for (int column = 0; column < 3; ++column) {
                    LCDRange lcdRange = new LCDRange();
                    grid.addWidget(lcdRange, row, column);
                }
            }
        }

        class LCDRange extends QWidget
        {

            public LCDRange()
            {
                QLCDNumber lcd = new QLCDNumber(2);
                lcd.setSegmentStyle(QLCDNumber.SegmentStyle.Filled);

                QSlider slider = new QSlider(Qt.Orientation.Horizontal);
                slider.setRange(0, 99);
                slider.setValue(0);

                slider.valueChanged.connect(lcd, "display(int)");

                QVBoxLayout layout = new QVBoxLayout();
                layout.addWidget(lcd);
                layout.addWidget(slider);
                setLayout(layout);
            }

        }

        public static void main(String args[])
        {
            QApplication.initialize(args);

            BlocksGalore widget = new BlocksGalore();
            widget.show();

            QApplication.exec();
        }
    }

## Line by Line Walkthrough

        class LCDRange extends QWidget
        {

The `LCDRange` widget is a widget without any API. It just has a constructor. This sort of widget is not very useful, so we'll add some API later.

            public LCDRange()
            {
                QLCDNumber lcd = new QLCDNumber(2);
                lcd.setSegmentStyle(QLCDNumber.SegmentStyle.Filled);

                QSlider slider = new QSlider(Qt.Orientation.Horizontal);
                slider.setRange(0, 99);
                slider.setValue(0);

                slider.valueChanged.connect(lcd, "display(int)");

                QVBoxLayout layout = new QVBoxLayout();
                layout.addWidget(lcd);
                layout.addWidget(slider);
                setLayout(layout);
            }

The code in the constructor is lifted straight from the `Blocks` constructor in Chapter 5. The only differences are that the Quit button is left out and the class is renamed.

The `BlocksGalore` class, too, contains no API except a constructor:

    public class BlocksGalore extends QWidget
    {
        public BlocksGalore()
        {
            QPushButton quit = new QPushButton(tr("Quit"));
            quit.setFont(new QFont("Times", 18, QFont.Weight.Bold.value()));

            quit.clicked.connect(QApplication.instance(), "quit()");

The push button that used to be in what is now `LCDRange` has been separated so that we can have one Quit button and many `LCDRange` objects.

            QGridLayout grid = new QGridLayout();
            QVBoxLayout layout = new QVBoxLayout();
            layout.addWidget(quit);
            layout.addLayout(grid);
            setLayout(layout);
            setWindowTitle(tr("Building Blocks Galore"));

We create a QWidget with a QGridLayout that will contain three columns. The QGridLayout automatically arranges its widgets in rows and columns; you can specify the row and column numbers when adding widgets to the layout, and QGridLayout will fit them into the grid.

We use a QVBoxLayout to lay out the Quit button and the grid layout. The QWidget.addLayout() method is similar to the QWidget.addWidget() method, making the given layout a child of the main layout.

We then proceed to create the LCDRange widgets:

            for (int row = 0; row < 3; ++row) {

                for (int column = 0; column < 3; ++column) {
                    LCDRange lcdRange = new LCDRange();
                    grid.addWidget(lcdRange, row, column);
                }
            }
        }

We create nine `LCDRange` widgets, and we arrange them in three rows and three columns. We set the parent of the widgets to the BlocksGalore instance in the constructor. If we didn't, the parent of the widgets would be set when the layout is installed on the widget with setLayout(). For this reason, it might be a good idea to always set a parent to a widget in its constructor.

That's all, folks!

## Running the Application

This program shows how easy it is to use many widgets at a time. Each one behaves like the slider and LCD number in the previous chapter. Again, the difference lies in the implementation.

## Exercises

Initialize each slider with a different/random value on startup.