网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
08月13日漏签0天
sdl吧 关注:4,212贴子:12,534
  • 看贴

  • 图片

  • 吧主推荐

  • 视频

  • 游戏

  • 11回复贴,共1页
<<返回sdl吧
>0< 加载中...

【教程向】如何在SDL2中实现InputBox

  • 取消只看楼主
  • 收藏

  • 回复
  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
原版的教程在我的博客上:在SDL中实现一个输入框 (gitee.io)
然后如果要参考完整的代码的话看看这里src/gui.cpp · VisualGMQ/SDLEngine - 码云 - 开源中国 (gitee.com)
和这里include/gui.hpp · VisualGMQ/SDLEngine - 码云 - 开源中国 (gitee.com)
不过不建议看源码,一是写的比较乱,二是里面有很多不相干的代码。
这里附上实现的效果:

本来是在写游戏的,然后发现需要用GUI,就打算自己写一个。这个InputBox比较难处理,自己也想了不少,所以就发一篇贴来说一下经验。
楼下讲一下做的一些要点和注意事项


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
靠我的链接居然无了,算了直接说吧。


2025-08-13 15:08:28
广告
不感兴趣
开通SVIP免广告
  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
如果不开启输入SDL是不会给你推这两个事件的


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
三楼写的有问题,重写了一下:
首先是SDL如何接收用户输入的问题。使用的是SDL_StartTextInput和SDL_StopTextInput两个函数。第一个用来开启输入,第二个用来关闭输入。
开启输入后,当你进行输入的时候分两种情况:编辑输入法条和输入。
编辑输入法条就是会屏幕上会出现输入法条,这个时候你需要选词什么的:

输入就是当你选词选好了,按下空格/回车,输入法条消失的时候,这个时候你的词会输入到文本框中,这就是输入步骤。或者当你打英文的时候没有输入法条时,打的英文也会直接输入到文本框。
在编辑输入法条的时候,SDL会发送SDL_TEXTEDITING事件,包含了正在编辑的文字和输入法条中的光标位置。当输入文字时,SDL会发送SDL_TEXTINPUT事件,包含了输入的文本


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
这个时候第一个问题就来了。
SDL推给你的SDL_TEXTINPUT/SDL_TEXTEDITING中的文字(分别在event.text.text和event.edit.text中)都是UTF-8编码,如果你使用SDL_ttf可以通过TTF_RenderUTF8_XXX系列函数生成图像。
但是我们的输入框需要按下BACKSPACE删除文字,按下左右键进行光标的移动,这就非常有必要判断当前光标所在的文字的UTF-8编码所占char的个数。
因为UTF-8编码是不定长编码,最小占一个char,最多能占4 char,假设你存下了event.text.text中的字符为std::string(记为text_),那你按下BACKSPACE的时候就不能只调用text_.pop(),要看情况pop 1~4个字符;在移动光标的时候也是。这就很烦


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
所以第一步就是统一编码(当然你也可以在对光标操作的时候自己判断光标左右的UTF-8编码所占的char个数然后pop,我这里直接就统一编码)。
统一编码有两种方法:统一成UTF-8或者Unicode.
我这里是统一成UTF-8(别问我为什么,我造完轮子之后才发现好像用Unicode更好),我自己仿照std::string写了个utf8string的类,可以将const char*, std::string, std::array<char, 4>转换成UTF-8并且存下来,utf8string的基本单元就是std::array<char,4>,即一个UTF-8字符。
这就是将每个UTF-8字符分开,而不是像SDL一样都揉在一个std::string中。
或者你可以使用Unicode。Unicode是以16位为一个编码,所以你可以用std::wstring来存而不是自己写类。不过使用Unicode的话如果想要将Unicode转换为std::string得考虑大小端问题,而且最后生成纹理的时候还得转成Uint16数组然后传给TTF_RenderUNICODE_XXX函数。
总之就是想个办法让每个字符独立分开,不然杂糅在一起后面不好操作


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
然后就是判断用户是否正在编辑输入法条的问题。这里需要使用一个变量isEditing来记录。
具体的话直接上代码:

这里要注意的是,如果你编辑输入法条的时候将里面东西都删了,这样输入法条也会消失,但是不会给你推SDL_TEXTINPUT事件,反而会推一个SDL_TEXTEDITING事件并且event.edit.text的长度为0,这也是为什么第2行要判断的原因。


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
因为如果用户在编辑输入法条,那么你按下退格和左右键是不应该移动InputBox内的光标的,所以有必要判断


2025-08-13 15:02:28
广告
不感兴趣
开通SVIP免广告
  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
最后,当你成功解决了上述所有问题后,你可能会发现每次你输入中文,你的输入法条总是在屏幕的左上角,而不是像其他InputBox一样在输入的位置的下方。
这个时候你可以尝试使用SDL_SetTextInputRect(),并将你的InputBox的Rect给他。注意我说的是”尝试“,因为根据其他人的反馈,这个函数好像不总是能生效(但是在我的MacOS上是有用的)


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
以上就是我这次编写的所有坑。好家伙坑是真多啊。不过还好踩掉了。希望这个帖子对吧友有所帮助


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
补个我博客的教程吧,里面只是给了些代码的实现,重点和坑我上面都说完了
https://visualgmq.gitee.io/2021/09/21/%E5%9C%A8SDL%E4%B8%AD%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E8%BE%93%E5%85%A5%E6%A1%86/#SDL2%E7%9A%84%E8%BE%93%E5%85%A5%E9%97%AE%E9%A2%98


  • 木土土ttk
  • 高级粉丝
    3
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
再补一个SDL官网给的关于输入的教程
https://wiki.libsdl.org/Tutorials-TextInput


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 11回复贴,共1页
<<返回sdl吧
分享到:
©2025 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示