2023-05-29 用 fltk gui库编写一个打字练习程序

news2024/10/3 4:40:14

用 fltk gui库编写一个打字练习程序

  • 前言
  • 一、FLTK GUI 库
  • 二、使用步骤
    • 1.引入库
    • 2.使用代码
  • 总结


前言

给孩子练习键盘打字, 发现终端还是欠点意思, 研究了一下gui, 最终用 fltk库弄了一个.

对于没有接触过gui的人, 发现, 编程的逻辑和终端区别很大, 很繁琐, 可能需要适应适应, 另外, 文档很重要, 示例很重要.


一、FLTK GUI 库

FLTK is a cross-platform C++ GUI toolkit for UNIX®/Linux® (X11), Microsoft® Windows®, and macOS®. FLTK provides modern GUI functionality without the bloat and supports 3D graphics via OpenGL® and its built-in GLUT emulation.

FLTK is designed to be small and modular enough to be statically linked, but works fine as a shared library. FLTK also includes an excellent UI builder called FLUID that can be used to create applications in minutes.

FLTK is provided under the terms of the GNU Library Public License, Version 2 with exceptions that allow for static linking.

总之, 就是足够小, 跨平台, 可商用, 当然更具体的请去官网查看.

二、使用步骤

1.引入库

我使用msys2安装的, 因为比较容易, 我暂时不想自己编译.

以下是比较常用的头文件, 主要用于建立窗口, 输入输出框, 时钟, GUI也少不了图片解析, 比如jpg和png.

#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Clock.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Image.H>
#include <FL/Fl_PNG_Image.H>

编译参数需要加上fltk的库文件

 E:\msys64\clang64\bin\clang++.exe -glldb  -lfltk -lfltk_images  test227.cpp p -o E:\clangC++\answer\C++\test227.exe 

2.使用代码

代码如下(示例):

头文件, 用于给出最基本的结构及函数, 为了能够catch键盘事件, 派生一个windowInput类, 改写handle函数.

// generated by Fast Light User Interface Designer (fluid) version 1.0308
#ifndef TYPING_H
#define TYPING_H

#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Clock.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Output.H>

struct windowInput : Fl_Input
{
    windowInput(int X, int Y, int W, int H, const char *l = nullptr)
        : Fl_Input(X, Y, W, H, l)
    {}
    auto handle(int event) -> int override;
};

struct windowObject
{
    Fl_Double_Window *window;
    Fl_Box *box;
    windowInput *input;
    Fl_Output *displayText;
    Fl_Output *displayChar;
    Fl_Clock *clock;
};

auto makeWindow(const char *fileName) -> windowObject &;

auto openFile(const char *fileName) -> bool;

#endif

cpp文件, 装载函数实现, 但我要坦白, 由于对库不是特别了解, 使用了大量的全局数据, 但通过匿名的命名空间, 约束在cpp文件中, 尽量不污染全局.

gui本身不复杂, 但需要熟练, 文档和示例协助理解.

当然, 编程思路和终端编程还是有比较大的区别, 比如, 原先我想主程序由while循环和标准IO流驱动, 但发现, 在这种框架下是不可能的, 因为需要在进入gui框架循环前不能有任何阻塞, 否则就进入不了图形界面, 所以需要将循环部分揉进GUI框架的handle函数中, 而这个函数, 还不能传进数据, 只能用全局数据.

不过也可能是我用的实在不熟, 一天时间有点紧, 可能callback这种传数据的方法, 更符合这种编程模式, 只是我不太了解callback的运行逻辑(这个GUI框架的逻辑), 可能要看看源码.

// generated by Fast Light User Interface Designer (fluid) version 1.0308
#include "typingGUI.h"
#include <FL/Fl_Image.H>
#include <FL/Fl_PNG_Image.H>
#include <fstream>
#include <string>

namespace
{
windowObject winObj;

std::ifstream file;
std::string text;
std::array<char, 128> chrArr{"请输入: "};

int chr = 0xff8d;
int charIndex;

auto image_keyboard2(const char *fileName) -> Fl_Image *
{
    static Fl_Image *image = new Fl_PNG_Image(fileName);
    return image;
}

} // namespace

