Chapter 9. Modifying the existing UI

Now we want to change the interface of our application and would like to add a new slider that allows the user to modify also the opacity (or alpha) component of the tint.

Adding the alpha slider

First, in the File Groups tab, we select the centralviewbase.ui file and KDevelop will open it in designer. The very first thing we'll do is breaking the layouts. Breaking the layouts? you'll wonder. Yes, that's done in order to be able to say : "Hey, stop managing the way these widgets are positioned because I'm going to add new widgets between them".

Click to select the main widget, and then click on the Break Layout toolbar icon (or from the Layout menu). Now select the groupbox that contains the sliders and break the layout there too. You should note that those two layouts are independent one from the other. The layout of the main widget is a vertical layout, which manages m_label and the groupbox, and the groupbox's layout manages the text labels and the sliders.

Break layout

If you try to add a widget inside another one which has a layout, then you'll be asked if you want to break the layout first in order to be able to add the widget. But you shouldn't be asked because you already broke them manually :).

Break layout?

Now that the layout is broken, you can move up the sliders and labels a bit to free some space for the new slider we'll add. Add an Alpha: text label and a slider which we will call m_alpha (which the user can use to set the alpha or opacity value of the color blend) at the bottom of the groupbox. Please make the range of values for m_alpha from 0 to 100 by changing its properties . Select the groupbox ...

New alpha slider
... and click on the toolbar button to add a grid layout.
New alpha slider

Now you can select the main widget and add the vertical layout.

Adding the color chooser button

Still, we want to make our application prettier, don't we?. So we'll add a KColorButton button with which the user can select the color alternatively via a standard color dialog.


Select it and add it at the right side of the group box (but inside the group box). Oops, do you recognize that dialog? Yes, it's asking you if the layout should be broken or the operation cancelled. We'll choose to break the layout and now we'll remake the layout.

our widget with a KColorButton

We can just add a grid layout to the groupbox as it is, and designer will “automagically” do it right, but we'll use another technique just for the sake of learning a bit more. Unselect any widget that you may have selected, and pressing the Ctrl key in the keyboard, draw a rectangle that covers the text labels and the sliders (not the entire groupbox, and not the kcolorbutton), that will select them. Once the 8 widgets are selected, click on the grid layout, and Designer will generate a grid layout for those widgets. Note that the layout manages it's children, but the layout is not (yet) managed by anyone, so it's quite useless.

an independent grid layout

To fix that, we select the groupbox, and add an horizontal layout. This layout will manage the grid layout and the KColorButton widget, placing them one next to the other.

and an horizontal layout

Note the difference between selecting the groupbox and adding an horizontal layout to selecting the grid layout and the kcolorbutton widget and then adding the horizontal layout. In the first case, the layout will belong to the groupbox, so it will manage the size policies of the groupbox and it will manage (directly or indirectly) all its children. In the second case, we would be adding an independent horizontal layout. You can play with those two ways to do things and use the Preview Form entry to see the differences when resizing the window.

Well, we now select the main widget and add a vertical layout and this way, we've made all the widgets managed by a layout, which is the way things should work (perhaps I should say this is the way things must work to emphasize that you have to do it that way if you want your application to behave correctly).

main layout too

This is nice enough for most people, but not for us! We want to make the KColorButton widget (which we'll call m_colorButton) higher so that it takes all the space in the groupbox. To do so, we will change its size policy. So select m_colorButton and in the Property Editor, open the sizePolicy section and change the vSizeType to Expanding.

Vertical expanding m_colorButton

Hmmm, that's probably not what we wanted. We observe that previously, m_label had an expanding size policy (MinimumExpanding to be precise) while the groupbox didn't care (just had a Preferred policy). Now, the groupbox is expanding too (because m_colorButton is Expanding so it tries to get as much vertical size as it can), and m_label too, so the layout system gives each one of them half the available size which is not what we want. Is there a solution? Of course. In cases like this, you can give two "competing" widgets different stretching factors so that one of them is given more space than the other in case both try to get as much space as possible. This is done via the verticalStretch property. So we increase the verticalStretch property of m_label to make it bigger and that fixes it.

Setting the stretch factor

Ok, now that the look of our widget is nice again, we can open the slot editor and add two new slots, one for the alpha slider (called setAlpha(int) ) and another one that will be called when the user modifies the color in m_colorButton, which we'll call setColor(const QColor &) .

It's time to make the connections, I'll not explain how to do it again, as it's quite easy. Just note that you have to connect the valueChanged(int) signal from m_alpha to the setAlpha(int) slot in our main widget. Don't forget to also connect the changed(const QColor &) signal from m_colorButton to the setColor(const QColor &) slot in our main widget.

More connections

Well, I think that is enough for now, so we'll just save the .ui file, close designer, compile the result and call that s6. Note that in this case, we haven't done anything with kdevelop all that we've done is modifying the user interface with designer and just compiling without changing anything more gives us our new user interface (with all the already working code still working). We'll add the code for the new interface in the next step.