首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Qt桌面软件的多主题风格界面

Qt桌面软件的多主题风格界面

原创
作者头像
WelSim的小仿真
发布2026-03-20 23:37:48
发布2026-03-20 23:37:48
630
举报
文章被收录于专栏:WELSIMWELSIM

Qt 是全球最流行的跨平台 C++ 图形用户界面(GUI)应用程序开发框架之一。Qt 最强大的特性在于其跨平台能力。开发者编写一次代码,经过重新编译,即可在桌面端(Windows, macOS, Linux),移动端(iOS, Android),和嵌入式(QNX, VxWorks, 各种 RTOS)系统中运行。已经有大量的软件产品,尤其是大型工业软件,都是基于Qt的框架开发而成的。本文从实际开发的角度,讨论如何最优地实现Qt软件的多主题风格界面,尤其是暗色风格。

在开发大型 Qt 桌面程序(如 IDE、工业控制软件或生产力工具)时,界面(UI)不仅仅是“好看”,更关乎长时间操作的舒适度、信息层级的清晰度以及品牌专业感。因此现代大型可视化软件,都实现了多种界面风格,从色彩来区分,常见的有暗色和亮色主题两种风格。亮色通常是默认风格,而暗色风格需要开发人员专门增加相关的功能。虽然一个软件可以拥有无数个界面风格,但是从实用性角度,只需要两个风格:亮色和暗色。

实现方案

在 Qt 中实现多个主题风格,同时这些风格之间还可以动态切换,已经有一些成熟的方案。本文只讨论最常用的两种实现方式:源码和qss文件。

这两种主流方法细节如下:

1. 在C++或Python源代码中设置QStyle

这是最经典的做法。开发者直接在源码中定义不同主题,每个主题定义好颜色。然后通过setStyle和setPalette函数对QApplication进行设置主题即可。这种方法的好处是开发简单迅速,易于维护,开发者只需要和其他Qt代码一起管理风格。但是拓展性较弱,当用户想要自定义某种风格时,必须要有源代码才能实现。对于大型商业软件,尤其是工程类软件,用户很少会自定义界面风格,因此直接在源代码中设置QStyle是一个比较简单高效的方案。大型通用工程仿真软件WELSIM也选择了这种方式。

2. 通过QSS设置QStyleSheet

这是较为灵活且可扩展的做法。通过加载不同的 .qss 文件,配合变量替换(利用正则或 setProperty)实现。优点是与逻辑解耦,样式修改无需重新编译源码,最终用户也可以修改或添加qss文件来实现想要的风格。缺点是渲染性能在极复杂界面下略有损耗;维护与开发过程相对繁琐,需要熟悉qss文件的语法。

亮色vs暗色

亮色和暗色是开发多风格主题最主要的两个色系。浅色风格和操作系统的原生风格比较相似。因此,在开发多风格界面时,主要工作就是是增加暗色主题。这两种主题可以按照用户的需求随时切换,就好比车载大屏幕的地图系统,白天会显示亮色背景,而夜晚会以暗色背景显示。此外,深色界面的桌面软件越来越多,主要是由于对于软件使用者的眼睛和视力保护较为友好,尤其是大型工程软件,用户会长时间的观看电脑屏幕,暗色界面可以有效缓解用户眼睛的疲劳。

很多开发者误以为暗色模式就是简单的“反相”,其实不然。直接将白底黑字翻转为黑底白字会导致极高的对比度,产生“光晕效应”,导致视觉疲劳。这里给出合适的明暗两种风格的配色方案。

