GUI07-学工具栏,懂MVC

MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。这节将安排您学习:

  1. Model-View-Controller 模式
  2. 如何创建工具栏以及如何于其上创建普通、多选、单选工具按钮
  3. 控件之间如何通过“空闲”事件实现状态统一

wxToolBar & MVC

0. 课堂视频

建议先看视频,再看文本教程。最后到 d2school 课堂做本课的学习强化练习。

GUI07-学工具栏,懂 MVC

1. 才不是题外话:MVC

MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。

MVC 是 “Model-View-Controller” 的简写:

  • Model / 模型:可认为就是我们在代码中定义的各种业务数据;
  • View / 视图:业务数据的展现形式,一种模型(数据)往往有多种展现形式;
  • Controller / 控制器: 用户通过控制器,以可定制的方式,获取数据模式,及指定形式展现(视图)。

程序员开发软件时,将代码按照 Model-View-Controller 加以分离,能让软件代码:

  1. 逻辑,意图更清晰
  2. 耦合更低
  3. 更可维护

MVC 比较适用于中大型软件代码的组织,我们前几节课所写的程序,看似简单,但其实, GUI软件没有小项目,是底层的库(比如 wxWidgets)默默地做出大量支持,包括 MVC 架构。

以前面课堂写的小例程为例:我们在窗体上鼠标位置下显示鼠标所在的坐标值,并且允许用户做如下控制:

  1. 是否显示坐标值,或仅显示一行提示文字;
  2. 文字以蓝或红哪种颜色显示。

则,至少有两个数据模型:

编号Model
M1表达坐标的两个整数:x, y
M2表达用户选中颜色的菜单项ID

以及,这两个数据,至少四种组合态的展现形式:

编号View (数据视图)
V1蓝色 + 显示坐标
V2红色 + 显示坐标
V3蓝色 + 不显示坐标(仅显示提示)
V4红色 + 不显示坐标(仅显示提示)

以下是实际运行时,显示的 V2 状态界面截图:
工具栏框架窗口运行效果
正如本课视频所讲到,View 并不仅仅包含业务数据的展现,用于实现和用户交互的 GUI 界面控制,比如我们已学的菜单、工具栏、状态栏等界面控件,也是 View 的组成。它们也会有和业务数据紧密关联的状态,比如菜单或工具图标的多选或单选状态。

以上归纳了 Model 和 View,那 Controller是什么呢?是控制流程。在我们所写的程序中,程序接收用户的输入(鼠标点击等),然后调用相应的事件函数,在事件函数中修改 Model 数据,最后引发视图刷新,包括业务视图刷新和人机交互界面中控件状态的改变,这整个过程即为 Controller。

初接触时,对 MVC 的三个最常见的误解为:

  • 误解一:以为 View的展现内容只能给看。正解:一个程序的输出可以是另一个程序的输入,此时可视为后者是前者的“用户”,同理,同一个程序的控制,也可能是来自另一个程序的输入。正因为 Views 不一定真实的人,所以在服务端程序中,特别是多层网络架构的软件系统中,MVC 的应用也广泛可见;

  • 误解二:以为人机交互过程中界面控件,就是 Controller 。正解:Controller 是接受用户(不一定是人,见上)的输入,然后引发(即动作的发起者)Model 被修改,并最终体现到 View 变化的每一个完整过程。

  • 误解三:以为只有业务数据的展现是 Views。正解:凡是需要展现给用户看的内容,基本都是 View,包括控件的状态。

2. 创建图标

在 Windows 系统下,应用程序工具栏按钮所需要的图标,需要使用 ICON 类型的图标,在 wxWidgets中,对应到 wxIcon 类。

2.1 从文件直接创建

可在程序运行时,通过读取指定路径(相对或绝对)读取指定的图标文件,以构造出一个wxIcon对象,示例代码:

wxIcon myIcon = wxIcon(wxT("路径/图标文件.ico"), wxBITMAP_TYPE_ICO, 16, 16);

注意,创建所得是普通的栈对象,非堆对象。

  • 入参1:图标的磁盘位置(包括路径和文件名,可使用绝对或相对路径);
  • 入参2:图标文件的类型(注意是 wxBITMAP_TYPE_ICO,而非 wxBITMAP_TYPE_ICON);
  • 入参3,4:两个整数,图标的长、宽(像素)。

