21

When I cross-compile Qt 5.8.0 from source myself and use it to build the Qt "Dynamic Layouts" example from Qt Widgets for Microsoft Windows, it looks old-fashioned, as if it were running on Windows 2000, as shown in the left window below. However, if I compile the exact same program using the pre-built mingw-w64-x86_64-qt5-static package (version 5.8.0-1) from MSYS2, it looks like a nice modern Windows application, as shown in the right window below. How can I fix my version of Qt so that GUIs built with it will look nice? Is there a configuration option I am missing?

Left: Qt compiled by me.  Right: Qt compiled by MSYS2 project

One thing to look into is the QWindowsVistaStyle class. I noticed that when I compiled my program in MSYS2, I had to add -luxtheme because that class referred to some functions from there, like GetThemeColor. Those functions are only available in Windows Vista and later. When I cross-compiled using my own Qt on Linux, I didn't need that library, so perhaps that class was somehow disabled in my build.

Cross-compiled Qt build details

I built the cross-compiled Qt and the old-looking Dynamic Layouts example using commit f51d834 of my nixcrpkgs repository. If you look at the code in that commit, it will show you exactly what commands were run to build the mingw-w64 cross-compiler, and build Qt, and build the Qt examples, including Dynamic Layouts. You can build it yourself if you install Nix, download nixcrkpkgs, and then run nix-build -A pkgs.i686-w64-mingw32.qt.base-examples in the nixcrpkgs directory. You can see my build recipe for the Qt package in that commit.

MSYS2 build details

I ran this script in a MINGW64 shell in MSYS2 to build the example and got good results. It relies on the mingw-w64-x86_64-qt5-static package from MSYS2. You can see the build recipe for that package.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • 1
    You need a manifest file: https://stackoverflow.com/questions/37792366/how-to-create-manifest-file-for-qt-standalone-application – Dan Korn Jun 27 '17 at 15:41
  • I'll try this eventually, but the working GUI did not have a manifest file so I am skeptical. And the thing you linked to has nothing to do with themes or styles. – David Grayson Jun 27 '17 at 16:45
  • 1
    Widgets styles are optional when you build Qt. Meaning that you can choose which styles to build and which not to build. Also some styles requires external dependencies and they can be omitted from the build if you do not provide such dependencies. The Windows Vista style does have external dependencies and might have been skipped from your build. To check which styles are available at run time you can call `QStyleFactory::keys()`. – Benjamin T Jun 27 '17 at 18:50
  • Thanks, I looked around in the Qt source files, and `src/widgets/configure.json` in particular. The Windows Vista and XP themes depend on "uxtheme.h". From my config.log, I can see that the test for uxtheme.h is failing, but it doesn't say why. I might need to set `_WIN32_WINNT` in `CFLAGS` or get more details about why that test is failing. – David Grayson Jun 27 '17 at 19:05
  • Manifests have EVERYTHING to do with themes and styles on Windows: https://msdn.microsoft.com/en-us/library/windows/desktop/bb773175%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 – Dan Korn Jun 29 '17 at 01:48
  • 2
    Perhaps Qt draws the styles itself instead of relying on those Windows DLLs to do it. I got things working by configuring Qt correctly; a manifest was never needed. – David Grayson Jun 29 '17 at 03:34

5 Answers5

20

I had the same issue after upgrading from Qt5.9.1 to Qt5.12.

Placing qwindowsvistastyle.dll, which I found to be in Qt\5.12.0\msvc2017_64\plugins\styles, needed to be placed in my applicationDir\styles directory.

Jonathan Owens
  • 216
  • 3
  • 4
  • 2
    Thank you very much! Such an easy solution! Thumb up! –  Jul 12 '19 at 10:38
  • 2
    For those who use CMake, you will need something like this: `install(PROGRAMS "$" DESTINATION platforms )` and `install(PROGRAMS "$" DESTINATION styles )` – Rtbo Mar 05 '20 at 09:54
11

Widgets

Qt-based GUIs will automatically select the default theme depending on your OS. If you want to override it, you are looking for QApplication's setStyle method, which lets you define the style used for your application, regardless of the OS it runs on.

