FluentUI系列 - 1 - 介绍第一个窗口

news2024/11/27 13:36:51

介绍一个QML的UI库,国人编写,作者也耍知乎。这个UI库确实好用,但是教程基本等于无,个人在使用中顺便记录一下学习内容。这玩意儿也有Pyside6的版本,有需要的可以查看PySide6-FluentUI-QML。

FluentUI库地址​github.com/zhuzichu520/FluentUI

预览程序,可以在上面查看大部分组件

安装

浏览项目的Github页,注意有如下前置需求。

有缺少的可以在Qt目录下的MaintenanceTool.exe里进行安装。

  • Qt Core, Qt Quick, Qt QML, Qt ShaderTool, Qt 5 Compatibility Module. (必备)
  • Qt LinguistTool (optional,for translations)
    • Tips: 在 Qt安装目录\版本\编译环境类型\bin 里
    • 例如:F:\Qt\6.5.2\mingw_64\bin
  • Qt Svg (optional, however essential for Qt 5)

确认前置条件满足后,开始安装,具体步骤参考:

FluentUI:如何在新项目中使用?_哔哩哔哩_bilibili​www.bilibili.com/video/BV1ek4y1N7r8/​编辑

这里要注意git clone有些坑,作者的库里有引用别的库的,clone过程使用如下

cd source
git clone --recursive https://github.com/zhuzichu520/FluentUI.git
cd FluentUI

完成后的FluentUI源码目录

注意检查完成后的framelesshelper与zxing-cpp可能是空的。我写这篇文章的时候,作者的引用的framelesshelper仍然处于NotFound状态, 可能需要直接去clone再放进此目录下。

删除framelesshelper与zxing-cpp文件夹,直接clone:

git clone --recursive https://github.com/zhuzichu520/framelesshelper.git
git clone https://github.com/zhuzichu520/zxing-cpp.git

完成安装后,Qt目录下会有QML模块生成的。路径类似F:\Qt\6.5.2\mingw_64\qml\FluentUI

路径中的版本和编译环境类型来源于图中

第一个程序

  1. 新建一个Qt Quick Application,为了方便可以命名为Tutorial1-FirstWindow

2. 选择前面用来编译FluentUI的Qt版本

3. 如果有选择项,构建方式选cmake而不是qmake或者qbs

新建项目完成后

4. 把之前的FluentUI文件夹丢到项目根目录下

5. 修改CMakeLists.txt, 改完之后类似上面的构建视频的cmakelist

cmake_minimum_required(VERSION 3.16)

# Tutorial1-FirstWindow是项目名, 修改为自己的项目名
project(Tutorial1-FirstWindow VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(FLUENTUI_BUILD_EXAMPLES OFF)
set(FLUENTUI_BUILD_FRAMELESSHEPLER OFF)
find_package(FluentUI)
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)

qt_standard_project_setup()

qt_add_executable(appTutorial1-FirstWindow
    main.cpp
)

qt_add_qml_module(appTutorial1-FirstWindow
    URI Tutorial1-FirstWindow
    VERSION 1.0
    QML_FILES Main.qml
)

# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appTutorial1-FirstWindow PROPERTIES
#    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appTutorial1-FirstWindow
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

target_link_libraries(appTutorial1-FirstWindow
    PRIVATE Qt6::Quick
)

include(GNUInstallDirs)
install(TARGETS appTutorial1-FirstWindow
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

6. 修改Main.qml代码:

import QtQuick
import QtQuick.Window
// 注意这里,如果报错的话可能是前面构建FluentUI失败。检查这种路径F:\Qt\6.5.2\mingw_64\qml\FluentUI
import FluentUI

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    FluFilledButton {
        width: 100
        height: 50
        anchors.centerIn: parent
        text: "HelloWorld"
    }

}

FluFilledButton

使用FluApp与FluWindow

  1. QtCreator右键项目选择添加新文件->Qt Resource File->命名resource
  2. 在项目根目录下新建文件夹qml
  3. qml文件夹内新建文件AppMainWindow.qml
  4. 修改AppMainWindow.qml
import QtQuick 2.15
import FluentUI

FluWindow {

    id: mainWindow

    // 避免双屏情景下的宽度溢出
    minimumWidth: Screen.width * 0.8
    minimumHeight: Screen.desktopAvailableHeight * 0.8
    visible: true
    title: "Helloworld"
    //appBar: undefined

}
  1. 右键resource.qrc->添加现有文件->AppMainWindow.qml