在程序运行时读取外部文件以创建图标(或其它资源)——

  • 好处:可随时更换图标——不少应用程序支持 “换肤”,对于工具栏按钮来说,这是一种简便可行的方法;
  • 坏处:程序无法单独运行。比如你想把程序发给你的朋友,就得同时附上这些图标文件,并需确保路径正确。

2.2 从程序嵌入资源中创建

Windows 支持将一些资源,嵌入到可执行文件(.exe)“体内”,从而实现可执行文件可独立运行。

Code::Blocks 向导生成的 wxWidgets 项目中,已经自带 resource.rc 的文件,打开它,默认内容为:

aaaa ICON "wx/msw/std.ico"
#include "wx/msw/wx.rc"

默认包含的 wxWidgets 程序图标。其中,aaaa 为资源的名字,ICON 为资源类型,此处为图标,最后一列 “wx/msw/std.ico” 为图标在磁盘上的路径和名字(仅编译时需用到,运行时不再需要此路径)。

假设我们已经在当前项目下创建名为 icons 的子目录,并于其下准备好 about.ico、show_info.ico、blue_txt.ico、red_txt.ico、quit.ico 等图标,则可将 resouce.rc 内容修改成:

aaaa ICON "wx/msw/std.ico"

about ICON  "icons/about.ico"
blue_txt ICON "icons/blue_txt.ico"
red_txt ICON "icons/red_txt.ico"
quit ICON "icons/quit.ico"
show_info ICON "icons/show_info.ico"

#include "wx/msw/wx.rc"

这样,在编译后,相关图标资源就会内嵌在编译生成的可执行文件中,并可通过 wxIcon 的另一个构造函数读出并且成图标对象:

wxIcon icon = wxIcon(wxT("资源名"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);

比如,创建 quit 图标:

wxIcon iconQuit = wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);

本文后续代码均从内嵌资源创建图标。

3. 工具栏与工具栏按钮

3.1 创建工具栏

wxFrame::CreateToolBar() 用于创建一个空白的工具栏,该方法返回一个 wxToolBar * (指针)。

示例代码:

wxToolBar* tb = this->CreateToolBar(); // 创建工具栏

以上代码中的 this 工具栏所属的框架窗口,它也将负责该工具栏的生命周期(在框架窗口关闭前,将自释放上面创建工具栏堆对象)。

以下各种工具栏按钮,都需要由工具栏(wxToolBar)对象来创建。

3.2 普通工具按钮

使用工具栏对象,创建一个普通工具栏按钮,方法名为 “AddTool()”示例代码:

// 准备图标 (从内嵌资源中读取)
wxIcon iconQuit = wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);

// 创建带图标的普通工具按钮
tb->AddTool(idMenuQuit, _("Quit"), iconQuit, _("Quit the Application"));
  • 入参1:工具按钮要执行的命令对应的ID,通常来自已经创建的菜单项所绑定的事件ID。比如本例的 idMenuQuit 为 “Quit” 菜单项的ID,该命令用于退出整个应用程序;
  • 入参2:工具按钮的标签,默认状态下并不显示,复杂情况下,可设置为在图标底部或右侧显示按钮的名字;
  • 入参3:前面创建的图标对象(并非指针);
  • 入参4:鼠标在该工具按钮上浮动时出现的提示。

也可将构造图标对象和创建工具按钮合成一步:

tb->AddTool(idMenuQuit, _("Quit"), 
		wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16)_("Quit the Application"));

实际还需要第三步,但当连续为同一个工具栏创建多个工具按钮时,仅需在最后调用一次:

tb->Realize(); // 真实展现,最后调用,只需一次

仅在调用该方法后,工具栏才真正地将新创建的各工具按钮展现出来。

3.3 复选工具按钮

使用方法为:AddCheckTool(),示例代码:

