C++ Qt 项目设计:基于C++与Qt的跨平台定时关机/关屏应用开发
基于C++与Qt框架的定时关机与关屏应用开发全攻略
- (一) 项目概述 (Project Overview)
- 1.1 项目需求解析 (Analyzing the Project Requirements)
- 1.2 选择技术栈 (Choosing the Tech Stack)
- 1.3 功能概览 (Function Overview)
- (二) 设计思路 (Design Thinking)
- 2.1 系统架构设计 (System Architecture Design)
- 2.2 功能模块设计 (Functional Module Design)
- 2.3 用户界面设计 (User Interface Design)
- (三) 技术架构与框架选择 (Technical Architecture and Framework Selection)
- 3.1 C++11/14/17/20 特性分析 (Analyzing Features of C++11/14/17/20)
- 3.2 Qt框架选择原因 (Reasons for Choosing Qt Framework)
- 3.3 操作系统 API 和库选择原因 (Reasons for Choosing Operating System API and Libraries)
- (四) 项目结构与设计模式 (Project Structure and Design Patterns)
- 4.1 项目文件结构 (Project File Structure)
- 4.2 设计模式的选择和实现 (Choosing and Implementing Design Patterns)
- 4.2.1 单例模式在项目中的应用与实践 (Singleton Pattern Application and Practice in the Project)
- 4.2.2 命令模式在项目中的应用与实践 (Command Pattern Application and Practice in the Project)
- 4.2.3 工厂方法模式在项目中的应用与实践 (Factory Method Pattern Application and Practice in the Project)
- 4.3 代码规范与风格 (Coding Standard and Style)
- (五) 核心功能详解 (Core Functions Detailed Explanation)
- 5.1 定时关机与倒计时关机 (Timed Shutdown and Countdown Shutdown)
- 5.2 定时关屏与倒计时关屏 (Timed Screen Off and Countdown Screen Off)
- 5.3 实时显示当前时间 (Real-time Display of Current Time)
- 5.4 设置不操作自动关机或关屏幕 (Setting Idle Timeout for Shutdown or Screen Off)
- (六) 项目实战
- 6.1 UML图
- 6.2 项目结构
- 6.3 运行流程图
- 6.4 Cmake设计
- 6.5 工作量评估
- (七) 项目执行流程与耗时 (Project Execution Process and Time Consumption)
- 7.1 开发流程 (Development Process)
- 7.2 测试流程 (Testing Process)
- 7.3 项目耗时分析 (Project Time Consumption Analysis)
- (八) 结语
(一) 项目概述 (Project Overview)
1.1 项目需求解析 (Analyzing the Project Requirements)
在开始我们的项目之前,我们首先需要深入理解项目的需求。在这个项目中,我们需要构建一个使用C++和Qt的跨平台定时关机器。这个关机器需要支持定时关机、倒计时关机、定时关屏、倒计时关屏等多个功能。除此之外,它还需要能够实时显示当前时间,并支持设置多久不操作后自动关机或者关屏幕。最后,这个关机器需要能够在linux和windows系统上运行。
解析这些需求,我们可以归纳出以下几点关键的技术要求:
- 跨平台:应用程序需要能够在linux和windows系统上运行。这就需要我们在设计和编码的过程中需要注意到平台的差异,并采取相应的策略来适应这些差异。
- 定时和倒计时:应用程序需要支持定时和倒计时两种模式。这就需要我们在设计和编码的过程中需要处理时间的计算和转换。
- 关机和关屏:应用程序需要支持关机和关屏两种操作。这就需要我们在设计和编码的过程中需要调用到操作系统的相关接口。
- 实时显示当前时间:应用程序需要能够实时显示当前的时间。这就需要我们在设计和编码的过程中需要处理时间的获取和显示。
- 无操作自动关机或关屏:应用程序需要支持设置多久不操作后自动关机或者关屏。这就需要我们在设计和编码的过程中需要处理用户的操作和时间的计算。
有了这些技术要求,我们就可以开始设计和编码我们的应用程序了。在接下来的部分中,我们将详细介绍这个过程。
1.2 选择技术栈 (Choosing the Tech Stack)
确定了项目需求后,接下来我们需要选择合适的技术栈来实现这些功能。根据我们的需求,我们需要一个能支持跨平台,且能实现定时任务的编程语言,同时考虑到用户界面的设计,我们也需要一个强大的图形用户界面库。因此,我们选择了C++和Qt。
C++(C Plus Plus):C++是一种使用广泛的编程语言,不仅提供了强大的底层操作能力,同时也支持面向对象编程,可以帮助我们更好地组织和管理代码。另外,C++有着良好的性能和强大的库支持,这也是我们选择C++的原因。
- 跨平台:C++代码可以在不同的操作系统和硬件平台上编译运行,符合我们项目的需求。
- 强大的库支持:C++有大量的开源库,可以帮助我们更快地实现项目需求。
- 高效性能:C++是编译型语言,运行效率高,适合需要高性能的应用场景。
Qt:Qt是一个跨平台的C++图形用户界面应用程序开发框架,被广泛用于开发GUI程序,例如Adobe Photoshop也是用Qt开发的。除了GUI程序,Qt也被用于开发非GUI程序,如命令行工具和服务器。- 强大的GUI设计:Qt提供了大量的用户界面组件,可以帮助我们快速设计出美观的用户界面。
- 跨平台:Qt可以在Windows, Linux, macOS等多个平台上运行,符合我们项目的需求。
- 定时器支持:Qt提供了QTimer类,可以方便地进行定时任务。
以上便是我们项目的技术栈:C++和Qt。下一步,我们将详述项目的功能概览。
1.3 功能概览 (Function Overview)
有了清晰的项目需求和适合的技术栈,接下来我们将概述应用程序的功能。这个跨平台定时关机器将包含以下主要功能:
- 定时关机(Timed Shutdown):用户可以设置一个特定的时间点,当达到这个时间点时,计算机会自动关机。这个功能对于在特定时间需要关机的用户很有用,例如在晚上睡觉之前设置一个定时关机。
- 倒计时关机(Countdown Shutdown):用户可以设置一个倒计时的时间,当倒计时结束时,计算机会自动关机。这个功能对于在一段时间后需要关机的用户很有用,例如在下载完成后一定时间内关机。
- 定时关屏(Timed Screen Off):用户可以设置一个特定的时间点,当达到这个时间点时,计算机的屏幕会自动关闭。这个功能对于需要在特定时间节省电能的用户很有用。
- 倒计时关屏(Countdown Screen Off):用户可以设置一个倒计时的时间,当倒计时结束时,计算机的屏幕会自动关闭。这个功能对于需要在一段时间后节省电能的用户很有用。
- 实时显示当前时间(Real-time Display of Current Time):应用程序的界面会实时显示当前的时间,用户可以直观地看到当前的时间。
- 无操作自动关机/关屏(Auto Shutdown/Screen Off When Idle):用户可以设置一个时间,当在这个时间内没有任何操作时,计算机会自动关机或者屏幕会自动关闭。这个功能对于需要在长时间无操作后节省电能的用户很有用。
在设计和编码的过程中,我们将重点考虑如何实现这些功能,并且确保它们能够在linux和windows系统上正常工作。下一章节我们将深入讨论设计思路。
(二) 设计思路 (Design Thinking)
2.1 系统架构设计 (System Architecture Design)
我们的跨平台定时关机器主要有三层架构:用户界面层(User Interface Layer),业务逻辑层(Business Logic Layer)和操作系统接口层(Operating System Interface Layer)。每一层都有自己特定的任务,它们相互协作,以提供一个无缝且友好的用户体验。
在设计过程中,我们借鉴了MVC(Model-View-Controller)模式,一种常见的软件设计模式。MVC模式将系统划分为三个主要部分,从而实现关注点分离,减少部分之间的依赖,使得维护和开发更加容易。
- 用户界面层 (User Interface Layer):该层是用户直接与之交互的部分。它将用户的输入(如键盘和鼠标操作)转换为对业务逻辑层的命令。在我们的案例中,这部分将会用Qt框架来构建,我们会在后面的章节详细讨论。
- 业务逻辑层 (Business Logic Layer):这部分处理用户界面层发送的命令,并进行适当的处理。例如,当用户设置一个新的关机时间,业务逻辑层会检查这个时间是否合理(例如,是否在未来,是否在允许的范围内),然后存储这个时间,以便将来执行关机操作。此外,如果没有用户操作,这一层也会管理自动关机或者关屏的功能。
- 操作系统接口层 (Operating System Interface Layer):这是一个连接业务逻辑层和操作系统的桥梁。当到达预设的关机时间时,业务逻辑层会通过操作系统接口层发送一个关机命令到操作系统。同时,这一层也需要能够获取系统的当前时间,以便业务逻辑层可以显示到用户界面层。
这种分层设计的好处是,如果我们想要支持新的操作系统,我们只需要修改操作系统接口层,而不需要修改业务逻辑层或用户界面层。同样的,如果我们想要修改用户界面,我们也不需要修改其他两层。这种解耦合的设计,使得我们的系统更加灵活,更容易进行修改和扩展。
2.2 功能模块设计 (Functional Module Design)
功能模块设计是设计思路的核心部分,它帮助我们理清业务逻辑并确定项目的主要组成部分。在这个跨平台定时关机器项目中,我们定义了以下几个主要的功能模块:
- 定时关机模块 (Timed Shutdown Module):这是我们应用的核心模块。用户可以设定一个具体的关机时间点,当系统时间达到该点时,程序将通过操作系统接口层发送关机指令。
- 倒计时关机模块 (Countdown Shutdown Module):与定时关机类似,用户可以设定一个倒计时时间(例如30分钟后),当倒计时结束时,程序将发送关机指令。
- 定时关屏与倒计时关屏模块 (Timed Screen Off and Countdown Screen Off Module):这两个模块与定时关机和倒计时关机的功能类似,但是这里的操作是关闭屏幕,而不是关机。
- 实时时间显示模块 (Real-time Time Display Module):为了提供更好的用户体验,我们的应用程序会实时显示当前系统时间。
- 无操作自动关机/关屏模块 (Auto Shutdown/Screen Off When Idle Module):这是一个为了节省电力而设计的模块。用户可以设置一个时限,如果在这个时限内没有任何操作,程序将自动执行关机或关屏操作。
以上这些模块将根据用户界面层的输入在业务逻辑层中进行相应处理,最终通过操作系统接口层反馈给用户。请注意,虽然我们在这里讨论的是关机和关屏功能,但是实际上这个设计可以很容易地扩展到其他操作,例如重启、休眠等。
2.3 用户界面设计 (User Interface Design)
用户界面(User Interface)是用户与程序交互的窗口,设计一个直观且友好的用户界面对于任何软件项目来说都至关重要。在这个定时关机器项目中,我们尽量让界面清晰简洁,方便用户使用。
我们的用户界面设计如下:
- 系统时间显示区域 (System Time Display Area):在界面的顶部,我们有一个显示系统当前时间的区域,它会实时更新,使用户能够随时看到准确的系统时间。
- 关机设置区域 (Shutdown Setting Area):在界面的中部,我们设立了一个关机设置区域。这个区域包含两个部分:定时关机设置和倒计时关机设置。用户可以在这个区域输入想要的关机时间或者倒计时时间。
- 屏幕关闭设置区域 (Screen Off Setting Area):在关机设置区域的下方,我们设立了一个屏幕关闭设置区域。这个区域也包含两个部分:定时关屏设置和倒计时关屏设置。用户可以在这个区域输入想要的屏幕关闭时间或者倒计时时间。
- 无操作设置区域 (Idle Setting Area):在屏幕关闭设置区域的下方,我们设立了一个无操作设置区域。用户可以在这里设置如果多久没有操作就自动关机或者关屏。
- 执行按钮 (Execution Buttons):在界面的底部,我们设置了几个按钮,包括“开始”(Start),“暂停”(Pause)和“取消”(Cancel)。用户可以点击这些按钮来开始定时任务、暂停正在进行的任务,或者完全取消任务。
这样的设计允许用户在一个单一的界面上设置所有的参数,并随时获取系统的当前时间。而且,所有的功能都被明确地标记和组织,使得用户能够直观地理解和使用。
在接下来的章节中,我们将会讲解如何使用Qt框架来实现这个用户界面设计。
(三) 技术架构与框架选择 (Technical Architecture and Framework Selection)
3.1 C++11/14/17/20 特性分析 (Analyzing Features of C++11/14/17/20)
C++作为一种广泛使用的编程语言,随着其版本的更新,为我们提供了许多有用的特性,这些特性极大地提高了我们编程的效率和代码的质量。在我们的项目中,我们将主要使用C++11、C++14、C++17以及C++20的一些重要特性。
1. 自动类型推断(auto):C++11引入了auto关键字,可以让编译器自动推断变量的类型。这不仅可以简化代码,避免复杂类型的书写,还可以提高代码的可读性。
2. 基于范围的for循环 (Range-based for loops):C++11引入了基于范围的for循环,让我们可以更简洁,更安全地遍历一个容器。
3. 智能指针 (Smart Pointers):C++11引入了智能指针,如unique_ptr、shared_ptr等,用于自动管理对象的生命周期,避免了因忘记delete导致的内存泄漏问题。
4. Lambda表达式 (Lambda Expressions):C++11引入的Lambda表达式让我们可以在代码中创建匿名函数,这在很多情况下可以让代码变得更简洁。
5. 并发库 (Concurrency Library):C++11新增了并发库,包括线程、互斥量、条件变量等,大大简化了并发编程的复杂性。
6. 可选值 (std::optional):C++17引入的std::optional可以表示一个可选的值,非常适合用于表示函数可能无法返回值的情况。
7. 结构化绑定 (Structured Binding):C++17的结构化绑定让我们可以方便地解构tuple或结构体。
8. 概念 (Concepts):C++20引入的概念为模板提供了一种新的约束方式,让我们能更好地编写泛型代码。
这些特性的使用,将在我们后续的代码实现中有所展现。在使用这些特性的同时,我们也会确保代码的兼容性,让我们的程序能在各种支持这些C++版本的编译器上正常运行。
3.2 Qt框架选择原因 (Reasons for Choosing Qt Framework)
Qt 是一款跨平台的 C++ 图形用户界面应用程序开发框架。在我们的项目中,我们选择使用 Qt,主要基于以下几个原因:
1. 跨平台性 (Cross-Platform):Qt 支持多种操作系统,包括 Linux、Windows、macOS 等,这对于我们的跨平台定时关机器项目至关重要。
2. 丰富的 GUI 库 (Rich GUI Library):Qt 提供了一套强大的图形用户界面库,可以轻松创建复杂的用户界面。
3. 多线程支持 (Multithreading Support):Qt 提供了 QThread 类用于管理线程,这对于我们实现定时关机功能,处理多任务非常重要。
4. 定时器支持 (Timer Support):Qt 提供了 QTimer 类,方便我们设定定时任务,如倒计时关机或者关屏。
5. 高效的事件处理机制 (Efficient Event Handling Mechanism):Qt 的事件处理机制可以高效地处理各种用户交互事件,如按钮点击,输入框输入等。
6. 简洁的信号槽机制 (Concise Signal-Slot Mechanism):Qt 的信号槽机制使得程序的组件之间可以方便地进行通信,这对于我们实现项目的各个功能模块之间的协调非常有帮助。
在接下来的章节中,我们将详细介绍如何使用 Qt 框架实现我们项目的功能需求。
3.3 操作系统 API 和库选择原因 (Reasons for Choosing Operating System API and Libraries)
关于操作系统层面的任务,比如关闭或休眠屏幕,我们需要选择适合的操作系统 API 或者库来实现。在这个项目中,我们主要会使用以下两种方法:
1. Windows API:
- 丰富的系统管理功能:Windows API 提供了许多系统管理的函数,可以方便地进行系统级的操作,如关闭或休眠屏幕。
- 广泛的社区支持:Windows API 有一个活跃的开发者社区和丰富的文档资源,方便我们查找和使用。
2. D-Bus 通信接口(仅针对 Linux 系统):
- 跨平台的进程间通信:D-Bus 提供了一种简单有效的方式在进程间进行通信,可以方便地与其他系统服务进行交互。
- 与 systemd 集成:在 Linux 系统中,我们可以通过 D-Bus 与 systemd(系统及服务管理器)进行交互,发送关闭或休眠屏幕的命令。
通过上述方法,我们可以在 Windows 和 Linux 系统上实现关屏或休眠屏幕的功能。在后续的章节中,我们将详细讲解如何使用这些工具来实现我们的项目需求。
(四) 项目结构与设计模式 (Project Structure and Design Patterns)
4.1 项目文件结构 (Project File Structure)
在我们的定时关机器项目中,为了保持代码的清晰性和可维护性,我们将项目组织成下面的文件结构:
- src/:该目录下存放所有的源代码文件。其中又包含以下几个子目录:
- core/:存放核心功能模块的代码,包括定时关机,定时关屏,倒计时关机,倒计时关屏等功能的实现。
- utils/:存放通用的工具函数和类,例如处理操作系统相关操作的函数等。
- gui/:存放所有和图形用户界面有关的代码,主要是用 Qt 实现的界面代码。
- include/:该目录下存放所有的头文件。头文件按照其在源代码中的模块进行分类,和 src/ 目录下的结构相似。
- test/:该目录下存放所有的测试代码,用于测试各个模块的功能是否正常。
- doc/:该目录下存放所有的文档,包括需求文档,设计文档,用户手册等。
- resources/:该目录下存放项目中使用的所有资源文件,例如图标,字体等。
- CMakeLists.txt:该文件是项目的构建脚本,用于描述项目的构建过程。
采用这样的项目结构,旨在使我们的项目易于理解,易于维护,并且在功能模块之间保持清晰的界限。同时,通过将相关的文件组织在一起,也使得查找相关代码变得更加方便。
4.2 设计模式的选择和实现 (Choosing and Implementing Design Patterns)
在 Qt 中,我们可以将信号看作是事件发生的通知,而槽可以看作是响应这个事件的处理器。所以在 Qt 中,我们可以用信号槽机制来代替观察者模式。
下面是对23种设计模式可能对此项目的帮助的分析:
设计模式 帮助描述 重要性权重 单例模式 Singleton 管理全局设置信息,确保在程序的任何地方都可以访问到这个全局的设置信息。 9 命令模式 Command 实现各种定时任务的调度和执行,提高了代码的可扩展性和重用性。 8 工厂方法模式 Factory Method 如果有多种定时任务或者关机策略,可以通过工厂方法来创建具体的任务或策略,提高代码的灵活性。 7 抽象工厂模式 Abstract Factory 如果需要支持更多类型的定时任务或者关机策略,可以通过抽象工厂来创建具体的任务或策略,提高代码的灵活性和扩展性。 7 状态模式 State 如果定时任务有多种状态(例如:未开始,进行中,已完成等),可以通过状态模式来管理和转换这些状态。 7 策略模式 Strategy 如果有多种关机或者关屏策略(例如:立即关机,延时关机等),可以通过策略模式来实现这些策略,提高代码的灵活性。 7 桥接模式 Bridge 如果需要在运行时动态地选择或者更换关机或者关屏策略,可以通过桥接模式来实现。 6 组合模式 Composite 如果定时任务可以被组合成更复杂的任务,可以通过组合模式来实现。 5 装饰器模式 Decorator 如果需要给定时任务动态地添加一些额外的功能或者行为,可以通过装饰器模式来实现。 5 其他模式 Other Patterns 对于其他的设计模式,如:访问者模式,迭代器模式,原型模式,解释器模式等,在此项目中可能暂时没有明显的应用场景,其重要性权重相对较低。 1-4
4.2.1 单例模式在项目中的应用与实践 (Singleton Pattern Application and Practice in the Project)
单例模式在我们的项目中主要应用在全局设置信息管理上,具体来说,就是管理定时关机和定时关屏的时间设置。
在项目中,我们创建了一个名为GlobalSettings
的类,它包含了定时关机和定时关屏的时间设置。这个类采用单例模式,保证在程序的任何地方都可以访问到这个全局的设置信息。
GlobalSettings
的实现示例如下:class GlobalSettings { public:static GlobalSettings& getInstance(){static GlobalSettings instance;return instance;}int getShutdownTime() const { return shutdownTime; }void setShutdownTime(int value) { shutdownTime = value; }int getScreenOffTime() const { return screenOffTime; }void setScreenOffTime(int value) { screenOffTime = value; }private:GlobalSettings() = default;~GlobalSettings() = default;GlobalSettings(const GlobalSettings&) = delete;GlobalSettings& operator=(const GlobalSettings&) = delete;int shutdownTime;int screenOffTime; };
单例模式在这里的作用主要有两点:
1. 保证全局唯一访问:我们希望全局的设置信息只有一份,避免出现数据冲突和不一致的情况。通过单例模式,我们可以保证GlobalSettings
的实例在全局范围内只有一份。
2. 提供全局访问点:通过GlobalSettings::getInstance()
方法,我们可以在程序的任何地方都能访问到GlobalSettings
的实例,方便我们在不同模块之间共享和同步设置信息。
通过以上的应用和实践,我们可以看到,单例模式在管理全局唯一实例方面具有非常大的优势,极大地提高了我们项目的效率和稳定性。
4.2.2 命令模式在项目中的应用与实践 (Command Pattern Application and Practice in the Project)
命令模式在我们的项目中主要应用在定时任务的调度和执行上。每个定时任务(如定时关机,定时关屏等)都被封装成一个命令对象,然后被添加到任务队列中等待执行。
在项目中,我们创建了一个名为Command
的基类,并为每种定时任务定义了派生类(如ShutdownCommand
,ScreenOffCommand
等)。每个命令对象都封装了具体的任务执行逻辑。同时,我们还定义了一个Scheduler
类,它负责管理和调度命令的执行。
Command
基类的实现示例如下:class Command { public:virtual ~Command() {}virtual void execute() = 0; // 执行命令的虚函数,由派生类实现 };
ShutdownCommand
派生类的实现示例如下:class ShutdownCommand : public Command { public:void execute() override{// 执行关机操作的代码} };
命令模式在这里的作用主要有两点:
1. 将请求封装成对象:这样我们可以使用对象来参数化其他对象(如调度器),使得我们可以将不同的请求(命令)队列化,存储和传递。
2. 解耦请求的发送者和接收者:命令的发送者(如调度器)只需要知道如何发送请求,而不需要知道如何完成请求。这使得命令的发送者和接收者(执行者)之间的耦合度降低,提高了代码的灵活性。
通过以上的应用和实践,我们可以看到,命令模式在处理请求调度和执行上具有非常大的优势,极大地提高了我们项目的灵活性和扩展性。
4.2.3 工厂方法模式在项目中的应用与实践 (Factory Method Pattern Application and Practice in the Project)
工厂方法模式在我们的项目中主要应用于创建命令对象。根据不同的任务类型,我们需要创建不同类型的命令对象(如
ShutdownCommand
,ScreenOffCommand
等)。为了隐藏命令对象的创建逻辑,我们引入了工厂方法模式。
在项目中,我们创建了一个名为CommandFactory
的类,它提供了一个静态的createCommand
方法,用于根据输入的任务类型,创建相应的命令对象。
CommandFactory
类的实现示例如下:class CommandFactory { public:static std::unique_ptr<Command> createCommand(TaskType type){switch (type){case TaskType::Shutdown:return std::make_unique<ShutdownCommand>();case TaskType::ScreenOff:return std::make_unique<ScreenOffCommand>();// ...default:throw std::invalid_argument("Unsupported task type.");}} };
工厂方法模式在这里的作用主要有两点:
1. 隐藏对象创建逻辑:客户端代码无需关心命令对象是如何创建的,只需通过工厂类创建所需的对象。这使得客户端代码和命令对象的创建逻辑解耦,提高了代码的可维护性。
2. 提高代码的可扩展性:如果我们需要添加新类型的任务,我们只需要添加相应的命令类,然后在工厂类中添加相应的创建逻辑,无需修改客户端代码。
通过以上的应用和实践,我们可以看到,工厂方法模式在处理对象创建的问题上具有非常大的优势,极大地提高了我们项目的可维护性和可扩展性。
4.3 代码规范与风格 (Coding Standard and Style)
在我们的定时关机器项目中,我们遵循一套明确的代码规范和风格,以保持代码的整洁,可读,和一致性。以下是我们遵循的一些主要规范和风格:
1. 命名规范:我们使用明确和描述性的命名,避免使用简写和缩写。对于变量和函数,我们使用小写字母和下划线(_
),例如shutdown_timer
;对于类和结构,我们使用大写字母开头的驼峰命名法,例如ShutdownManager
。
2. 注释规范:我们在代码中充分使用注释,以帮助他人理解代码的功能和工作原理。对于所有的函数和类,我们在其定义处提供文档注释,描述其功能,参数,返回值等信息。
3. 缩进与空格规范:我们采用四个空格的缩进,不使用制表符(Tab)。在运算符两边以及逗号后面,我们都会添加一个空格,以提高代码的可读性。
4. 代码组织规范:我们尽量保持每个文件的长度不超过500行。每个文件只包含一个类或者一组相关的函数和常量。我们也会使用空行来分隔逻辑上相关的代码段。
遵循这些规范和风格,可以帮助我们更容易地阅读和理解代码,也可以使得多人协作更为顺畅。
(五) 核心功能详解 (Core Functions Detailed Explanation)
5.1 定时关机与倒计时关机 (Timed Shutdown and Countdown Shutdown)
这部分我们将详细探讨定时关机与倒计时关机的实现方式。在编程中,如何实现这两个功能的区别在于我们设置系统关机的时机和方式。
(1) 定时关机(Timed Shutdown)是指用户可以自定义一个特定的时间,例如今天的18:00,当系统的时间到达这个设定的时间时,系统将会自动关机。这个功能的核心是定时器(Timer)。在C++和Qt中,我们可以使用QTimer类来实现这个功能。我们需要设定QTimer的timeout信号(Signal),当到达我们设定的时间时,这个信号会被触发,并执行对应的槽函数(Slot Function),在这个函数中,我们将执行系统关机的命令。
(2) 倒计时关机(Countdown Shutdown)是指用户可以自定义一个时间长度,例如30分钟,系统将会在这个时间长度之后自动关机。这个功能的核心同样是定时器(Timer)。但与定时关机不同的是,倒计时关机需要的是一个倒计时器(Countdown Timer)。在Qt中,我们同样可以使用QTimer类来实现,只是我们需要将定时器设定为倒计时模式,并且在槽函数(Slot Function)中执行系统关机的命令。
具体实现时,我们可以根据用户的输入(例如特定的时间或者时间长度)来设置定时器。对于定时关机,我们需要将用户的输入转换为一个具体的时间点,然后设置定时器在这个时间点触发。对于倒计时关机,我们需要将用户的输入转换为一个时间长度,然后设置定时器在这个时间长度后触发。
定时器的触发将会执行一个我们预先定义的槽函数。在这个槽函数中,我们将执行系统关机的命令。对于Windows系统,我们可以使用Qt的QProcess类来调用系统的shutdown命令。对于Linux系统,我们也可以使用QProcess类,但是调用的命令可能会有所不同。
实现这两个功能的关键在于对Qt的QTimer类和QProcess类的理解和运用。QTimer类提供了强大的定时器功能,可以帮助我们在特定的时间触发特定的事件。QProcess类则提供了与系统命令交互的功能,可以帮助我们在程序中执行系统的命令。
下面是一个简单的示例,展示如何在Qt中使用QTimer和QProcess来实现定时关机和倒计时关机的功能:
#include <QTimer> #include <QProcess>// 创建一个定时器 QTimer *timer = new QTimer(this);// 设定定时器的时间,例如设定为18:00 QTime shutdownTime(18, 0); // 计算当前时间到设定时间的毫秒数 int msecs = QTime::currentTime().msecsTo(shutdownTime); if (msecs < 0) {// 如果设定的时间已经过去,那么设定为明天的这个时间msecs += 24 * 60 * 60 * 1000; }// 设定定时器在设定时间后触发 timer->start(msecs);// 当定时器触发时,执行系统的关机命令 connect(timer, &QTimer::timeout, [=]() {// 创建一个QProcess对象QProcess *process = new QProcess(this);// 执行系统的关机命令 #ifdef Q_OS_WINprocess->start("shutdown -s -t 0"); #elseprocess->start("shutdown -h now"); #endif });
这个示例展示了如何在Qt中使用QTimer和QProcess来实现定时关机的功能。倒计时关机的实现方式类似,只是设定定时器的时间需要变为一个时间长度,例如30分钟。
5.2 定时关屏与倒计时关屏 (Timed Screen Off and Countdown Screen Off)
接下来我们将讨论定时关屏和倒计时关屏的功能。这两个功能的实现方式与定时关机和倒计时关机非常类似,主要区别在于执行的系统命令不同。
(1) 定时关屏 (Timed Screen Off):此功能允许用户设定一个特定时间点,到达这个时间点时,系统将自动关闭屏幕。我们依然使用QTimer来实现这个功能,只是在定时器触发时,执行的是关闭屏幕的命令,而非关机命令。
(2) 倒计时关屏 (Countdown Screen Off):此功能允许用户设定一段时间长度,这段时间过后,系统将自动关闭屏幕。这与倒计时关机的实现方式一样,也是使用QTimer作为倒计时器,在倒计时结束时,执行关闭屏幕的命令。
在实现定时关屏和倒计时关屏的功能时,我们需要注意的一个关键问题是:在不同的操作系统中,关闭屏幕的命令是不同的。例如,在Windows系统中,我们可以使用SendMessage函数发送一个关屏消息。在Linux系统中,我们则需要通过调用xset命令来关闭屏幕。因此,在编写程序时,我们需要根据当前的操作系统来选择正确的命令。
下面是一个在Qt中实现定时关屏的简单示例:
#include <QTimer> #include <QProcess>// 创建一个定时器 QTimer *timer = new QTimer(this);// 设定定时器的时间,例如设定为18:00 QTime screenOffTime(18, 0); // 计算当前时间到设定时间的毫秒数 int msecs = QTime::currentTime().msecsTo(screenOffTime); if (msecs < 0) {// 如果设定的时间已经过去,那么设定为明天的这个时间msecs += 24 * 60 * 60 * 1000; }// 设定定时器在设定时间后触发 timer->start(msecs);// 当定时器触发时,执行关闭屏幕的命令 connect(timer, &QTimer::timeout, [=]() {// 创建一个QProcess对象QProcess *process = new QProcess(this);// 执行关闭屏幕的命令 #ifdef Q_OS_WINprocess->start("powershell", QStringList() << "-Command" << "Add-Type -TypeDefinition \"[DllImport(\\\"user32.dll\\\")] public static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);\"; [PInvoke]::SendMessage(-1, 0x0112, 0xF170, 2)"); #elseprocess->start("xset dpms force off"); #endif });
该代码示例展示了如何在Qt中使用QTimer和QProcess来实现定时关屏的功能。倒计时关屏的实现方式与定时关屏类似,唯一的区别是设定QTimer的时间需要变为用户设定的时间长度,例如30分钟。
这两个功能的实现需要对Qt的QTimer类和QProcess类有深入理解。QTimer类提供了强大的定时器功能,可以在特定的时间触发特定的事件。QProcess类则可以执行系统的命令,这在这个场景中非常有用,因为我们需要执行关闭屏幕的命令。
实现这两个功能的过程中,我们还需要注意系统命令的区别。在不同的操作系统中,关闭屏幕的命令可能是不同的,因此我们需要根据当前的操作系统来选择合适的命令。在Windows系统中,我们可以使用powershell发送关屏消息,而在Linux系统中,我们可以使用xset命令来关闭屏幕。在编写程序时,我们需要根据这些差异来正确的实现这两个功能。
在实现这两个功能的过程中,你可能会遇到一些问题,例如定时器的设定时间可能会有误差,或者关闭屏幕的命令可能在某些系统中无法正常工作。在遇到这些问题时,你需要有足够的耐心和决心去解决这些问题,这是我们作为开发者的职责和挑战。但是,我相信通过不断的努力和学习,你一定能够成功实现这两个功能,并为你的用户提供一个稳定、可靠的定时关机和定时关屏的服务。
5.3 实时显示当前时间 (Real-time Display of Current Time)
在我们的定时关机器中,实时显示当前时间是一个重要的功能。实时显示的当前时间不仅可以让用户有一个清晰的时间感知,也方便用户进行定时关机或关屏的设置。接下来,我们将详细解析这个功能的设计与实现过程。
首先,我们需要创建一个专门用于显示时间的Qt窗口部件(Widget)。在Qt中,我们可以选择使用QLabel
类来创建一个标签,该标签可以用来显示文本,也可以用来显示图片。在我们的项目中,我们选择使用QLabel
来显示时间。
QLabel *timeLabel = new QLabel(this);
然后,我们需要定期更新时间标签的显示内容,以实现时间的实时显示。这里我们可以使用Qt的
QTimer
类。QTimer
类是一个定时器,我们可以设定一个时间间隔,然后在这个时间间隔到达后,QTimer
会发出一个信号,我们可以连接这个信号到一个槽函数,这个槽函数就会在每次时间间隔到达时被调用。我们可以设置
QTimer
的时间间隔为1000毫秒(即1秒),然后连接QTimer
的timeout()
信号到一个槽函数,这个槽函数用于更新时间标签的显示内容。
QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateTime())); timer->start(1000);
在槽函数
updateTime()
中,我们获取当前的系统时间,然后格式化为我们想要的格式,最后设置到时间标签上。void MainWindow::updateTime() {QDateTime currentDateTime = QDateTime::currentDateTime();QString currentDateTimeString = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");timeLabel->setText(currentDateTimeString); }
在这个过程中,我们使用了Qt的信号与槽机制(Signals and Slots)。信号与槽机制是Qt的一个重要特性,它使得不同对象之间的通信变得更加简单直观。在我们的项目中,我们使用信号与槽机制来实现定时更新时间标签的功能。
以上就是实时显示当前时间的设计与实现过程。在下一小节,我们将详解设置无操作自动关机/关屏的功能。
5.4 设置不操作自动关机或关屏幕 (Setting Idle Timeout for Shutdown or Screen Off)
在某些情况下,用户可能希望在一段时间内没有任何操作时,系统能够自动进行关机或者关屏幕。这种情况下,我们需要检测用户的输入活动,如鼠标移动、键盘敲击等,以确定系统是否处于空闲状态。
在Qt中,我们可以使用QApplication::idleTime()函数来获取系统的空闲时间,这个函数返回的是自上次用户交互以来的毫秒数。然后,我们可以将这个空闲时间与用户设置的空闲超时时间进行比较,如果空闲时间超过了超时时间,那么我们就执行关机或者关屏的操作。
这里面涉及到两个关键的点,一个是如何获取系统的空闲时间,另一个是如何在空闲时间超过超时时间后执行关机或者关屏的操作。下面的示例代码展示了如何在Qt中实现这个功能:
#include <QApplication> #include <QTimer> #include <QProcess>// 用户设定的空闲超时时间,例如设定为30分钟 int idleTimeout = 30 * 60 * 1000;// 创建一个定时器 QTimer *timer = new QTimer(this);// 设定定时器每秒触发一次 timer->start(1000);// 当定时器触发时,检查系统的空闲时间 connect(timer, &QTimer::timeout, [=]() {// 获取系统的空闲时间int idleTime = QApplication::idleTime();// 如果空闲时间超过了设定的超时时间,那么执行关机或者关屏的操作if (idleTime > idleTimeout) {// 创建一个QProcess对象QProcess *process = new QProcess(this);// 执行关机或者关屏的命令 #ifdef Q_OS_WINprocess->start("shutdown -s -t 0"); #elseprocess->start("shutdown -h now"); #endif} });
这个示例展示了如何在Qt中使用QApplication::idleTime()函数和QTimer来实现在系统空闲一段时间后自动进行关机的功能。如果要实现关屏的功能,只需将关机的命令替换为关屏的命令即可。
(六) 项目实战
6.1 UML图
在这个UML图中,我们有以下几个主要的类:
Application
:这是主应用程序类,它使用UserInterface
,BusinessLogic
和OperatingSystemInterface
。UserInterface
:这是用户界面类,它提供了一系列的方法供用户进行交互,如设置关机时间、显示当前时间等。BusinessLogic
:这是业务逻辑类,它使用了所有的模块类,如TimedShutdownModule
,CountdownShutdownModule
等,用于处理用户的输入和执行相应的操作。OperatingSystemInterface
:这是操作系统接口类,它提供了发送关机命令和获取当前时间的方法。TimedShutdownModule
,CountdownShutdownModule
,TimedScreenOffModule
,CountdownScreenOffModule
,RealTimeDisplayModule
和AutoShutdownScreenOffModule
:这些是各个功能模块的类,它们实现了各自的功能。
6.2 项目结构
根据您的需求和目录结构,以下是一个可能的项目文件结构:
├── CMakeLists.txt ├── src │ ├── main.cpp │ ├── core │ │ ├── TimedShutdownModule.cpp │ │ ├── CountdownShutdownModule.cpp │ │ ├── TimedScreenOffModule.cpp │ │ ├── CountdownScreenOffModule.cpp │ │ ├── RealTimeDisplayModule.cpp │ │ └── AutoShutdownScreenOffModule.cpp │ ├── utils │ │ └── OperatingSystemInterface.cpp │ └── gui │ └── UserInterface.cpp ├── include │ ├── core │ │ ├── TimedShutdownModule.h │ │ ├── CountdownShutdownModule.h │ │ ├── TimedScreenOffModule.h │ │ ├── CountdownScreenOffModule.h │ │ ├── RealTimeDisplayModule.h │ │ └── AutoShutdownScreenOffModule.h │ ├── utils │ │ └── OperatingSystemInterface.h │ └── gui │ └── UserInterface.h ├── test │ ├── TimedShutdownModuleTest.cpp │ ├── CountdownShutdownModuleTest.cpp │ ├── TimedScreenOffModuleTest.cpp │ ├── CountdownScreenOffModuleTest.cpp │ ├── RealTimeDisplayModuleTest.cpp │ ├── AutoShutdownScreenOffModuleTest.cpp │ ├── OperatingSystemInterfaceTest.cpp │ └── UserInterfaceTest.cpp ├── doc │ ├── requirements.md │ ├── design.md │ └── user_manual.md └── resources├── icon.png└── font.ttf
在这个结构中,
src
目录下存放所有的源代码文件,include
目录下存放所有的头文件,test
目录下存放所有的测试代码,doc
目录下存放所有的文档,resources
目录下存放项目中使用的所有资源文件。
CMakeLists.txt
是项目的构建脚本,用于描述项目的构建过程。这只是一个基本的项目文件结构,您可以根据您的实际需求进行修改和扩展。
6.3 运行流程图
在这个流程图中,我们可以看到以下的执行逻辑:
- 用户通过
User Interface
设置关机时间,屏幕关闭时间,倒计时时间和空闲时间。- 这些设置会被传递到相应的模块,如
Timed Shutdown Module
,Timed Screen Off Module
,Countdown Shutdown Module
,Countdown Screen Off Module
和Auto Shutdown/Screen Off Module
。- 当到达预设的时间或者倒计时结束,这些模块会执行相应的操作,如关机或者关闭屏幕。
- 这些操作会通过
Operating System Interface
发送到操作系统。Real-time Time Display Module
会实时显示当前的时间到User Interface
。
6.4 Cmake设计
以下是一个基本的
CMakeLists.txt
文件,它配置了一个使用 Qt6 的项目:# Set the minimum required version of CMake cmake_minimum_required(VERSION 3.16)# Set your project name project(MyQtProject)# Set the C++ standard you want to use set(CMAKE_CXX_STANDARD 17)# Find the QtWidgets library find_package(Qt6 COMPONENTS Widgets REQUIRED)# Add all your .cpp source files here set(SOURCESsrc/main.cppsrc/core/TimedShutdownModule.cppsrc/core/CountdownShutdownModule.cppsrc/core/TimedScreenOffModule.cppsrc/core/CountdownScreenOffModule.cppsrc/core/RealTimeDisplayModule.cppsrc/core/AutoShutdownScreenOffModule.cppsrc/utils/OperatingSystemInterface.cppsrc/gui/UserInterface.cpp )# If you have .h files, add them here set(HEADERSinclude/core/TimedShutdownModule.hinclude/core/CountdownShutdownModule.hinclude/core/TimedScreenOffModule.hinclude/core/CountdownScreenOffModule.hinclude/core/RealTimeDisplayModule.hinclude/core/AutoShutdownScreenOffModule.hinclude/utils/OperatingSystemInterface.hinclude/gui/UserInterface.h )# Tell CMake to create an executable using the sources and headers add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})# Link the executable to the necessary libraries target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets)# Specify include directories target_include_directories(${PROJECT_NAME} PRIVATE include)
这个
CMakeLists.txt
文件首先设置了 CMake 的最小版本要求,然后设置了项目名称和要使用的 C++ 标准。接着,它使用find_package
命令找到了 Qt6 的 QtWidgets 库。然后,它定义了一个变量
SOURCES
,其中包含了所有的源代码文件,以及一个变量HEADERS
,其中包含了所有的头文件。最后,它使用
add_executable
命令创建了一个可执行文件,并使用target_link_libraries
命令将这个可执行文件链接到必要的库。同时,使用target_include_directories
指定了头文件的路径。这只是一个基本的
CMakeLists.txt
文件,您可能需要根据您的实际项目需求进行修改和扩展。
6.5 工作量评估
以下是一个预估的工作量和技术难点的表格:
功能模块 预计工作量(小时) 技术难点 定时关机模块 8 如何在不同的操作系统上实现关机 倒计时关机模块 8 如何实现倒计时功能 定时关屏模块 8 如何在不同的操作系统上实现屏幕关闭 倒计时关屏模块 8 如何实现倒计时功能 实时显示当前时间模块 4 如何实现实时更新的用户界面 无操作自动关机/关屏模块 10 如何检测用户的活动状态 用户界面设计 16 如何设计易用的用户界面 业务逻辑层设计 16 如何设计灵活的业务逻辑层 操作系统接口层设计 12 如何与操作系统交互 测试 20 如何编写有效的测试用例 文档编写 10 如何编写清晰的文档 总计 120 这个表格是基于一个中级工程师的水平进行预估的,实际的工作量可能会根据工程师的经验和技能有所不同。同时,这个预估也没有考虑到项目管理和沟通的时间,这些也是项目开发的重要部分。
请注意,这只是一个粗略的预估,实际的工作量可能会有所不同。在实际的项目开发中,通常需要根据项目的进展和遇到的问题进行调整。
(七) 项目执行流程与耗时 (Project Execution Process and Time Consumption)
7.1 开发流程 (Development Process)
随着项目需求的确立,我们首先进行的是项目架构的设计,以保证我们的开发流程有一个稳固的基础。我们将项目的需求分解,对每个模块定义清晰的输入输出,从而形成一份详细的功能规格书。
在此基础上,我们利用UML(Unified Modeling Language,统一建模语言)进行系统设计。包括用例图(Use Case Diagram)的编制、类图(Class Diagram)的设计以及序列图(Sequence Diagram)的制作。这不仅能帮助我们理清项目的结构,也能对开发过程中可能出现的问题有所预见。
完成设计阶段后,进入到编码阶段。我们遵循C++的编码规范和风格,尽量使代码保持简洁和清晰,同时也保证代码的复用性和模块化。我们遵循DRY(Don’t Repeat Yourself)原则,对重复的代码进行抽象和封装,同时运用设计模式,例如观察者模式(Observer Pattern),提高代码的可扩展性和可维护性。
在开发过程中,我们采用敏捷开发模式,每完成一部分功能就进行测试,从而及时发现并解决问题。同时,我们也采用版本控制工具,如Git,来管理代码,以便在出现问题时能迅速回溯。
为了确保代码质量,我们在开发过程中使用了单元测试(Unit Testing),以检查每个函数和模块的功能是否正确。同时,我们也使用集成测试(Integration Testing)来确认各模块间的接口是否正确。
最后,我们进行了系统测试,验证系统的各项功能是否都能正常运行。在测试过程中发现的问题,我们立即进行修复,保证了软件的质量。
总的来说,我们的开发流程分为需求分析、设计、编码、测试和维护等几个步骤,每个步骤都严格执行,以保证软件的质量和稳定性。
7.2 测试流程 (Testing Process)
在我们的开发流程中,测试是一个至关重要的部分。我们采用的是一种名为持续集成(Continuous Integration,CI)的做法,它是敏捷开发的一个重要组成部分。持续集成要求开发人员频繁地提交代码到代码库,每次提交后,系统都会自动进行构建和测试,以发现并解决问题。
我们的测试流程分为三个主要的部分:单元测试、集成测试和系统测试。让我们深入探讨每个部分。
首先,我们进行单元测试(Unit Testing)。我们对每个函数和类进行单独测试,以验证它们是否能正常工作。这是最基础的测试,也是最重要的测试,因为它能在早期就发现问题。我们利用C++单元测试框架,如Google Test,编写测试用例,确保每个功能模块都被全面测试。
其次,我们进行集成测试(Integration Testing)。我们将几个相关的模块组合在一起,测试它们是否能协同工作。集成测试是为了检查不同模块间的接口是否正确,能否正常协同工作。我们在Qt框架中集成了相关测试工具,进行集成测试。
最后,我们进行系统测试。我们测试整个系统,看看它是否能满足所有的需求。系统测试是为了确认系统的整体功能和性能。我们利用Qt自带的测试工具,进行全面的系统测试,以确保我们的定时关机器能在各种条件下稳定运行。
我们采用自动化测试工具来提高测试的效率和准确性。所有的测试用例都会在持续集成环境中自动执行,从而确保每次代码提交都能通过所有的测试。
通过这样的测试流程,我们能确保我们的软件质量达到预期,同时也能及时发现和修复问题。这是我们的核心竞争力,也是我们能为用户提供优质软件的保障。
7.3 项目耗时分析 (Project Time Consumption Analysis)
项目的耗时是评估一个项目成本和效率的重要指标,这里我们将对项目的耗时进行详细的分析。
首先,需求分析和设计阶段。这是项目的初期阶段,我们需要深入理解需求,并设计出合理的架构和流程。这个阶段的耗时主要取决于项目的复杂度和团队的经验。在我们的项目中,由于我们对C++和Qt有深入的理解,因此我们在这个阶段上花费的时间较短,大约占总项目时间的15%。
其次,编码阶段。这是项目的核心阶段,我们需要将设计转化为实际的代码。由于我们采用了敏捷开发和持续集成的方法,我们可以在较短的时间内得到可运行的产品。同时,由于我们的代码是模块化的,因此每个模块可以独立开发和测试,从而大大提高了开发效率。编码阶段大约占总项目时间的50%。
接下来,测试阶段。我们需要对我们的代码进行详尽的测试,以确保其质量。由于我们采用了自动化测试,因此我们可以在较短的时间内完成大量的测试。我们在测试阶段花费的时间约占总项目时间的25%。
最后,维护阶段。在项目上线后,我们需要对项目进行持续的维护和优化。由于我们的代码是模块化的,因此我们可以快速定位到问题,并进行修复。维护阶段的耗时是持续的,目前为止约占总项目时间的10%。
通过以上分析,我们可以看出,尽管项目的耗时受到许多因素的影响,但通过合理的设计和开发方法,我们可以有效地控制项目的耗时,并确保项目的质量。这也是我们项目成功的关键因素之一。
(八) 结语
在这篇文章中,我们深入探讨了基于C++与Qt框架的定时关机与关屏应用的开发过程。通过详细分析需求,选择合适的技术栈和设计模式,我们实现了一个功能完善且用户友好的应用。
从心理学的角度来看,学习这篇文章可以帮助读者激发内在动力,提高编程技能以应对现实生活中的挑战。同时,我们希望您能从中找到解决问题和创新的方法,从而在编程和工程设计领域取得更好的成果。
此外,掌握这些技能将有助于提高自信心,并对自己的未来走向产生积极影响。如果您觉得这篇文章对您有所帮助,请不要忘记收藏、点赞和评论,与更多人分享您的学习经验。这将激励我们继续创作更多有价值的内容,为您的学习和成长提供更多支持。同时,鼓励他人进行学习,也是一种积极的行为,有助于形成一个良好的心理氛围。
在未来的学习过程中,如果遇到任何问题,请随时在评论区提问。我们期待与您互动,一起成长。祝您学习愉快,不断提升自己,不断走向成功!
相关文章:

C++ Qt 项目设计:基于C++与Qt的跨平台定时关机/关屏应用开发
基于C与Qt框架的定时关机与关屏应用开发全攻略 (一) 项目概述 (Project Overview)1.1 项目需求解析 (Analyzing the Project Requirements)1.2 选择技术栈 (Choosing the Tech Stack)1.3 功能概览 (Function Overview) (二) 设计思路 (Design Thinking)2.1 系统架构设计 (Syste…...

Python新技术和趋势:如何应对Python生态的变化和发展趋势
第一章:引言 Python作为一门简洁、优雅且易于学习的编程语言,一直以来都备受开发者的喜爱。它拥有强大的生态系统和活跃的社区,使得Python在各个领域都有广泛的应用。然而,随着时间的推移,Python生态系统也在不断演变…...

Flutter 又一元老离职,感谢 Tim 这些年的付出
前天在 insiders 收到 Tim Sneath 的离职邮件时感觉很震惊,因为他绝对是 Flutter 团队的元老级人物,几乎每次一次 Flutter 版本发布和社区活动都有他的身影,可以说他是我的 Flutter 领路人之一。 Tim 是在 2017 加入 Flutter 团队࿰…...

C++学习笔记3:sort和priority_queue的比较器重载
1 sort 三种方法 1. 直接重载函数 #include <vector> #include <memory> #include <vector> #include <queue> #include <iostream> #include <algorithm>using namespace std;class Node{ public:int value;Node(){value 0;};explici…...

Java之旅——Mybatis
Mybatis 是一个基于 Java 的 ORM(Object-Relational Mapping),用于 Java 应用程序的持久层框架,它将在 Java 对象和数据库关系之间建立一个映射。Mybatis 的作用主要是简化 SQL 语句的编写和维护,以及减少代码中的冗余…...

抽奖中的分布式锁应用
开发抽奖时遇到的分布式锁问题,特此记录一下几种实现方案 背景 开发中遇到个抽奖需求,会根据当前奖池内道具数量随机道具并发送给用户。这里面涉及到超发的问题,需要使用到分布式锁,特此记录一下常用的几种方案。 “超发”&#…...

项目总结 车牌识别
代码贴:OpenCV实战5 车牌号识别_opencv车牌字符识别_爱钓鱼的歪猴的博客-CSDN博客 目录 1、效果 2、代码思路 0、准备车配字符模板图片以及字符文件 1、对整图进行预处理 得到突出车牌的cany边缘图 2、车牌字体联通在一起,形成一个区域 3、筛选出车…...

一台服务器通过apache安装多个web应用
当我们只有一台linux服务器资源但有创建多个网站的需求时,我们可以通过安装一个网站服务器Apache进行搭建,此次服务器使用Centos 7 下面分别介绍一个域名多个端口和多个域名用Apache来搭建多个网站的操作过程。 一、使用apache 服务器 (一…...

网络连通性测试
ping 在Linux上,你可以使用Shell脚本编写一个for循环来ping一个网段的地址。下面是一个简单的示例: #!/bin/bashsubnet"192.168.0"for ((i1; i<255; i)); doip"$subnet.$i"ping -c 1 -W 1 $ip >/dev/null 2>&1if [ $…...

AntDB-S流式数据库体验
本文作者:彭冲老师,上一篇彭老师体验了亚信刚发布的社区版AntDB-T数据库,文章如下: AntDB-T交易型数据库体验 本文继续体验AntDB-S流式数据库的,AntDB-S目前还未开放社区版,可以联系AntDB小助手进行体验。…...

CentOS 和 Windows 上添加和删除路由
在 CentOS 上添加和删除路由 要在 CentOS 上添加和删除路由,你可以使用 ip 命令或修改网络配置文件。以下是使用 ip 命令的方法: 添加路由: ip route add <目标网络> via <网关> dev <接口>例如: ip route add 192.168.10.0/24 via 192.168.1.1 dev eth…...

2023年电大秋季招生截止日期 什么时候开始报名
2023年电大网上报名时间为3月份和9月份截止报考,电大每年可以报考两次,春季开始报名时间为12月份左右开始,秋季报名时间预计在6月份左右开始。 2023电大网上报名时间是什么时候 电大报名分为春季和秋季两个季节,一般春季招生时间为…...

滑动窗口问题
给定一个大小为 n≤106 的数组。 有一个大小为 k的滑动窗口,它从数组的最左边移动到最右边。 你只能在窗口中看到 k 个数字。 每次滑动窗口向右移动一个位置。 以下是一个例子: 该数组为 [1 3 -1 -3 5 3 6 7],k为 3。 窗口位置最小值最…...

电子合同网页预览盖章效果实现
电子合同在现在应用越来越广,需求也就随之产生。 本篇文章主要记录两种网页盖章效果实现方式,自己记录一下, 也给需要的人提供一点思路和帮助。 效果 目录 JqueryCSS实现 原理 1.设置印章图片并隐藏 2.标记盖章位置元素 3.获取目标元素位…...

棋盘覆盖问题
文章目录 棋盘覆盖程序设计程序分析棋盘覆盖 【问题描述】 在一个2k x 2k ( 即:2^k x 2^k )个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方…...

[CISCN2023]unzip
[CISCN2023]unzip 环境搭建 1.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><form method"post" action"1.php" en…...

基于Html5的在线资料库的设计与实现(asp.NET,SQLServer)
在线资料库系统采用.NET开发平台进行开发,开发工具采用Microsoft Visual Studio 2010集成开发环境,后台编程语言采用C#编程语言来进行编程开发,数据库我们采用当下流行的SQL Server 2008数据库管理系统来存放平台中的数据信息,整个…...

【Vue】二:Vue核心处理---计算属性 监视属性
文章目录 1.计算属性示例2. 监听属性3.补充 1.计算属性示例 实际上计算属性与methods中定义方法基本上没有什么区别,只是计算属性基于响应式依赖缓存,只要数据没有发生改变,计算属性从缓存中取值,只有当数据发送改变,才…...

【Web服务器集群】Nginx网站服务
文章目录 一、Nginx 概述1.什么是 Nginx2.Nginx 的特点3.Nginx 应用场景 二、Nginx 服务基础1.编译安装 Nginx 服务1.1 布置环境1.2 安装依赖包1.3 创建运行用户、组1.4 编译安装 2.Nginx 的运行控制2.1 检查配置文件2.2 启动、停止 Nginx2.3 日志分割以及升级 Nginx 服务2.4 添…...

开始第一个vue项目,环境搭建+html项目运行
【用vue.js,通过script标签导入】 1. 搭建vue脚手架 安装node js安装cnpm(淘宝源) 【vue】在windows中搭建vue开发环境(全网最详细)_vue环境搭建_一起来学吧的博客-CSDN博客2a 2. 官网下载地址: 安装 …...

Redis 的数据类型和命令帮助
文章结构 Redis 数据类型1. Redis全局命令(跟key有关系,而跟value无关)2. StringsGetting and setting StringsManaging counters 3. Lists(L)Basic commandsBlocking commands 4. Sets(S)Basic commands 5. Hashes(H)Basic commands 6. Sort…...

【C++11】智能指针
什么是智能指针: 智能指针是一个类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函…...

三、Go的常用命令以及Go的执行原理
Go的执行原理以及Go的命令 一、Go的源码文件 Go 的源码文件分类: 如上图,分为三类: 1、命令源码文件: 声明自己属于 main 代码包、包含无参数声明和结果声明的 main 函数。 命令源码文件被安装以后,GOPATH 如果…...

ESP32 CAM 模块和 OpenCV 的二维码扫描器
概述 该项目是关于使用 ESP32 CAM 模块和 OpenCV 设计的二维码扫描仪或阅读器。我们将使用 ESP32 摄像头模块和 python 库开发一个程序和设备,我们可以用它来扫描二维码。使用 ESP32 CAM,项目变得更便宜。 QR 码现在已经成为我们日常生活的一部分,因为我们几乎在任何地方都…...

多链路传输技术在火山引擎 RTC 的探索和实践
动手点关注 干货不迷路 传统的数据传输方式大多是利用一个链路、选择设备的默认网卡进行传输,使用这种方式实现实时音视频通话时,如果默认网络出现问题(如断网、弱网等),用户的通信就会发生中断或者卡顿,影…...

在Flask中构建API接口
重定向行为 斜杠 以下两个路由的不同之处在于是否使用尾部的斜杠。 第一个路由的URL尾部有一个斜杠,看起来就像一个文件夹,访问一个没有斜杠结尾的URL时,Flask会自动进行重定向,在结尾加上一个斜杠。 第二个路由的URL没有尾部…...

Postgres vs MySQL
主要区别及示例 简而言之,Postgres 和 MySQL 之间的主要区别实际上归结为主索引和辅助索引的实现方式以及数据的存储和更新方式。 让我们进一步探讨这个问题。 但首先... 基础知识 索引是一种数据结构(主要是 B 树),允许通过…...

02.IP地址以及静态路由配置
文章目录 IP地址IP地址分类IPV4地址(32位)IPV4地址的分类特殊IP地址 VLSM --- 可变长子网掩码(子网划分)CLDR --- 无类域间路由(汇总)配置静态路由的基础配置静态路由的拓展配置 IP地址 IP地址分类 IPV4(32位二进制构成) — 点分十进制IPV6(128位二进制构成) — 冒分十六进制…...

GD32(STM32)因为中断问题,导致不能进行程序 正常运行
项目中,之前定时器中断就用了个TIM2,但后来程序优化需要再加一个计数定时器TIM6, TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // 开启定时器时钟,即内部时钟CK_INT72M RCC_APB1PeriphClockCmd(RCC_APB1Perip…...

华为OD机试真题B卷 Java 实现【统计字符】,附详细解题思路
一、题目描述 输入一行字符,分别统计出包含英文字母、空格、数字和其它字符的个数。 数据范围:输入的字符串长度满足 1 \le n \le 1000 \1≤n≤1000 。 二、输入描述 输入一行字符串,可以有空格。 三、输出描述 统计其中英文字符&#…...