创建完成后的项目

5. 右键resource.qrc下的AppMainWindow-> Copy URL "qrc:/qml/AppMainWindow.qml"

6. 修改Main.qml

import QtQuick
import QtQuick.Window
import FluentUI

Window {

    id: app
    flags: Qt.SplashScreen
    // 一定要是false
    visible: false

    Component.onCompleted: {
        // 初始化FluApp,实质是记录了app这个根组件实例用以获取QQmlEngine
        // 然后从engine中以initialRoute文本找到用户定义的组件.qml(在这里是AppMainWindow.qml)
        // 实例化AppMainWindow,在窗口实例表中对照是否已有相同窗口存在,若存在则会判断launchMode
        // 所以AppMainWindow要继承自FluWindow, 否则必须自行添加Property: _pageRegister 、 argument、 _route、 launchMode
        FluApp.init(app)
        // 相关枚举大部分都在Def.h里
        FluTheme.darkMode = FluThemeType.Light
        // 开启动画
        FluTheme.enableAnimation = true
        // 开启文本本地渲染
        FluTheme.nativeText = true
        // 切换主题色
        // FluTheme.primaryColor = FluColors.Orange
        // 路由表
        FluApp.routes = {
            "/": "qrc:/qml/AppMainWindow.qml"
        }
        // 初始化路径
        FluApp.initialRoute = "/"
        FluApp.run()
    }
}

Ctrl+R运行

FluWindow

图中的FluWindow拥有一个默认的FluAppBar,这个玩意儿是使用Loader动态载入的Component。我遇到过一个bug就是因为window的appbar还没有载入完成,我的canvas组件就依据appBar进行paint导致页面错误。所以可以自定义一个appBar。

这个appBar其实是有与FramelessHelper联动的,我的工作机上FramelessHelper时好时坏,就不无人子弟了。

刚刚AppMainWindow.qml里,取消这一行的注释:

appBar: undefined

后面再加上新的AppBar,整个文件内容:

import QtQuick 2.15
import FluentUI

FluWindow {

    id: mainWindow

    // 避免双屏情景下的宽度溢出
    minimumWidth: Screen.width * 0.8
    minimumHeight: Screen.desktopAvailableHeight * 0.8
    visible: true
    title: "Tutorial1-FirstWindow"
    appBar: undefined

    // 窗口标题栏
    FluAppBar {
        id: title_bar
        title: mainWindow.title
        // 可以在resource.qrc中添加ico,把url复制过来,程序左上角就有图标了
        // icon:"qrc:/example/res/image/favicon.ico"
        anchors {
            top: parent.top
            left: parent.left
            right: parent.right
        }
        showDark: true
        darkText: "Dark Mode"
    }
}

这里点了右上角的dark mode会切换黑/白模式

关闭窗口提示

在AppMainWindow.qml中添加代码

    // 退出软件确认提示框
    FluContentDialog {
        id: dialog_close
        title: "退出"
        message: "确定要退出程序吗?"
        negativeText: "最小化"
        buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton
                     | FluContentDialogType.PositiveButton
        onNegativeClicked: {
            mainWindow.hide()
        }
        positiveText: "退出"
        neutralText: "取消"
        onPositiveClicked: {
            FluApp.exit()
        }
    }

onPositiveClicked这里,如果是1.6.0版本之前的FluentUI,需要写成

            mainWindow.deleteWindow()
            FluApp.closeApp()

现在Ctrl+R运行程序,点击右上角关闭窗口,发现并没有什么不一样

我们查看FluWindow的代码里有:

    Connections{
        target: window
        function onClosing(event){closeListener(event)}
    }
    property var closeListener: function(event){
        if(closeDestory){
            destoryOnClose()
        }else{
            visible = false
            event.accepted = false
        }
    }

我们查看QML的Window 文档会发现

closing(CloseEvent close)

This signal is emitted when the user tries to close the window.
This signal includes a close parameter. The close.accepted property is true by default so that the window is allowed to close; but you can implement an onClosing handler and set close.accepted = false if you need to do something else before the window can be closed.

所以FluWindow的onClosing已经被监听了,会调用closeListener, 我们直接用closeListener就行。

    closeListener:function(event){
        // 打开关闭确认 弹窗
        dialog_close.open()
        // 取消关闭先
        event.accepted = false
    }

完整代码

import QtQuick 2.15
import FluentUI

