Chapter 35. Desktop

This chapter reveals the hidden side of desktop applications. You’ll discover how professional Qt developers move logic beyond the main window, use the system tray, and gain full control over the desktop. Approaches that improve user convenience and reduce unnecessary actions will be revealed — without complicating the architecture.

Topics covered include working with QSystemTrayIcon, managing windows without terminating the application, accessing screens via QScreen, centering and restoring window positions, as well as screen capture and integration with system services. Practical examples show how to implement behaviors used by Telegram, Discord, and other mature applications in just a few steps.

Skipping this chapter risks staying at the “ordinary window” level. Those who work with Qt professionally have long been using these techniques in real products.

This chapter includes ready-to-use code examples.

Chapter Self-Check

Why is it necessary to call QApplication::setQuitOnLastWindowClosed(false) for system tray applications?Answer
Correct answer: Without this call, the application will terminate when the main window closes, even though the tray icon should remain active. This allows the application to continue running in the background even when all windows are hidden.
Why is the closeEvent() method overridden in the example and pe->ignore() called instead of standard processing?Answer
Correct answer: This allows hiding the window with the hide() method instead of closing it, preserving the window’s position on screen and internal state for future use. Calling ignore() cancels the standard window closing behavior.
What three mandatory methods of the QSystemTrayIcon class must be called for basic system tray application functionality?Answer
Correct answer: setIcon() to set the icon, setToolTip() for the tooltip, and show() to display the icon in the notification area.
What will happen if a system tray application doesn’t set a context menu via setContextMenu()?Answer
Correct answer: The user won’t be able to interact with the application through right-clicking the tray icon, making the application less functional and potentially difficult to close without the task manager.
Why does Qt6 use screen->grabWindow(0) for screen capture instead of a direct call from QPixmap?Answer
Correct answer: In Qt6, the grabWindow() method was moved to the QScreen class for correct operation with multi-monitor systems. Passing 0 means capturing the entire screen, not a specific window.
Why use Qt::SmoothTransformation when scaling a captured screen image?Answer
Correct answer: This provides smoothing and improves the quality of the scaled image, making it more pleasant to view, especially when significantly reducing the size.
Why is it important to first obtain QGuiApplication::primaryScreen() when centering a window on screen, rather than simply using desktop dimensions?Answer
Correct answer: In multi-monitor systems, each screen has its own geometry and resolution. Getting primaryScreen() ensures the window will be centered on the primary screen rather than getting lost between monitors.
What information should be saved along with window coordinates to correctly restore its position on the next run?Answer
Correct answer: You need to save the screen name via screen->name(), since geometry and the number of screens may change between application runs.
What will happen if you call showMessage() with the fourth parameter as 0 milliseconds?Answer
Correct answer: The message will be shown for the default time determined by the system, which is usually several seconds depending on OS settings.
What is the geometryChanged() signal of the QScreen class used for in real applications?Answer
Correct answer: For tracking screen configuration changes (monitor connection/disconnection, resolution changes) and automatically adapting application window positions and sizes.
Why does the QDesktopServices::openUrl() method return a boolean value?Answer
Correct answer: To indicate whether the system successfully opened the URL or file. This allows handling situations when there’s no suitable browser or program to open the file.
What will happen if you create multiple QSystemTrayIcon objects for one application?Answer
Correct answer: Multiple icons of the same application will appear in the notification area. Although this is technically possible, typically one icon with a menu for different functions is used.
Why use QUrl::fromLocalFile() instead of directly passing a path to openUrl()?Answer
Correct answer: The fromLocalFile() method correctly converts local paths to URL format with the proper scheme (file:///) and properly handles special characters, ensuring cross-platform compatibility.
What practical advantage does using QScreen::screenAt(QPoint) provide in an application with multiple windows?Answer
Correct answer: It allows determining which monitor contains a window or part of it, which is useful for opening child windows on the same screen or applying settings specific to a particular monitor.
Why isn’t the show() method called for the main window in the example’s constructor?Answer
Correct answer: System tray applications typically start minimized, showing only the tray icon. The window becomes visible only when the user explicitly requests it through the context menu.

Practice Assignments

Easy Level

Task Notifier
Create a system tray application that shows a list of tasks (3-4 tasks) in the context menu. When selecting a task from the menu, a notification should appear with the selected task’s text. Add the ability to exit the application through the menu.
Hints: Use QSystemTrayIcon to create the tray icon. Create a QMenu with several QActions for tasks. Connect each action’s triggered() signal to a slot that calls showMessage(). Don’t forget setQuitOnLastWindowClosed(false).

Medium Level

Multi-Monitor Window Manager
Develop an application that displays information about all connected screens (name, resolution, DPI) as a list. When pressing the “Show on Screen N” button, the main window should move to the center of the selected screen. Add the ability to take a screenshot of a specific screen.
Hints: Use QGuiApplication::screens() to get the list of screens. For each screen, display its properties via QScreen::name(), size(), physicalDotsPerInch(). To move the window, calculate the center of the selected screen and use move(). For screenshots, use screen->grabWindow(0).

Hard Level

Smart Timer with System Tray
Create a timer application with system tray support. The user should be able to set time in the main window, start the timer, after which the window automatically hides. The tray icon should change every second (animation or color change), showing progress. When the timer completes, display a notification and open a link to relaxing music via QDesktopServices. Add pause/resume capability through the tray context menu.
Hints: Use QTimer for time countdown. For icon animation, create several images and change them via setIcon(). In the context menu, add actions for pause, resume, and stop. When the timer finishes, call showMessage() and QDesktopServices::openUrl(). Handle the activated() signal of the QSystemTrayIcon class for double-click.

💬 Join the Discussion!

Successfully mastered working with the system tray and screen capture? Have questions about cross-platform differences or QScreen signals?

Share your experience creating background applications, discuss best practices for working with multi-monitor systems, or help other readers understand the peculiarities of QSystemTrayIcon!

Leave a Reply

Your email address will not be published. Required fields are marked *