auto openFile(const char *fileName) -> bool
{
    file.open(fileName);
    return file.is_open();
}

auto windowInput::handle(int event) -> int
{
    if (event == FL_KEYDOWN || event == FL_KEYUP)
    {
        static int keycode;
        keycode = Fl::event_key();

        if (keycode == chr)
        {
            if (charIndex != text.size())
            {
                chr = text[charIndex];
                chrArr[11] = text[charIndex++];
                winObj.displayChar->value(chrArr.data());
                winObj.input->value(reinterpret_cast<char *>(&chr));
            }
            else if (file >> text)
            {
                charIndex = 0;
                chr = text[charIndex];
                chrArr[11] = text[charIndex++];
                winObj.displayText->value(text.c_str());
                winObj.displayChar->value(chrArr.data());
                winObj.input->value(reinterpret_cast<char *>(&chr));
            }
            else
            {
                winObj.displayText->value("恭喜过关, 请关闭窗口");
                file.close();
            }
        }
        else
        {
            winObj.input->value(reinterpret_cast<char *>(&keycode));
        }
    }
    return Fl_Input::handle(event);
}

auto makeWindow(const char *fileName) -> windowObject &
{
    winObj.window = new Fl_Double_Window(1920, 1017, "打字练习");
    winObj.window->resizable(winObj.window);

    // 获取系统中的字体数目
    Fl::set_fonts("-*");

    if (winObj.window != nullptr)
    {
        winObj.window->box(FL_UP_BOX);
        winObj.window->color(static_cast<Fl_Color>(25));

        {
            winObj.box = new Fl_Box(80, 23, 1720, 512);
            winObj.box->image(
                image_keyboard2(fileName)); //"E:\\clangC++\\keyboard2.png"
            winObj.box->labelfont(617);
            winObj.box->labelsize(53);
            winObj.box->labelcolor(static_cast<Fl_Color>(139));
        } // Fl_Box* box

        {
            winObj.input = new windowInput(276, 747, 1517, 84, "input:");
            winObj.input->labelfont(617);
            winObj.input->labelsize(72);
            winObj.input->textfont(617);
            winObj.input->textsize(72);
            winObj.input->align(static_cast<Fl_Align>(36));
        } // Fl_Input* input

        {
            winObj.displayText = new Fl_Output(83, 545, 1710, 84);
            winObj.displayText->box(FL_UP_BOX);
            winObj.displayText->labeltype(FL_NO_LABEL);
            winObj.displayText->labelfont(617);
            winObj.displayText->labelsize(72);
            winObj.displayText->textfont(617);
            winObj.displayText->textsize(72);
            winObj.displayText->value("按回车开始练习!");
        } // Fl_Text_Display* displayText

        {
            winObj.displayChar = new Fl_Output(83, 644, 1710, 84);
            winObj.displayChar->box(FL_UP_BOX);
            winObj.displayChar->labeltype(FL_NO_LABEL);
            winObj.displayChar->labelfont(617);
            winObj.displayChar->labelsize(72);
            winObj.displayChar->textfont(617);
            winObj.displayChar->textsize(72);
        } // Fl_Text_Display* displayChar

        {
            winObj.clock = new Fl_Clock(918, 849, 150, 150);
            winObj.clock->labelfont(617);
            winObj.clock->labelsize(24);
            winObj.clock->align((FL_ALIGN_CENTER));
        } // Fl_Clock* clock
        winObj.window->end();

        winObj.window->show();
    } // Fl_Double_Window* window

    return winObj;
}

下面是测试程序, 就显得十分简单了, 毕竟运行逻辑都在Cpp文件中了

#include "typingGUI.h"

auto main() -> int
{
    openFile("E:\\clangC++\\keytest.txt");
    makeWindow("E:\\clangC++\\keyboard2.png");

    return Fl::run();
}

这是最终效果:

打字练习
看着像是 二十年前的程序, 对的, 这个GUI就是比较简朴, 低调, 不油腻.

