25 min read

In this article by Lee Zhi Eng, author of the book, Qt5 C++ GUI Programming Cookbook, we will see how Qt allows us to easily design our program’s user interface through a method which most people are familiar with. Qt not only provides us with a powerful user interface toolkit called Qt Designer, which enables us to design our user interface without writing a single line of code, but it also allows advanced users to customize their user interface components through a simple scripting language called Qt Style Sheets.

(For more resources related to this topic, see here.)

In this article, we will cover the following recipes:

  • Using style sheets with Qt Designer
  • Basic style sheets customization
  • Creating a login screen using style sheet

Use style sheets with Qt Designer

In this example, we will learn how to change the look and feel of our program and make it look more professional by using style sheets and resources. Qt allows you to decorate your GUIs (Graphical User Interfaces) using a style sheet language called Qt Style Sheets, which is very similar to CSS (Cascading Style Sheets) used by web designers to decorate their websites.

How to do it…

  1. The first thing we need to do is open up Qt Creator and create a new project. If this is the first time you have used Qt Creator, you can either click the big button that says New Project with a + sign, or simply go to File | New File or New Project.
  2. Then, select Application under the Project window and select Qt Widgets Application.
  3. After that, click the Choose button at the bottom. A window will then pop out and ask you to insert the project name and its location.
  4. Once you’re done with that, click Next several times and click the Finish button to create the project. We will just stick to all the default settings for now.
  5. Once the project is created, the first thing you will see is the panel with tons of big icons on the left side of the window which is called the Mode Selector panel; we will discuss this more later in the How it works section.
  6. Then, you will also see all your source files listed on the Side Bar panel which is located right next to the Mode Selector panel. This is where you can select which file you want to edit, which, in this case, is mainwindow.ui because we are about to start designing the program’s UI!
  7. Double click mainwindow.ui and you will see an entirely different interface appearing out of nowhere. Qt Creator actually helped you to switch from the script editor to the UI editor (Qt Designer) because it detected .ui extension on the file you’re trying to open.
  8. You will also notice that the highlighted button on the Mode Selector panel has changed from the Edit button to the Design button. You can switch back to the script editor or change to any other tools by clicking one of the buttons located at the upper half of the Mode Selector panel.
  9. Let’s go back to the Qt Designer and look at the mainwindow.ui file. This is basically the main window of our program (as the file name implies) and it’s empty by default, without any widget on it. You can try to compile and run the program by pressing the Run button (green arrow button) at the bottom of the Mode Selector panel, and you will see an empty window popping out once the compilation is complete:

  10. Now, let’s add a push button to our program’s UI by clicking on the Push Button item in the widget box (under the Buttons category) and drag it to your main window in the form editor. Then, keep the push button selected and now you will see all the properties of this button inside the property editor on the right side of your window. Scroll down to somewhere around the middle and look for a property called styleSheet. This is where you apply styles to your widget, which may or may not inherit to its children or grandchildren recursively depending on how you set your style sheet. Alternatively, you can also right click on any widget in your UI at the form editor and select Change Style Sheet from the pop up menu.
  11. You can click on the input field of the styleSheet property to directly write the style sheet code, or click on the button besides the input field to open up the Edit Style Sheet window which has a bigger space for writing longer style sheet code. At the top of the window you can find several buttons such as Add Resource, Add Gradient, Add Color, and Add Font that can help you to kick-start your coding if you don’t remember the properties’ names.

    Let’s try to do some simple styling with the Edit Style Sheet window.

  12. Click Add Color and choose color.
  13. Pick a random color from the color picker window, let’s say, a pure red color. Then click Ok.
  14. Now, you will see a line of code has been added to the text field on the Edit Style Sheet window, which in my case is as follows:

    color: rgb(255, 0, 0);

  15. Click the Ok button and now you will see the text on your push button has changed to a red color.

How it works