FluWindow {

    id: mainWindow

    // 避免双屏情景下的宽度溢出
    minimumWidth: Screen.width * 0.8
    minimumHeight: Screen.desktopAvailableHeight * 0.8
    visible: true
    title: "Tutorial1-FirstWindow"
    appBar: undefined

    closeListener: function (event) {
        dialog_close.open()
        // 取消窗口关闭
        event.accepted = false
    }

    // 窗口标题栏
    FluAppBar {
        id: title_bar
        title: mainWindow.title
        // icon:"qrc:/example/res/image/favicon.ico"
        anchors {
            top: parent.top
            left: parent.left
            right: parent.right
        }
        showDark: true
        darkText: "Dark Mode"
    }

    // 退出软件确认提示框
    FluContentDialog {
        id: dialog_close
        title: "退出"
        message: "确定要退出程序吗?"
        negativeText: "最小化"
        buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton
                     | FluContentDialogType.PositiveButton
        onNegativeClicked: {
            mainWindow.hide()
        }
        positiveText: "退出"
        neutralText: "取消"
        onPositiveClicked: {
            FluApp.exit()
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1590595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开关灯---一维数组

直接看题&#xff1a; 开关灯 此题用模拟的复杂度是O(n&#xff09; &#xff0c;其实有更优解就是用完全平方数。但是我不想在C中遇到数学。。。所以用模拟解。 把数组的类型设为bool类型即可&#xff01; AC代码&#xff1a; #include<bits/stdc.h> using namespace …

Unity TMP Inputfield 输入框 框选 富文本 获取真实定位

一、带富文本标签的框选是什么 UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition&#xff0c;开始选择时的光标下标和当前光标下标 对于未添加富文本标签时&#xff0c;直接通过以上两个值&#xff0c;判断一下框选方向&#xff08;前向后/后向前&…

前端 接口返回来的照片太大 加载慢如何解决

现象 解决 1. 添加图片懒加载 背景图懒加载 对背景图懒加载做的解释 和图片懒加载不同&#xff0c;背景图懒加载需要使用 v-lazy:background-image&#xff0c;值设置为背景图片的地址&#xff0c;需要注意的是必须声明容器高度。 <div v-for"img in imageList&quo…

麒麟 V10 离线 安装 k8s 和kuboard

目录 安装文件准备 主机准备 主机配置 修改主机名&#xff08;三个节点分别执行&#xff09; 配置hosts&#xff08;所有节点&#xff09; 关闭防火墙、selinux、swap、dnsmasq(所有节点) 安装依赖包&#xff08;所有节点&#xff09; 系统参数设置(所有节点) 时间同步…

html 引入vue Element ui 的方式

第一种&#xff1a;使用CDN的方式引入 <!--引入 element-ui 的样式&#xff0c;--> <link rel"stylesheet" href"https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <!-- 必须先引入vue&#xff0c; 后使用element-ui --> <…

Pycharm通过配置隧道连接远程服务器

前言&#xff1a; 上篇有说到局域网windows和服务器互通的情况下连接远程pycharm&#xff0c;这次咱们来说下通过跳板机的方式连接服务器如何做到windows远程连接到服务器 1&#xff1a;设置SSH隧道或SSH代理 ssh -L localhost:LOCAL_PORT:FINAL_SERVER_IP:FINAL_SERVER_PORT…

【深度学习】深入探索卷积神经网络:从基础到先进架构”

卷积神经网络&#xff1a;深度学习的视觉之眼 在过去的十年中&#xff0c;深度学习已经彻底改变了我们处理和理解图像、视频及其他视觉媒体的方式。其中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;无疑是这一革命的核心。本文将带您深入了解CNN的基础知识、关键发展…

CentOS 8服务器搭建L2TP服务器(over IPsec)操作指南

正文共&#xff1a;1234 字 14 图&#xff0c;预估阅读时间&#xff1a;2 分钟 之前发过把我自己的服务器搬上公网的文章&#xff08;我用100块钱把物理服务器放到了公网&#xff0c;省了几万块&#xff01;&#xff09;&#xff0c;当时L2TP拨号用的是网络上的解决方案&#x…

MySQL 修改数据

目录 数据插入-insert 不指定列名插入&#xff1a; 插入整行数据 格式&#xff1a; 多行数据插入 格式&#xff1a; 指定列名插入 插入1行 插入多行 更新字段-update 语法&#xff1a; 删除表 语法&#xff1a; 案例&#xff1a; 数据插入-insert INSERT 将数据行…

c++命令行解析开源库cxxopts上手教程

文章目录 cxxopts快速入门1. cmake环境配置2. 定义解析的规则3. 使用例子 cxxopts 简介 cxxopts是一个轻量级的C命令行解析库&#xff0c;它提供了易于使用的API来定义和解析命令行选项。它支持多种类型的选项&#xff0c;并且允许用户自定义选项的处理逻辑。 项目地址&#x…

Unity中支持泰语--没有版权限制

在Unity中支持泰语主要涉及以下几个方面&#xff1a; 选择合适的字体&#xff1a;在Unity中&#xff0c;确保使用支持泰文字符的字体是至关重要的。例如&#xff0c;可以选择使用Noto Serif Thai字体&#xff0c;这是一个支持泰语的字体2。 处理Unity版本问题&#xff1a;某些…

【C++之queue的应用及模拟实现】

C学习笔记---014 C之queue的应用及模拟实现1、queue的简单介绍2、queue的简单接口应用3、queue的模拟实现3.1、queue的结构一般的构建3.2、queue的适配器模式构建3.3、queue的主要接口函数 4、queue的模拟实现完整代码4.1、一般方式4.2、泛型模式 5、queue巩固练习题5.1、最小栈…

软件开发安全备受重视,浙江某运营商引入CWASP认证课程,

​浙江省某大型运营商是一家实力雄厚、服务优质的通信运营商&#xff0c;致力于为全省用户提供优质、高效的通信服务。数字时代&#xff0c;该运营商顺应信息能量融合发展趋势&#xff0c;系统打造以5G、算力网络、能力中台为重点的新型信息基础设施&#xff0c;夯实产业转型升…

VUE_H5页面跳转第三方地图导航,兼容微信浏览器

当前项目是uniapp项目&#xff0c;若不是需要替换uni.showActionSheet选择api onMap(address , organName , longitude 0, latitude 0){var ua navigator.userAgent.toLowerCase();var isWeixin ua.indexOf(micromessenger) ! -1;if(isWeixin) {const mapUrl_tx "…

nacos服务器挂了之后springboot/springcloud服务会挂吗?不会挂(顺便深入源码分析nacos配置中心客户端核心功能实现)

文章目录 nacos挂了之后服务会挂吗&#xff1f;不会挂&#xff08;深入源码分析&#xff09;展开nacos客户端源码找本地缓存配置相关文件客户端内存缓存客户端健康状态获取配置的实现 nacos挂了之后服务会挂吗&#xff1f;不会挂&#xff08;深入源码分析&#xff09; 展开nac…

MATLAB 浮点数 转化为 定点数

a fi(v,s,w,f) 一个 fi 对象&#xff0c;其值为 v&#xff0c;符号性为 s&#xff0c;字长为 w&#xff0c;小数长度为 f。 AD9361 a fi(0.707,1,12,11)

GPT建模与预测实战

代码链接见文末 效果图&#xff1a; 1.数据样本生成方法 训练配置参数&#xff1a; --epochs 40 --batch_size 8 --device 0 --train_path data/train.pkl 其中train.pkl是处理后的文件 因此&#xff0c;我们首先需要执行preprocess.py进行预处理操作&#xff0c;配置参数…

一个开源跨平台嵌入式USB设备协议:TinyUSB

概述 TinyUSB 是一个用于嵌入式系统的开源跨平台 USB 主机/设备堆栈&#xff0c;设计为内存安全&#xff0c;无需动态分配&#xff0c;线程安全&#xff0c;所有中断事件都被推迟&#xff0c;然后在非 ISR 任务函数中处理。查看在线文档以获取更多详细信息。 源码链接&#xff…

【U8+】打开固定资产卡片提示:运行时错误‘91’,未设置对象变量或with block变量。

【问题描述】 用友U8软件&#xff0c;固定资产模中打开某张卡片后&#xff0c; 提示&#xff1a;运行时错误‘91’&#xff0c;未设置对象变量或with block变量。 Ps&#xff1a;但不是所有卡片打开的时候都会提示&#xff0c;有的正常。 【解决方法】 跟踪数据库后&#xff…

基于单片机的智能模拟路灯控制系统

摘 要: 随着电力资源的紧缺,以及光污染和雾霾天气的影响,更智能化的路灯设计对人们的日常生活意义重大。本文的智能路灯控制系统是基于单片机的控制器,通过介绍该系统相应的硬件设计和软件设计,实现定时开关和依具体情况是否需要来开关路灯和进行亮度调节,并且具有自检功能…