SDL学习笔记(4):第二个SDL实例 T9KeyBoard

项目说明

SDL实现一个T9键盘

设计思想

1.图片准备
找一张T9键盘的图片
2.字体包准备
宋体 simfang.ttf
3.程序设计
显示T9键盘图片
确定每块键的区域坐标
响应点击事件(点击区域+连续点击次数)
显示输入字符串
渲染器定时刷新

代码展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#include <SDL.h>
#include <SDL_ttf.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
//窗口的坐标
#define WINDOW_X 100
#define WINDOW_Y 100
//窗口的大小
#define WINDOW_WIDTH 300
#define WINDOW_HEIGHT 400
//输出框的高度
#define SCREEN_HEIGHT 100
//键盘宫格的大小
#define KEY_UNIT_X 100
#define KEY_UNIT_Y 100
//键盘的大小
#define KEY_ROW 3
#define KEY_COLUMN 3
//最多显示的字符数
#define MAX_BUFF 12
//可修改输入的最大时间间隔
#define CLICK_INTERVAL 30
//字体
#define FONT_STYLE "simfang.ttf"
//窗体,渲染器,键盘,字符串,文字,颜色等变量定义
SDL_Window *window = nullptr;
SDL_Renderer *renderer = nullptr;
SDL_Texture *keyboard = nullptr;
SDL_Texture *character = nullptr;
SDL_Surface *letter = NULL;
SDL_Color color = {255,255,255};
//字符串相关变量定义及初始化
int buff_cnt = 0;
char buff[MAX_BUFF];
char keychar[][5] = {{'.','_','@','/','#'},
{'a','b','c'},
{'d','e','f'},
{'g','h','i'},
{'j','k','l'},
{'m','n','o'},
{'p','q','r','s'},
{'t','u','v'},
{'w','x','y','z'}};
//加载png图片
SDL_Texture* LoadImage(SDL_Renderer *renderer,char *file) {
SDL_Texture *tex = nullptr;
//加载图片
tex = IMG_LoadTexture(renderer,file);
if (tex == nullptr)
throw runtime_error("Failed to load image." + string(file) + IMG_GetError());
return tex;
}
//加载字体
SDL_Surface *Load_ttfText(char *filename,int size,const char *text,SDL_Color color)
{
TTF_Font *font;
SDL_Surface *ptext;
//打开字体库
font = TTF_OpenFont(filename,20);
if (font == NULL) {
printf ("TTF_OpenFont fail:%s",SDL_GetError());
}
//创建文字
ptext = TTF_RenderText_Solid(font,text,color);
if (ptext == NULL) {
printf ("TTF_RenderText_Solid fail:%s",SDL_GetError());
}
//关闭字体库
TTF_CloseFont(font);
return ptext;
}
//功能函数:判断数值是否落入区间内
bool IsInInterval(double lower,double upper,double pos) {
if (pos > lower && pos < upper) {
return true;
}
else {
return false;
}
}
//判断点击事件发生的位置
int ClickPos() {
//区间头
int x_upper,x_lower;
//区间尾
int y_upper,y_lower;
SDL_Event event;
if (SDL_PollEvent (&event)) {
switch (event.type) {
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) {
//获取点击位置
int x = event.button.x;
int y = event.button.y-SCREEN_HEIGHT;
//i行,j列
for (int i = 0;i < KEY_ROW;i++) {
for (int j = 0;j < KEY_COLUMN;j++) {
x_lower = KEY_UNIT_X * j;
x_upper = KEY_UNIT_X + x_lower;
y_lower = KEY_UNIT_Y * i;
y_upper = KEY_UNIT_Y + y_lower;
//判断点击位置是否落入i*3+j号宫格内
if (IsInInterval(x_lower,x_upper,x) && IsInInterval(y_lower,y_upper,y)) {
return i*3+j;
}
}
}
}
}
}
return -1;
}
//当显示字符到达上限时,所有字符左移
void LeftShift(char *buff,char ch) {
for (int i = 0;i < MAX_BUFF-1;i++) {
buff[i] = buff[i+1];
}
buff[MAX_BUFF-1] = ch;
}
//显示最新的buff
void Display(SDL_Renderer *renderer,SDL_Texture *keyboard,SDL_Texture *character,SDL_Surface *letter,SDL_Color color,char *buff,int buff_cnt) {
letter = Load_ttfText(FONT_STYLE, 60, buff, color);
character = SDL_CreateTextureFromSurface(renderer, letter);
SDL_RenderClear(renderer);
//将更新后的character加载到渲染器上
SDL_Rect rect_character = {20,30,20*(buff_cnt+1),60};
SDL_Point center_character = {0,0};
SDL_RenderCopyEx(renderer,character,NULL,&rect_character,0,&center_character,SDL_FLIP_NONE);
//将更新后的keyboard加载到渲染器上
SDL_Rect rect_keyboard = {0,100,WINDOW_WIDTH,WINDOW_HEIGHT-SCREEN_HEIGHT};
SDL_Point center_keyboard = {0,0};
SDL_RenderCopyEx(renderer,keyboard,NULL,&rect_keyboard,0,&center_keyboard,SDL_FLIP_NONE);
//展示渲染器
SDL_RenderPresent(renderer);
}
int main(int argc, char* argv[]) {
//初始化
if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
cout << SDL_GetError() << endl;
return 1;
}
//创建窗口
window = SDL_CreateWindow("T9KeyBoard",WINDOW_X,WINDOW_Y,WINDOW_WIDTH,WINDOW_HEIGHT,SDL_WINDOW_SHOWN);
if (window == nullptr) {
cout << SDL_GetError() << endl;
return 2;
}
//创建渲染器
renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == nullptr) {
cout << SDL_GetError() << endl;
return 3;
}
//初始化字体库
if (TTF_Init() == -1) {
cout << TTF_GetError() << endl;
return 4;
}
//清空渲染器
SDL_RenderClear(renderer);
//加载图片
keyboard = LoadImage(renderer,"../T9keyboard.png");
//将keyboard加载到渲染器上
SDL_Rect rect = {0,100,WINDOW_WIDTH,WINDOW_HEIGHT-SCREEN_HEIGHT};
SDL_Point center = {0,0};
SDL_RenderCopyEx(renderer,keyboard,NULL,&rect,0,&center,SDL_FLIP_NONE);
//展示渲染器
SDL_RenderPresent(renderer);
while(true) {
//计时器
int timer = 0;
//表示该宫格的第几个字符
int sub_pos = 0;
//是否已经显示在屏幕上
int has_record = 0;
//获取点击的宫格号
int pos = ClickPos();
for (int i = 0;i < KEY_ROW*KEY_COLUMN;i++) {
//找到该宫格
if (i == pos) {
while (true) {
timer++;
//设置延时
SDL_Delay(CLICK_INTERVAL);
if (ClickPos() == pos) {
timer = 0;
sub_pos++;
//多次点击同一个宫格,字符循环
if (pos == 0) {
sub_pos %= 5;
}
else if (pos == 6 || pos == 8) {
sub_pos %= 4;
}
else {
sub_pos %= 3;
}
}
//超过最大时间间隔,自动确定输入字符
if (timer >= CLICK_INTERVAL) {
break;
}
//判断显示字符数到达上限以及是否显示在屏幕上
if (buff_cnt < MAX_BUFF || has_record == 1) {
buff[buff_cnt] = keychar[pos][sub_pos];
}
else {
has_record = 1;
LeftShift(buff,keychar[pos][sub_pos]);
}
//展示最新已输入的字符串
Display(renderer,keyboard,character,letter,color,buff,buff_cnt);
}
//字符数增加一,如已达到上限则不增加
if (buff_cnt < MAX_BUFF) {
buff_cnt++;
}
}
}
}
//释放
SDL_DestroyTexture(keyboard);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return 0;
}

项目成果

这里写图片描述