暗色主题 (Dark Theme)

  • 背景: 避免使用纯黑色(#000000),建议使用深灰色(如 #121212 或 #1E1E1E)。深灰色能通过阴影展现深度感。
  • 层级: 遵循“越靠前越亮”的原则。底层背景最暗,弹出窗口或浮动面板应稍微亮一点。
  • 文字: 避免纯白色文字(#FFFFFF),建议使用米白或浅灰(如 #E0E0E0),降低刺眼感。

亮色主题 (Light Theme)

  • 背景: 通常选择极浅的灰色(如 #F5F5F5)而非纯白,作为主背景色,将纯白留给编辑区或核心内容区。
  • 对比: 强调通过细腻的边框(Border)而非大面积阴影来区分模块。
  • 色彩平衡: 辅助色(如状态条、图标)应具备足够的饱和度,以免在强光下显得苍白。

值得一提的是,Qt自带的Fusion风格就是很好的主题,内含亮色和暗色两种主题,开发者可以直接以Fusion风格为模板进行开发。

图标

背景色改变后,之前的图标可能不太适用。如在浅色主题背景下设计的图标,在深色背景下就显得非常不明显。因此就需要对图标管理有一个很好的方式。Qt为多风格主题提供了图标的解决方案。常用的方式有三种。

1. 直接使用 QStyle 提供的标准图标,Fusion 风格下会自动适配明暗主题,这是最方便的方式,但是Qt自带的标准图标数量有限,可以满足小型软件的图标需求。对于大型软件,往往开发者还需要增加新的图标。

2. 使用SVG图片的动态变色功能,核心:将 SVG 图标内的固定颜色(如 fill="#000000")改为 fill="currentColor"。Qt 会自动将 currentColor 替换为控件的前景色(palette.color(QPalette::WindowText))。此方案只适用于单调颜色图标,当图标含有2种颜色以上时,难以实现理想颜色。

3. 使用双图标集,一套浅色,另一套深色。这是大型软件常用的方式,虽然需要建立并维护两套图标,但是方式简单,易于维护。且可以实现复杂且好看的图标集。也是WELSIM的亮暗两种风格的图标集方案。

在使用两套图标集时,判断应用当前的主题是否为深色,如果是深色就应用深色图标,反之则使用浅色图标。判断是否为深色主题的方法有多种,对于Qt6.5以上可以用如下方式:

代码语言:javascript
复制
bool isDark() { 
  return qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark; 
}

动态加载图标的方式如下:

代码语言:javascript
复制
void updateIcon() { 
  QString path = isDark() ? ":/icons/icon_dark.svg" : ":/icons/icon_light.svg"; 
  ui->button->setIcon(QIcon(path)); 
}

放置上述updateIcon()函数的位置常常是在信号槽接受函数changeEvent(QEvent *e)中。通过e->type() == QEvent::PaletteChange或e->type() == QEvent::StyleChange来捕捉系统的色彩主题变化。

OpenGL渲染窗口

在很多大型软件中,含有带OpenGL绘图的渲染窗口,此时Qt的默认对QWidget的配色主题,无法自动在OpenGL窗口展现。需要对渲染器进行手动的修改,同步色彩主题。需要对Renderer渲染器的背景色设置,与QWidget的背景色一致。同时对画布的背景和绘画颜色进行设置。

下图所示,前后两个表格在不同颜色下的表现。

以一个VTK实现的图表为例。在同步2维绘图区域时,需要设置Renderer的背景,表格的背景,轴线相关的颜色。最后需要更新渲染器来显示新的主题风格。

给出同步颜色主题的代码如下:

代码语言:javascript
复制
void myWelSimChartPlot::syncVtkThemeWithQtDark(QWidget* qtWidget)
{
    vtkRenderWindow* renderWindow = this->renderWindow();
    vtkRendererCollection* renderers = renderWindow ? renderWindow->GetRenderers() : nullptr;
    vtkRenderer* renderer = renderers ? renderers->GetFirstRenderer() : nullptr;
    if (!qtWidget || !renderer || !renderWindow) return;
    const QPalette palette = qtWidget->palette();
    const QColor bgColor = palette.color(QPalette::Base);
    const QColor fgColor = palette.color(QPalette::WindowText);
    renderer->SetBackground(qColorToVtk(bgColor));
    vtkColor4ub color;
    color.Set(bgColor.red(), bgColor.green(), bgColor.blue(), bgColor.alpha());
    this->chart()->GetBackgroundBrush()->SetColor(color);
    int axisIDs[4] = { vtkAxis::BOTTOM, vtkAxis::TOP, vtkAxis::LEFT, vtkAxis::RIGHT };
    for (unsigned int axisIndex = 0; axisIndex < 4; ++axisIndex)
    {
        int axisID = axisIDs[axisIndex];
        vtkAxis* axis = this->chart()->GetAxis(axisID);
        if (!axis) { assert(0); continue; }
        axis->GetTitleProperties()->SetColor(qColorToVtk(fgColor));
        axis->GetLabelProperties()->SetColor(qColorToVtk(fgColor));
        axis->GetGridPen()->SetColorF(qColorToVtk(borderColor));
        axis->GetPen()->SetColorF(qColorToVtk(fgColor));
    }
    renderWindow->Render();
}

除了二维绘图窗口,OpenGL驱动的三维窗口也可以做相应色彩主题设置。但实际的产品设计中,往往不需要,因为三维窗口会提供其他配色。如图所示,WELSIM的3D渲染窗口支持蓝白渐变,黑色,白色三种背景。用户可以根据需要自行设置3D OpenGL渲染窗口的风格颜色。

总结

现在,一款成熟的大型工程软件,支持多风格主题已经成为一个必备功能。至少具有亮色与暗色两个风格主题。而核心就是实现暗色主题。虽然技术难度不大,但是有大量且琐碎的开发与测试工作,需要一定的开发时间,以及长期的优化与维护。如果已有的代码中有一些局部的修改样式代码,如setStyle, setStyleSheet函数,还需要做相应修改,从易于维护的角度,最好是删除那些局部风格代码。统一由全局风格来管理整个软件的界面。


WelSim与作者不隶属于Qt, 和Qt开发团队与机构没有直接关系。这里引用这些开源软件的名称和图片仅用作技术博客文章与软件使用的参考。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现方案
  • 亮色vs暗色
  • 图标
  • OpenGL渲染窗口
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档