其实就是丑, 我承认, 但第一次吗, 还有进步空间. 编译后大概430多k, 和终端程序没有明显区别.


总结

没什么好总结的, 简单使用而已, 一般来讲是足够了.

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

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

相关文章

Windows远程Centos7图形化界面

一、centos7服务器安装tigervnc 1、更新yum源 yum update 2、安装tigervnc yum -y install tigervnc* 3、启动vnc vncserver &#xff08;1&#xff09;执行命令后需要输入密码 &#xff08;2&#xff09;再次输入密码 注意&#xff1a;密码一定要记住&#xff0c;方便以…

链表反转方法汇总

反转范围之前有节点&#xff0c;prev就指向该节点&#xff0c;没有就prevnull&#xff1b; 一、头插法 class Solution {public ListNode reverseList(ListNode head) {ListNode header new ListNode(-1);ListNode cur head;while(cur ! null) {ListNode tmp cur.next;cur.…

LabVIEWCompactRIO 开发指南第六章41 同步模块

同步模块 同时运行的模块每个通道有一个ADC&#xff0c;并且采集数据时通道之间没有明显的偏差。同步模块的两个子类别&#xff0c;按需和三角积分&#xff0c;通过SPI总线传输数据&#xff0c;并受到其他SPI总线模块的所有规格和挑战的约束。 按需转换 表6.1.具有按需转换的…

Postgresql源码(104)子连接提升过程pull_up_sublinks