Let’s take a bit of time to get ourselves familiar with Qt Designer’s interface before we start learning how to design our own UI:

  1. Menu bar: The menu bar houses application-specific menus which provide easy access to essential functions such as create new projects, save files, undo, redo, copy, paste, and so on. It also allows you to access development tools that come with Qt Creator, such as the compiler, debugger, profiler, and so on.
  2. Widget box: This is where you can find all the different types of widgets provided by Qt Designer. You can add a widget to your program’s UI by clicking one of the widgets from the widget box and dragging it to the form editor.
  3. Mode selector: The mode selector is a side panel that places shortcut buttons for easy access to different tools. You can quickly switch between the script editor and form editor by clicking the Edit or Design buttons on the mode selector panel which is very useful for multitasking. You can also easily navigate to the debugger and profiler tools in the same speed and manner.
  4. Build shortcuts: The build shortcuts are located at the bottom of the mode selector panel. You can build, run, and debug your project easily by pressing the shortcut buttons here.
  5. Form editor: Form editor is where you edit your program’s UI. You can add different widgets to your program by selecting a widget from the widget box and dragging it to the form editor.
  6. Form toolbar: From here, you can quickly select a different form to edit, click the drop down box located above the widget box and select the file you want to open with Qt Designer. Beside the drop down box are buttons for switching between different modes for the form editor and also buttons for changing the layout of your UI.
  7. Object inspector: The object inspector lists out all the widgets within your current .ui file. All the widgets are arranged according to its parent-child relationship in the hierarchy. You can select a widget from the object inspector to display its properties in the property editor.
  8. Property editor: Property editor will display all the properties of the widget you selected either from the object inspector window or the form editor window.
  9. Action Editor and Signals & Slots Editor: This window contains two editors – Action Editor and the Signals & Slots Editor which can be accessed from the tabs below the window. The action editor is where you create actions that can be added to a menu bar or toolbar in your program’s UI.
  10. Output panes: Output panes consist of several different windows that display information and output messages related to script compilation and debugging. You can switch between different output panes by pressing the buttons that carry a number before them, such as 1Issues, 2Search Results, 3Application Output, and so on.

There’s more…

In the previous section, we discussed how to apply style sheets to Qt widgets through C++ coding. Although that method works really well, most of the time the person who is in charge of designing the program’s UI is not the programmer himself, but a UI designer who specializes in designing user-friendly UI. In this case, it’s better to let the UI designer design the program’s layout and style sheet with a different tool and not mess around with the code.

Qt provides an all-in-one editor called the Qt Creator. Qt Creator consists of several different tools, such as script editor, compiler, debugger, profiler, and UI editor. The UI editor, which is also called the Qt Designer, is the perfect tool for designers to design their program’s UI without writing any code. This is because Qt Designer adopted the What-You-See-Is-What-You-Get approach by providing accurate visual representation of the final result, which means whatever you design with Qt Designer will turn out exactly the same when the program is compiled and run.

The similarities between Qt Style Sheets and CSS are as follows:

  • CSS: h1 { color: red; background-color: white;}
  • Qt Style Sheets: QLineEdit { color: red; background-color: white;}
  • As you can see, both of them contain a selector and a declaration block. Each declaration contains a property and a value, separated by a colon.
  • In Qt, a style sheet can be applied to a single widget by calling QObject::setStyleSheet() function in C++ code. For example:
    myPushButton->setStyleSheet("color : blue");
  • The preceding code will turn the text of a button with the variable name myPushButton to a blue color. You can also achieve the same result by writing the declaration in the style sheet property field in Qt Designer. We will discuss more about Qt Designer in the next section.
  • Qt Style Sheets also supports all the different types of selectors defined in CSS2 standard, including Universal selector, Type selector, Class selector, ID selector, and so on, which allows us to apply styling to a very specific individual or group of widgets. For instance, if we want to change the background color of a specific line edit widget with the object name usernameEdit, we can do this by using an ID selector to refer to it:

    QLineEdit#usernameEdit { background-color: blue }

To learn about all the selectors available in CSS2 (which are also supported by Qt Style Sheets), please refer to this document: http://www.w3.org/TR/REC-CSS2/selector.html.

Basic style sheet customization

In the previous example, you learned how to apply a style sheet to a widget with Qt Designer. Let’s go crazy and push things further by creating a few other types of widgets and change their style properties to something bizarre for the sake of learning. This time, however, we will not apply the style to every single widget one by one, but we will learn to apply the style sheet to the main window and let it inherit down the hierarchy to all the other widgets so that the style sheet is easier to manage and maintain in long run.