//复选工具按钮(是否显示鼠标坐标)
tb->AddCheckTool(idMenuShowMotionInfo, _("Show Info"),
           wxIcon(wxT("show_info"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),
           wxNullBitmap, // 按钮变灰时显示的图标,由程序自动生成
           _("Show motion info or no")); // 提示

第四个入参用于指定,该复选按钮在不可用(disabled)状态下如何展现,除非你确实想为之提供一种特别的样子,否则,可如代码所示,指定使用代表空图片的对象 wxNullBitmap,系统将自动以 “灰度” 方式生成该状态的展现样式。

因为方法名已经是 “AddCheckTool ()”,故无需像普通的 “AddTool ()” 那样,再由入参指定按钮的类型,下面用于创建单选工具按钮的方法,也是如此。

3.4 单选工具按钮

使用方法为:AddRadioTool(),示例代码:

//单选工具按钮(两个:选择使用蓝色文本或使用红色文本)
tb->AddRadioTool(idMenuBlueText, _("Blue Text"),
           wxIcon(wxT("blue_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),
           wxNullBitmap, // 按钮变灰时显示的图标,由程序自动生成
           _("Set text blue")); // 提示

tb->AddRadioTool(idMenuRedText, _("Red Text"),
           wxIcon(wxT("red_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),
           wxNullBitmap,
           _("Set text red"));

和复选按钮不同,单独一个单选按钮没有意义,通常需要接连创建一组,让用户从多个中选择一个(即为单选之意)。

同一工具栏上如有多组单选按钮,除了可考虑使用分隔(见下面小节)在视觉上加以分组之外,并不需要再额外在逻辑上分组,因为工具按钮通常对应到菜单项,而对菜单项,我们已经作了逻辑分组,详见 《第5节 玩转主菜单》。

3.5 分隔线

tb->AddSeparator(); // 分隔线

3.6 连续代码

以下是在示例项目中, wxToolBarFrame 构造函数尾部,创建工具栏及相应按钮、分隔线的代码片段:

    // 工具栏
    wxToolBar* tb = this->CreateToolBar(); // 创建工具栏
    wxIcon iconQuit = wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);
    tb->AddTool(idMenuQuit, _("Quit"), iconQuit, _("Quit the Application"));

    tb->AddSeparator(); // 分隔线

    //复选工具按钮(是否显示鼠标坐标)
    tb->AddCheckTool(idMenuShowMotionInfo, _("Show Info"),
                    wxIcon(wxT("show_info"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),
                    wxNullBitmap, // 按钮变灰时显示的图标,由程序自动生成
                    _("Show motion info or no")); // 提示

    tb->AddSeparator(); // 分隔线

    // 单选工具按钮(两个)
    tb->AddRadioTool(idMenuBlueText, _("Blue Text"),
                    wxIcon(wxT("blue_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),
                    wxNullBitmap,
                    _("Set text blue"));

    tb->AddRadioTool(idMenuRedText, _("Red Text"),
                    wxIcon(wxT("red_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),
                    wxNullBitmap,
                    _("Set text red"));

    tb->Realize(); // 真实展现,最后调用,只需一次

4. 控件状态同步

为了使用方便,GUI 程序往往允许用户从不同控件入口发起操作,在本例,用户通过菜单栏或工具栏,都可以修改文字的颜色。窗体上输出的文字归属 View,但是菜单项或工具按钮的显示状态,也归于 View 范畴,它们的选中状态,必须保持同步。

举例:用户选中 “变帅” 菜单项,则 工具栏上 “变帅” 按钮也需要在操作后,变成“被按下”的状态;反过来也一样:用户按下 “变帅” 按钮,则同名的菜单项之前,必须打上勾。这还是复选控件,如果是单选控件,则需要的维护一组控件的状态,会更加啰嗦,容易出错。

因此,无论是大家比较熟悉的 Windows 或 苹果的 GUI 系统,还是 Linux 下的各种 GUI 桌面系统,或者是新兴的智能手机 Android 系统,或者是为浏览器前端开发提供支持各种前端库,基本都会提供一套机制,来辅助程序员实现界面组件的状态同步。

GUI 程序有一个共同点:它不可能很忙。有人说,我打开 Word,然后以平均每分钟 120 个汉字,接近 500 次按键的速度打字,这 Word 肯定忙坏了呀? 不是的,这点输入对现在的计算机和程序来说真是一点压力没有,程序仍然能在你的指法间隙间,“挤出”一大把无所事事的时间(不信你可以打开 Windows 任务管理器,看看你要能以怎样的打字速度,让 CPU 占用率提高 0.1%?)。

程序这么闲,自然就可以利用起来,闲着也是闲着,不如打打孩子——不是,不如去检查一下,有哪个控件状态不对,我们好把它纠正过来。

这种空闲事件,在很多 GUI 系统(比如 Windows 或 Android)中称为 “Idle-Event” (对应的事件处理器称为 “Idle-Handler”)。我们正在学习的 wxWidgets 又将它细分出一个 “wxUpdateUIEvent”,即专门用来处理用户界面(UI)的控件状态更新(Update)的事件。对应的,绑定事件函数的宏为:“EVT_UPDATE_UI”。

以用户可以切换坐标是否显示这一功能为例,按照 MVC 的划分原则,我们首先需要有的 Model 数据是:

  • a) 坐标数据 x,y (之前课堂已经添加了);
  • b) 是否显示,之前课堂没有添加,因此本课需为框架窗口类加上该成员数据,取名 showMotionInfo,一个 bool 值。

接着,当用户依赖某个操作路径(菜单或工具按钮),发起切换操作时,作为一个GUI开发框架,wxWidget将配合作为一个 GUI 操作系统的 Windows,共同帮我们完成复杂的 Controller 过程(视频里说的那些“线”),最终调用到我们写的事件响应函数,该函数修改作为 Model 数据之一的 showMotionInfo。如何知道将它修改成 true 或 false 呢?也就是说,如何知道用户当前操作是选中或是取消选中呢?仍然得感谢 wxWidgets 和其下的操作系统,它已经将该信息,放在事件数据中的 “IsCheck()” 方法里了。

接受用户输入,修改 Model 数据(showMotionInfo)的示例代码:

// 1 绑定到菜单上:
EVT_MENU(idMenuShowMotionInfo, HelloToolBarFrame::OnShowMotionInfo)

...

// 2 在事件响应函数中,修改 Model,状态信息在事件中:
void HelloToolBarFrame::OnShowMotionInfo(wxCommandEvent& event)
{
    this->showMotionInfo = event.IsChecked(); // 修改 model
}

接下来,程序在某个时刻发现自己很闲,于是它去开始检查并纠正哪个“孩子”(控件)状态不对——但是,它自己并不知道,也不记录具体哪个控件所应该处于正确状态是什么——谁知道,当然只有作为程序员的我们知道,所以程序会自动触发 UpdateUIEvent 事件,让我们在这个事件里去告诉它,某个“孩子”现在的正确状态应该是:在睡觉……如果有十个不同ID的控件需要更新状态,程序会触发十次这样的事件。

以 “idMenuShowMotionInfo” 为例,空闲的程序想知道绑定该ID的菜单项和工具图标当前应该处于什么状态时,它会触发以下的事件函数被调用:

// 3 绑定控件ID
EVT_UPDATE_UI(idMenuShowMotionInfo, HelloToolBarFrame::OnUpdateShowMotionInfo)

...

// 4 在事件中,由程序员告诉程序,当前控件的正确状态(是否选中)
void HelloToolBarFrame::OnUpdateShowMotionInfo(wxUpdateUIEvent& event)
{
    event.Check(this->showMotionInfo); // 有没有选中
}

请对比代码中的 3 和 4,从 “SET/写” 和 “GET/读” 的角度,加以理解。

以上讲的是控件的复选状态,它的状态就是 “选中” 或 “没选中”;对比之下,单选状态稍显复杂。因为单选状态的控件通常成组出现(至少两个),对应的详细状态应该是:“选中哪一个了?”。再次感谢所有 GUI 库,当它们在触发控件的 “UpdateEvent” 时,会带上这个控件的 ID,因此,我们只需检查它是不是我们记录的,用户选中的那个控件ID即可。

比如颜色选择有两项:蓝或红,当用户做出选择,我们就用 Model 数据(selectedColorId) 记录下来:

// 5 绑定控件ID,同一组单选控件需要全部绑定到同一个事件函数:
EVT_UPDATE_UI(idMenuBlueText, HelloToolBarFrame::OnUpdateTextColor)
EVT_UPDATE_UI(idMenuRedText, HelloToolBarFrame::OnUpdateTextColor)

...

// 6 记录用户选的是哪个ID
void HelloToolBarFrame::OnTextColorSelected(wxCommandEvent& event)
{
    selectedColorId = event.GetId();
}

对应的,当程序因为闲着也是闲着,又要 “打孩子” 时,我们是这样告诉它哪个 “孩子” 需要被选中,哪个 “孩子” 不需要:

// 7 同样需要绑定一组单选控件(的ID)
EVT_UPDATE_UI(idMenuBlueText, HelloToolBarFrame::OnUpdateTextColor)
EVT_UPDATE_UI(idMenuRedText, HelloToolBarFrame::OnUpdateTextColor)

...

// 8 在事件中,由程序员告诉程序,它来“问”的控件,是不是被选中的那个
void HelloToolBarFrame::OnUpdateTextColor(wxUpdateUIEvent& event)
{
    event.Check(event.GetId() == this->selectedColorId);
}

5 Model 数据

最后,汇总一下本例程用到的 Model 数据:


    int xPos, yPos;
    int selectedColorId = idMenuBlueText;

    bool showMotionInfo = false; 

其中,前两项是在之前的课堂定义的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++----类与对象(中篇)

引言 以C语言栈的实现为例,在实际开发中,我们可能会遇到以下两个问题: 1.初始化和销毁管理不当:C语言中的栈实现通常需要手动管理内存(如使用malloc和free),这导致初始化和销毁栈时容易出错或…

linux打包qt程序

Linux下Qt程序打包_linuxdeployqt下载-CSDN博客 Linux/Ubuntu arm64下使用linuxdeployqt打包Qt程序_linuxdeployqt arm-CSDN博客 本篇文章的系统环境是 : 虚拟机ubuntu18.04 用下面这个qmake路径 进行编译 在 ~/.bashrc 文件末尾,qmake目录配置到文件末尾 将上图中…

气象与旅游之间的关系,如果借助高精度预测提高旅游的质量

气象与旅游之间存在密切的关系,天气条件直接影响旅游者的出行决策、旅游体验和安全保障。通过高精度气象预测技术,可以有效提升旅游质量,为游客和旅游行业带来显著的优势。 1. 提高游客出行决策效率 个性化天气服务:基于高精度气象预测,旅游平台可以提供个性化的天气预报服…

华为OD --- 靠谱的车

华为OD --- 靠谱的车 题目OJ用例独立实现思路源码 参考实现思路源码实现 题目 OJ用例 测试用例case 独立实现 思路 独立实现的思路比较简单,直接建一个长度为N的数组,然后找出index中不包含4的项数即可 源码 const rl require("readline").createInterface({ …

可视化平台FineReport的安装及简单使用

1. FineReport产品 FineReport介绍 FineReport报表软件是一款纯Java编写的、集数据展示(报表)和数据录入(表单)功能于一身的企业级web报表工具,它专业、简捷、灵活的特点和无码理念,仅需简单的拖拽操作便可以设计复杂的中国式报表,搭建数据决…

OkHttp源码分析:分发器任务调配,拦截器责任链设计,连接池socket复用

目录 一,分发器和拦截器 二,分发器处理异步请求 1.分发器处理入口 2.分发器工作流程 3.分发器中的线程池设计 三,分发器处理同步请求 四,拦截器处理请求 1.责任链设计模式 2.拦截器工作原理 3.OkHttp五大拦截器 一&#…

Nginx主要知识点总结

1下载nginx 到nginx官网nginx: download下载nginx,然后解压压缩包 然后双击nginx.exe就可以启动nginx 2启动nginx 然后在浏览器的网址处输入localhost,进入如下页面说明nginx启动成功 3了解nginx的配置文件 4熟悉nginx的基本配置和常用操作 Nginx 常…

概率论得学习和整理27:关于离散的数组 随机变量数组的均值,方差的求法3种公式,思考和细节。

目录 1 例子1:最典型的,最简单的数组的均值,方差的求法 2 例子1的问题:例子1只是1个特例,而不是普遍情况。 2.1 例子1各种默认假设,导致了求均值和方差的特殊性,特别简单。 2.2 我觉得 加权…

初学stm32 --- 时钟配置

目录 stm32时钟系统 时钟源 (1) 2 个外部时钟源: (2)2 个内部时钟源: 锁相环 PLL PLLXTPRE: HSE 分频器作为 PLL 输入 (HSE divider for PLL entry) PLLSRC: PLL 输入时钟源 (PL…

Latex+VsCode+Win10搭建

最近在写论文,overleaf的免费使用次数受限,因此需要使用本地的形式进行编译。 安装TEXLive 下载地址:https://mirror-hk.koddos.net/CTAN/systems/texlive/Images/ 下载完成直接点击iso进行安装操作。 安装LATEX Workshop插件 设置VsCode文…

深度学习之目标检测篇——残差网络与FPN结合

特征金字塔多尺度融合特征金字塔的网络原理 这里是基于resnet网络与Fpn做的结合,主要把resnet中的特征层利用FPN的思想一起结合,实现resnet_fpn。增强目标检测backone的有效性。代码实现如下: import torch from torch import Tensor from c…

Leetcode 面试150题 399.除法求值

系列博客目录 文章目录 系列博客目录题目思路代码 题目 链接 思路 广度优先搜索 我们可以将整个问题建模成一张图:给定图中的一些点(点即变量),以及某些边的权值(权值即两个变量的比值),试…

python实现Excel转图片

目录 使用spire.xls库 使用excel2img库 使用spire.xls库 安装:pip install spire.xls -i https://pypi.tuna.tsinghua.edu.cn/simple 支持选择行和列截图,不好的一点就是商业库,转出来的图片有水印。 from spire.xls import Workbookdef …

hpe服务器更新阵列卡firmware

背景 操作系统:RHEL7.8 hpe服务器经常出现硬盘断开,阵列卡重启问题,导致系统hang住。只能手动硬重启。 I/O error,dev sda smartpqi 0000:5c:00:0: resettiong scsi 1:1:0:1 smartpqi 0000:5c:00:0: reset of scsi 1:1:0:1:…

excel 使用vlook up找出两列中不同的内容

当使用 VLOOKUP 函数时,您可以将其用于比较两列的内容。假设您要比较 A 列和 B 列的内容,并将结果显示在 C 列,您可以在 C1 单元格中输入以下公式: 这个公式将在 B 列中的每个单元格中查找是否存在于 A 列中。如果在 A 列中找不到…

北邮,成电计算机考研怎么选?

#总结结论: 基于当前提供的24考研复录数据,从报考性价比角度,建议25考研的同学优先选择北邮计算机学硕。主要原因是:相比成电,北邮计算机学硕的目标分数更低,录取率更高,而且北邮的地理位置优势明显。对于…

OpenHarmony和OpenVela的技术创新以及两者对比

两款有名的国内开源操作系统,OpenHarmony,OpenVela都非常的优秀。本文对二者的创新进行一个简要的介绍和对比。 一、OpenHarmony OpenHarmony具有诸多有特点的技术突破和重要贡献,以下是一些主要方面: 架构设计创新 分层架构…

C语言——实现找出最高分

问题描述&#xff1a;分别有6名学生的学号、姓名、性别、年龄和考试分数&#xff0c;找出这些学生当中考试成绩最高的学生姓名。 //找出最高分#include<stdio.h>struct student {char stu_num[10]; //学号 char stu_name[10]; //姓名 char sex; //性别 int age; …

Qt Quick:CheckBox 复选框

复选框不止选中和未选中2种状态哦&#xff0c;它还有1种部分选中的状态。这3种状态都是Qt自带的&#xff0c;如果想让复选框有部分选中这个状态&#xff0c;需要将三态属性&#xff08;tristate&#xff09;设为true。 未选中的状态值为0&#xff0c;部分选中是1&#xff0c;选…

Docker常用命令总结~

1、关于镜像 获取镜像 docker pull [image name] [option:tag]AI助手//获取postgres镜像(没有设置镜像版本号则默认获取最新的&#xff0c;使用latest标记) docker pull postgres or docker pull postgres:11.14 列出本地镜像 docker imagesAI助手 指定镜像启动一个容…