1 场景构造 drop table student; create table student(sno int primary key, sname varchar(10), ssex int); insert into student values(1, stu1, 0); insert into student values(2, stu2, 1); insert into student values(3, stu3, 1); insert into student values(4, st…

模块化

一、目标 能够说出模块化的好处能够知道CommonJS规定了哪些内容能够说出Node.js中模块的三大分类各自是什么能够使用npm管理包能够了解什么是规范的包结构能够了解模块的加载机制 二、目录 模块化的基本概念Node.js中模块的分类npm与包模块的加载机制 1.模块化的基本概念 …

spring源码解读

深入了解Spring Bean Java bean和spring bean区别 Java bean的属性私有&#xff0c;只能通过get和set方法来对属性进行操作。Spring bean是由spring容器生成和管理的对象。 spring Bean的定义方式 xml文件 。 声明式。 bean注解。 声明式。 component注解。声明式。 Bea…

房产中介APP开发功能有哪些?

房产中介APP开发功能有哪些&#xff1f; 1. 发布信息。中介或房东通过房地产中介APP客户端发布出租房屋的相关信息。 2. 房屋搜查。根据不同类型的房源进行分类&#xff0c;如公寓、整租、合租、写字楼、办公楼等&#xff0c;也可以根据不同的位置信息、商圈、距…

2023年下半年软考高级需要报班吗?

首先&#xff0c;对于软考高级考试报班与否的问题&#xff0c;需要根据自身的情况来做出决定。如果你有较强的自学能力&#xff0c;且具备丰富的实际工作经验和技术知识&#xff0c;那么不报班也完全可以自学备考。但如果你对软件工程的知识掌握程度较低&#xff0c;或者时间紧…

算法01-算法概念与描述

文章目录 总结大纲要求算法概念举个例子&#xff1a;量水问题 算法描述算法的时间复杂度 总结 本系列为C算法学习系列&#xff0c;会介绍 算法概念与描述&#xff0c;入门算法&#xff0c;基础算法&#xff0c;数值处理算法&#xff0c;排序算法&#xff0c;搜索算法&#xff…

软件测试炸了,作为从业者,你做好准备了吗?

软件测试行业已经发生很大变化&#xff0c;你跟上变化了吗&#xff1f; 岗位少不可怕&#xff0c;要求越来越高也不可怕&#xff0c;可怕的是&#xff0c;软件测试行业已经发生巨变&#xff0c;而你却原地踏步&#xff01;目前一线大厂更多倾向于招收测试开发&#xff0c;或者…

06. 数据结构之散列表

前言 散列表也叫作哈希表&#xff08;hash table&#xff09;&#xff0c;这种数据结构提供了键&#xff08;Key&#xff09;和值&#xff08;Value&#xff09;的映射关系。只要给出一个Key&#xff0c;就可以高效查找到它所匹配的Value&#xff0c;时间复杂度接近于O(1) 1.…

photoshop矫正扫描图片的倾斜问题以及修改图片内容

由于工程原因&#xff0c;资料需要重新梳理 1.扫描工程表格到电脑中 2.在ps中导入表格内容&#xff08;表格有时候是倾斜的&#xff09; 需要修正为正常状态&#xff0c;即垂直状态 设置步骤&#xff1a; 1.调整ps的背景颜色与所在图片的背景颜色一致 用吸管工具&#xff…

AbandonedConnectionCleanupThread$ConnectionFinalizerPhantomReference内存溢出

网上查了查资料&#xff0c;根据自己情况在这里整理了一下&#xff0c;供大家学习和参考。 目录 1、现象 2、mysql-connector-java 源码分析 3、解决方法 3.1、配置disableAbandonedConnectionCleanup 3.2、暴力解决方式-----定时GC 4、什么是虚引用 5、关联对象真的被回…

数据可视化:趋势类可视化图表大全

图表是处理数据的重要组成部分&#xff0c;因为它们是一种将大量数据压缩为易于理解的格式的方法。数据可视化可以让受众快速Get到重点。 数据可视化的图表类型极其丰富多样&#xff0c;而且每种都有不同的用例&#xff0c;通常&#xff0c;创建数据可视化最困难的部分是确定哪…

【Linux】常用命令的汇总学习

文章目录 1.目录切换命令2.目录操作命令3.把ls -l中包含字母file&#xff08;不区分大小写&#xff09;的内容输出4.统计txt中的某个字符串5.grep命令的使用6.linux查找当前目录下所有txt文件7.linux中的find命令8.查看系统所有的进程信息9.如何确定文件的类型10.tar解压缩11.U…

员工防范网络钓鱼攻击的10个实用技巧

你知道网络钓鱼攻击的危害吗&#xff1f;以下是网络钓鱼的定义及其引起关注的原因&#xff1a; Verizon 最近的一份报告显示&#xff0c;82&#xff05;的网络漏洞均由人为因素造成&#xff0c;比如窃取凭证、网络钓鱼攻击、社会工程学、冒名顶替、滥用或错误等。网络钓鱼攻击…

惊!掌握千问通义的关键,从这些必知内容开始!

今年快过半了&#xff0c;要说顶流话题还得是ChatGPT&#xff0c;相关话题的热度居高不下&#xff0c;而其从GPT-3.5到GPT-4的升级&#xff0c;也让我们深刻了解了什么叫一代版本一代神&#xff0c;从GPT-3.5到GPT-4&#xff0c;真的就是一个跨阶级式的升级。 技术内涵 ChatGPT…

某SRC的渗透测试实战

前言 因为不甘心被称作会只点鼠标的猴子&#xff0c;所以开始了一次某SRC漏洞挖掘&#xff0c;为期一个多星期。文章有点长&#xff0c;但请耐心看完&#xff0c;记录了完整的SRC漏洞挖掘实战 渗透过程 因为选择的幸运儿没有对测试范围进行规划&#xff0c;所以此次范围就是…

OPC UA客户端访问 OPC DA服务器

目标 用OPC UA客户端&#xff08;如UaExpert&#xff09;读取OPC DA服务器上的点。 原理 OPC DA是基于COM/DCOM的&#xff0c;传统OPC DA客户端访问非本机OPC DA服务时需要配置DCOM。OPC UA客户端无法直接访问 OPC DA服务&#xff0c;需要将OPC DA服务映射为OPC UA服务&#x…

【Excel技巧】3个限制权限,保护表格不被人随意改动

Excel表格是很多人工作中经常用到的办公软件&#xff0c;有时候做好表格发给对方后&#xff0c;总是担心会被不小心做了改动。 如果有这种顾虑&#xff0c;就一定要用上Excel表格的3个“限制权限”&#xff0c;可以根据不同的情况&#xff0c;设置不同保护。下面就来看看可以设…