How to do it…

  1. First of all, let’s remove the style sheet from the push button by selecting it and clicking the small arrow button besides the styleSheet property. This button will revert the property to the default value, which in this case is the empty style sheet.
  2. Then, add a few more widgets to the UI by dragging them one by one from the widget box to the form editor. I’ve added a line edit, combo box, horizontal slider, radio button, and a check box.
  3. For the sake of simplicity, delete the menu bar, main toolbar, and the status bar from your UI by selecting them from the object inspector, right click, and choose Remove. Now your UI should look something similar to this:

  1. Select the main window either from the form editor or the object inspector, then right click and choose Change Stylesheet to open up the Edit Style Sheet.
    border: 2px solid gray;
    border-radius: 10px;
    padding: 0 8px;
    background: yellow;
    
  2. Now what you will see is a completely bizarre-looking UI with everything covered in yellow with a thick border. This is because the precedingstyle sheet does not have any selector, which means the style will apply to the children widgets of the main window all the way down the hierarchy. To change that, let’s try something different:
    QPushButton
    {
      border: 2px solid gray;
      border-radius: 10px;
      padding: 0 8px;
      background: yellow;
    }
    
  3. This time, only the push button will get the style described in the preceding code, and all other widgets will return to the default styling. You can try to add a few more push buttons to your UI and they will all look the same:

  4. This happens because we specifically tell the selector to apply the style to all the widgets with the class called QPushButton. We can also apply the style to just one of the push buttons by mentioningit’s name in thestyle sheet, like so:
    QPushButton#pushButton_3
    {
      border: 2px solid gray;
      border-radius: 10px;
      padding: 0 8px;
      background: yellow;
    }
    
  5. Once you understand this method, we can add the following code to the style sheet :
    QPushButton
    {
      color: red;
      border: 0px;
      padding: 0 8px;
      background: white;
    }
    
    QPushButton#pushButton_2
    {
      border: 1px solid red;
      border-radius: 10px;
    }
    
    QPushButton#pushButton_3
    {
      border: 2px solid gray;
      border-radius: 10px;
      padding: 0 8px;
      background: yellow;
    }
    
  6. What it does is basically change the style of all the push buttons as well as some properties of a specific button named pushButton_2. We keep the style sheet of pushButton_3 as it is. Now the buttons will look like this:

  7. The first set of style sheet will change all widgets of QPushButton type to a white rectangular button with no border and red text. Then the second set of style sheets changes only the border of a specific QPushButton widget by name of pushButton_2. Notice that the background color and text color of pushButton_2 remain as white and red color respectively because we didn’t override them in the second set of style sheet, hence it will follow back the style described in the first set of style sheet since it’s applicable to all QPushButton type widgets. Do notice that the text of the third button has also changed to red because we didn’t describe the color property in the third set of style sheet.
  8. After that, create another set of style using the universal selector, like so:
    * {   background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #fff, stop: 1 #888);   color: rgb(255, 255, 255);   border: 1px solid #ffffff; }
  9. The universal selector will affect all the widgets regardless of their type. Therefore, the preceding style sheet will apply a nice gradient color to all the widgets’ background as well as setting their text as white color and giving them a one-pixel solid outline which is also in white color. Instead of writing the name of the color (that is, white), we can also use the rgb function (rgb(255, 255, 255)) or hex code (#ffffff) to describe the color value.
  10. Just as before, the preceding style sheet will not affect the push buttons because we have already given them their own styles which will override the general style described in the universal selector. Just remember that in Qt, the style which is more specific will ultimately be used when there is more than one style having influence on a widget. This is how the UI will look like now:

How it works

If you are ever involved in web development using HTML and CSS, Qt’s style sheet works exactly the same way as CSS. Style Sheet provides the definitions for describing the presentation of the widgets – what the colors are for each element in the widget group, how thick the border should be, and so on and so forth.

If you specify the name of the widget to the style sheet, it will change the style of a particular push button widget with the name you provide. All the other widgets will not be affected and will remain as the default style.

To change the name of a widget, select the widget either from the form editor or the object inspector and change the property called objectName in the property window. If you have used the ID selector previously to change the style of the widget, changing its object name will break the style sheet and lose the style. To fix this problem, simply change the object name in the style sheet as well.

Creating a login screen using style sheet

Next, we will learn how to put all the knowledge we learned in the previous example together and create a fake graphical login screen for an imaginary operating system. Style sheet is not the only thing you need to master in order to design a good UI. You will also need to learn how to arrange the widgets neatly using the layout system in Qt Designer.

How to do it…

  1. The first thing we need to do is design the layout of the graphical login screen before we start doing anything. Planning is very important in order to produce good software. The following is a sample layout design I made to show you how I imagine the login screen will look. Just a simple line drawing like this is sufficient as long as it conveys the message clearly:

  2. Now that we know exactly how the login screen should look, let’s go back to Qt Designer again.
  3. We will be placing the widgets at the top panel first, then the logo and the login form below it.
  4. Select the main window and change its width and height from 400 and 300 to 800 and 600 respectively because we’ll need a bigger space in which to place all the widgets in a moment.
  5. Click and drag a label under theDisplay Widgets category from the widget box to the form editor.
  6. Change the objectName property of the label to currentDateTime and change its Text property to the current date and time just for display purposes, such as Monday, 25-10-2015 3:14 PM.
  7. Click and drag a push button under the Buttons category to the form editor. Repeat this process one more time because we have two buttons on the top panel. Rename the two buttons to restartButton and shutdownButton respectively.
  8. Next, select the main window and click the small icon button on the form toolbar that says Lay Out Vertically when you mouse-over it. Now you will see the widgets are being automatically arranged on the main window, but it’s not exactly what we want yet.
  9. Click and drag a horizontal layout widget under the Layouts category to the main window.
  10. Click and drag the two push buttons and the text label into the horizontal layout. Now you will see the three widgets being arranged in a horizontal row, but vertically they are located in the middle of the screen. The horizontal arrangement is almost correct, but the vertical position is totally off.
  11. Click and drag a vertical spacer from the Spacers category and place it below the horizontal layout we just created previously (below the red rectangular outline). Now you will see all the widgets are being pushed to the top by the spacer.
  12. Now, place a horizontal spacer between the text label and the two buttons to keep them apart. This will make the text label always stick to the left and the buttons align to the right.
  13. Set both the Horizontal Policy and Vertical Policy properties of the two buttons to Fixed and set the minimumSize property to 55×55. Then, set the text property of the buttons to empty as we will be using icons instead of text. We will learn how to place an icon in the button widgets in the following section:
  14. Now your UI should look similar to this:

Next, we will be adding the logo by using the following steps:

  1. Add a horizontal layout between the top panel and the vertical spacer to serve as a container for the logo.
  2. After adding the horizontal layout, you will find the layout is way too thin in height to be able to add any widget to it. This is because the layout is empty and it’s being pushed by the vertical spacer below it into zero height. To solve this problem, we can set its vertical margin (either layoutTopMargin or layoutBottomMargin) to be temporarily bigger until a widget is added to the layout.
  3. Next, add a label to the horizontal layout that you just created and rename it to logo. We will learn more about how to insert an image into the label to use it as logo in the next section. For now, just empty out the text property and set both its Horizontal Policy and Vertical Policy properties to Fixed. Then, set the minimumSize property to 150×150.
  4. Set the vertical margin of the layout back to zero if you haven’t done so.
  5. The logo now looks invisible, so we will just place a temporary style sheet to make it visible until we add an image to it in the next section. The style sheet is really simple:
    border: 1px solid;
  6. Now your UI should look something similar to this:

Now let’s create the login form by using the following steps:

  1. Add a horizontal layout between the logo’s layout and the vertical spacer. Just as we did previously, set the layoutTopMargin property to a bigger number (that is,100) so that you can add a widget to it more easily.
  2. After that, add a vertical layout inside the horizontal layout you just created. This layout will be used as a container for the login form. Set its layoutTopMargin to a number lower than that of the horizontal layout (that is, 20) so that we can place widgets in it.
  3. Next, right click the vertical layout you just created and choose Morph into -> QWidget. The vertical layout is now being converted into an empty widget. This step is essential because we will be adjusting the width and height of the container for the login form. A layout widget does not contain any properties for width and height, but only margins, due to the fact that a layout will expand toward the empty space surrounding it, which does make sense, considering that it does not have any size properties. After you have converted the layout to a QWidget object, it will automatically inherit all the properties from the widget class and so we are now able to adjust its size to suit our needs.
  4. Rename the QWidget object which we just converted from the layout to loginForm and change both its Horizontal Policy and Vertical Policy properties to Fixed. Then, set the minimumSize property to 350×200.
  5. Since we already placed the loginForm widget inside the horizontal layout, we can now set its layoutTopMargin property back to zero.
  6. Add the same style sheet as the logo to the loginForm widget to make it visible temporarily, except this time we need to add an ID selector in front so that it will only apply the style to loginForm and not its children widgets:
    #loginForm { border: 1px solid; }
  7. Now your UI should look something like this:

We are not done with the login form yet. Now that we have created the container for the login form, it’s time to put more widgets into the form:

  1. Place two horizontal layouts into the login form container. We need two layouts as one for the username field and another for the password field.
  2. Add a label and a line edit to each of the layouts you just added. Change the text property of the upper label to Username: and the one below as Password:. Then, rename the two line edits as username and password respectively.
  3. Add a push button below the password layout and change its text property to Login. After that, rename it as loginButton.
  4. You can add a vertical spacer between the password layout and the login button to distance them slightly. After the vertical spacer has been placed, change its sizeType property to Fixed and change the Height to 5.
  5. Now, select the loginForm container and set all its margins to 35. This is to make the login form look better by adding some space to all its sides.
  6. You can also set the Height property of the username, password, and loginButton widgets to 25 so that they don’t look so cramped.
  7. Now your UI should look something like this:

We’re not done yet! As you can see the login form and the logo are both sticking to the top of the main window due to the vertical spacer below them. The logo and the login form should be placed at the center of the main window instead of the top. To fix this problem use the following steps:

  1. Add another vertical spacer between the top panel and the logo’s layout. This way it will counter the spacer at the bottom which balances out the alignment.
  2. If you think that the logo is sticking too close to the login form, you can also add a vertical spacer between the logo’s layout and the login form’s layout. Set its sizeType property to Fixed and the Height property to 10.
  3. Right click the top panel’s layout and choose Morph into -> QWidget. Then, rename it topPanel. The reason why the layout has to be converted into QWidget because we cannot apply style sheets to a layout, as it doesn’t have any properties other than margins.
  4. Currently you can see there is a little bit of margin around the edges of the main window – we don’t want that. To remove the margins, select the centralWidget object from the object inspector window, which is right under the MainWindow panel, and set all the margin values to zero.
  5. At this point, you can run the project by clicking the Run button (withgreen arrow icon) to see what your program looks like now. If everything went well, you should see something like this:

  6. After we’ve done the layout, it’s time for us to add some fanciness to the UI using style sheets! Since all the important widgets have been given an object name, it’s easier for us to apply the style sheets to it from the main window, since we will only write the style sheets to the main window and let them inherit down the hierarchy tree.
  7. Right click on MainWindow from the object inspector window and choose Change Stylesheet.
  8. Add the following code to the style sheet:
    #centralWidget { background: rgba(32, 80, 96, 100); }
  9. Now you will see that the background of the main window changes its color. We will learn how to use an image for the background in the next section so the color is just temporary.
  10. In Qt, if you want to apply styles to the main window itself, you must apply it to its central widget instead of the main window itself because the window is just a container.
  11. Then, we will add a nice gradient color to the top panel:
    #topPanel { background-color: 
      qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0, y2:0, 
      stop:0 rgba(91, 204, 233, 100), stop:1 rgba(32, 80, 96, 
      100)); }
    
  12. After that, we will apply black color to the login form and make it look semi-transparent. After that, we will also make the corners of the login form container slightly rounded by setting the border-radius property:
    #loginForm
    {
      background: rgba(0, 0, 0, 80);
      border-radius: 8px;
    }
    
  13. After we’re done applying styles to the specific widgets, we will apply styles to the general types of widgets instead:
    QLabel { color: white; }
    QLineEdit { border-radius: 3px; }
    
  14. The style sheets above will change all the labels’ texts to a white color, which includes the text on the widgets as well because, internally, Qt uses the same type of label on the widgets that have text on it. Also, we made the corners of the line edit widgets slightly rounded.
  15. Next, we will apply style sheets to all the push buttons on our UI:
    QPushButton
    {
      color: white;
      background-color: #27a9e3;
      border-width: 0px;
      border-radius: 3px;
    }
    
  16. The preceding style sheet changes the text of all the buttons to a white color, then sets its background color to blue, and makes its corners slightly rounded as well.
  17. To push things even further, we will change the color of the push buttons when we mouse-over it, using the keyword hover:
    QPushButton:hover { background-color: #66c011; }
  18. The preceding style sheet will change the background color of the push buttons to green when we mouse-over. We will talk more about this in the following section.
  19. You can further adjust the size and margins of the widgets to make them look even better.Remember to remove the border line of the login form by removing the style sheet which we applied directly to it earlier.
  20. Now your login screen should look something like this:

How it works

This example focuses more on the layout system of Qt. The Qt layout system provides a simple and powerful way of automatically arranging child widgets within a widget to ensure that they make good use of the available space.

The spacer items used in the preceding example help to push the widgets contained in a layout outward to create spacing along the width of the spacer item. To locate a widget to the middle of the layout, put two spacer items to the layout, one on the left side of the widget and another on the right side of the widget. The widget will then be pushed to the middle of the layout by the two spacers.

Summary

So in this article we saw how Qt allows us to easily design our program’s user interface through a method which most people are familiar with. We also covered the toolkit, Qt Designer, which enables us to design our user interface without writing a single line of code. Finally, we saw how to create a login screen.

For more information on Qt5 and C++ you can check other books by Packt, mentioned as follows:

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here