QApplication::setStyle("fusion");

From the documentation, the following are supported:

  • "windows"
  • "fusion"
  • "windowsxp"
  • "macintosh"

The supported themes depend on your platform, and can be extended with plugins.


EDIT: This answer targets situations where the OS is correctly detected by Qt configuration step, and you just want to change the theme used. In the situation described, the incorrect theme was selected, which is fixed in OP's answer.

Qt Quick

If your GUI is based on QtQuick instead of Widgets, you can use QQuickStyle::setStyle("Material"); instead to customize the theme that you want to see used.

For more details, you can look at that documentation page:

Adrien Leravat
  • 2,731
  • 18
  • 32
  • I'll try this eventually, but I'm skeptical because the working GUI did not call `setStyle`. The working GUI used the exact same code as the ugly one. And both GUIs appear to look like "windows". – David Grayson Jun 27 '17 at 16:46
  • If I remember correctly, the left picture you showed is the default old linux style, so applying "windows" style should fix that, by forcing the theme used, instead of letting Qt deduce it. – Adrien Leravat Jun 27 '17 at 16:52
  • 1
    When Qt is built properly, it can deduce the right theme to use; there is no need to force it to use a Windows them when it's compiled for Windows. – David Grayson May 29 '18 at 05:29
  • That's correct, I'll modify my answer to add that general info. Upvoted your last answer, which nicely solves the problem! – Adrien Leravat May 29 '18 at 14:29
5

If you look in the src/widgets/configure.json file from Qt 5.8.0, you can see that it checks for the existence of uxtheme.h, and that uxtheme.h is a precondition for compiling the windowsxp style, which is a precondition for compiling the windowsvista style. By looking in Qt's config.log, I saw that the uxtheme.h test failed. I am not sure why, but it's probably because uxtheme.h cannot be included on its own; you need to include windows.h beforehand. I verified that the windowsxp and windowsvista styles were indeed not enabled by looking in the src/widgets/qtwidgets-config.pri file after configuring Qt. It has a list of styles that are going to get compiled, and windowsvista is not the list.

I tried adding the -style-windowsxp -style-windowsvista options to Qt's configure command, but those options just cause errors because the uxtheme.h test is failing and it is a prerequisite for compiling those themes.

My solution was to apply this patch to Qt 5.8.0 to skip the uxtheme test altogether:

diff -ur qt58-orig/src/widgets/configure.json qt58/src/widgets/configure.json
--- qt58-orig/src/widgets/configure.json        2017-05-28 02:07:07.625626151 -0700
+++ qt58/src/widgets/configure.json     2017-06-27 21:25:52.752628339 -0700
@@ -28,11 +28,6 @@
     },

     "tests": {
-        "uxtheme": {
-            "label": "uxtheme.h",
-            "type": "files",
-            "files": [ "uxtheme.h" ]
-        }
     },

     "features": {
@@ -57,7 +52,7 @@
         },
         "style-windowsxp": {
             "label": "WindowsXP",
-            "condition": "features.style-windows && config.win32 && !config.winrt && tests.uxtheme",
+            "condition": "features.style-windows && config.win32 && !config.winrt",
             "output": [ "styles" ]
         },
         "style-windowsvista": {

I'm not sure why the MSYS2 package worked well, since I don't see any patch like this in their build script.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
3

I had this same issue when upgrading from a static Qt 5.6.3 to static 5.12.0. I solved it after I tried to manually set the "windowsvista" style with QApplication::setStyle() and noticed that it returned null when debugging. It turns out in 5.12.0 the windowsvista style is its own separate plugin and you need to link against plugins/styles/qwindowsvistastyle.lib and add Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin) to the cpp file containing your main function. After that there is no need to manually set the style, it is chosen automatically.

1

I know that this subject is a bit outdated, but i found an easy solution for this problem that still not working in Qt 6

My environment

Windows 11 with QT 6.2.2, CLion with embedded CMake, MSVC 2019 compiler

add this line to the end of your CMakeLists.txt:

add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${QT_INSTALL_PATH}/plugins/styles/qwindowsvistastyle${DEBUG_SUFFIX}.dll" "$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/styles")