2025年EGE绘图之五 按钮(下)

EGE绘图之五 按钮(下)按钮添加状态 交互展现不同的样式 ege 创建按钮栏

EGE专栏:EGE专栏

上一篇:EGE绘图之(五) 按钮(上)

下一篇:

四、按钮状态

1. 按钮状态分类

  给按钮加上几个状态参数,比如用来标记 点击,选中,悬停,可被选中之类的按键状态。绘制按钮时,就根据这些状态,选用不同的样式来绘制按钮,给予用户更好的交互体验。

  通常是选用不同的颜色,改变按钮大小,叠加图形等,也有更换样式的。

  这些状态在鼠标进行按下,松开,悬停,点击之类的操作时进行相应的更改。
  一个按钮分为以下几种状态,用于和用户进行交互。对于根据不同状态显示不同样式的按钮,操作上会更为友好。

No. 状态名 含义
描述
1 Enabled 可用状态 按钮是否可用,不可用的按钮不响应事件
2 Visible 可见状态 按钮是否可见
3 Pressed 按下状态 按键是否被按下
4 Checked 选中状态 按钮处于选中或非选中状态
5 Checkable 可选状态 设置按钮是否可以切换选中状态
6 Focused 焦点状态 按钮是否取得焦点
7 Hovered 悬停状态 鼠标,指针等悬停在按钮上方

2. 按钮状态交互

  对于上面几种状态,需要根据鼠标操作来实时进行交互的有 选中,按下和悬停,重点便是这几种状态的交互。

2.1 状态变化:选中 (Checked)

  选中状态一般由点击事件进行触发状态改变,外观上和处于非选中的按钮有较大的区别。

  可选状态(Checkable):用于设置用户是否可以切换按钮的选中状态,当按钮设置了初始状态后,按钮选中和非选中将不可由用户行为进行切换

在这里插入图片描述

选中状态切换示例

  这里只简单地做个选中的示例:当鼠标点击按钮后,按钮的选中状态选中非选中之间切换。

if (insideButton(&buttonArray[i], x, y)) {
   
	//状态切换,这里在选中和非选中之间切换
	buttonArray[i].checked = !buttonArray[i].checked;
}

  对于按钮的不同状态,设置不同的填充颜色。

for (int i = 0; i < length; i++) {
   
	//根据状态进行不同的绘制,这里按状态改变颜色
	if (buttonArray[i].checked) {
   
		setfillcolor(EGEARGB(0xFF, 0x1E, 0x90, 0xFF));
	} else {
   
		setfillcolor(EGEARGB(0xFF, 0x40, 0xE0, 0xD0));
	}
}

  如下图所示,在点击后,切换按钮选中状态为选中和非选中,选中状态的按钮显示为蓝色。
在这里插入图片描述

示例代码
#include <graphics.h>

struct CircleButton
{
   
	int x, y;		/* 圆心*/
	int radius;		/* 半径*/
	bool checked;	/* 是否选中*/
};

// 判断点(x, y)是否在按钮点击区域内部
bool insideButton(const CircleButton* button, int x, int y);

// 绘制所有按钮
void drawButton(const CircleButton buttonArray[], int length);

// 查找 (x, y) 所在的按钮,返回按钮ID, 没有返回 -1
int searchButton(int x, int y, const CircleButton buttonArray[], int length);

// 绘制
void draw();

#define BUTTON_SIZE 8
#define BUTTON_ID_NONE -1

//定义按钮,确定区域
CircleButton buttonArray[BUTTON_SIZE];

// 点击按钮ID
int clickButtonId = BUTTON_ID_NONE;

int btnId = BUTTON_ID_NONE;

int main()
{
   
	initgraph(640, 480, INIT_RENDERMANUAL);
	setbkcolor(WHITE);
	setbkmode(TRANSPARENT);
	ege_enable_aa(true);

	for (int i = 0; i < BUTTON_SIZE; i++) {
   
		buttonArray[i].x = (i % 2 * 2 + 1) * 640 / 4;
		buttonArray[i].y = (i / 2) * 320 / 3 + 60;
		buttonArray[i].radius = 50;
		buttonArray[i].checked = false;
	}

	bool redraw = true;

	for (; is_run(); delay_fps(60)) {
   
		while (mousemsg()) {
   
			mouse_msg msg = getmouse();

			//判断鼠标左键点击(左键按下确定位置,抬起为执行时刻)
			if (msg.is_left()) {
   
				if (msg.is_down()) {
   
					btnId = searchButton(msg.x, msg.y, buttonArray, BUTTON_SIZE);
				}
				else {
   
					// 存在点击的按钮,则设置状态,这里状态在选中和非选中之间切换
					if (btnId != BUTTON_ID_NONE) {
   
						buttonArray[btnId].checked = !buttonArray[btnId].checked;
						redraw = true;
					}
					
					if (clickButtonId != btnId) {
   
						clickButtonId = btnId;
						redraw = true;
					}
				}
			}
		}

		// 判断是否需要重绘,减少不必要的绘制操作
		if (redraw) {
   
			cleardevice();
			draw();
			redraw = false;
		}
	}

	return 0;
}


bool insideButton(const CircleButton* button, int x, int y)
{
   
	int dx = x - button->x, dy = y - button->y;
	return (dx * dx + dy * dy) <= (button->radius * button->radius);
}

void drawButton(const CircleButton buttonArray[], int length)
{
   

	setfillcolor(EGEARGB(0xFF, 0x1E, 0x90, 0xFF));
	setcolor(WHITE);
	settextjustify(CENTER_TEXT, CENTER_TEXT);
	setfont(36, 0, "");

	color_t lastFillColor = getfillcolor();

	for (int i = 0; i < length; i++) {
   
		//根据状态进行不同的绘制,这里按状态改变颜色
		color_t curColor;
		if (buttonArray[i].checked) {
   
			curColor = EGEARGB(0xFF, 0x1E, 0x90, 0xFF);
		}
		else {
   
			curColor = EGEARGB(0xFF, 0x40, 0xE0, 0xD0);
		}

		//为了减少颜色设置操作进行的优化操作,少量绘制可有可无
		if (lastFillColor != curColor) {
   
			setfillcolor(curColor);
			lastFillColor = curColor;
		}

		// 绘制按钮
		ege_fillellipse(buttonArray[i].x - buttonArray[i].radius,
			buttonArray[i].y - buttonArray[i].radius,
			2 * buttonArray[i].radius,
			2 * buttonArray[i].radius);

		xyprintf(buttonArray[i].x, buttonArray[i].y, "%d", i);
	}
}

int searchButton(int x, int y, const CircleButton buttonArray[], int length)
{
   
	int buttonId = BUTTON_ID_NONE;

	for (int i = 0; i < length; i++) {
   
		if (insideButton(&buttonArray[i], x, y)) {
   
			buttonId = i;
			break;   //退出,已经检测到,后面的按钮不再检测
		}
	}

	return buttonId;
}

void draw()
{
   
	//绘制
	drawButton(buttonArray, BUTTON_SIZE);
	setcolor(BLACK);
	setfont(24, 0, "");
	settextjustify(LEFT_TEXT, TOP_TEXT);
	xyprintf(240, 360, "点击按钮ID:%d", clickButtonId);
}

2.2 状态变化:悬停(Hovered)

  悬停状态:鼠标移动到按钮位置上方却没有按下时的状态。

  检测到鼠标位置移动时,对按钮进行检索,找到悬停的按钮,将按钮标记为悬停状态,而原先如果有悬停的按钮,则将原先的按钮取消悬停状态。

在这里插入图片描述

#include <graphics.h>

struct CircleButton
{
   
	int x, y;		/* 圆心*/
	int radius;		/* 半径*/
	bool hovered;	/* 是否悬停*/
};

// 判断点(x, y)是否在按钮点击区域内部
bool insideButton(const CircleButton* button, int x, int y);

// 绘制所有按钮
void drawButton(const CircleButton buttonArray[], int length);

// 查找 (x, y) 所在的按钮,返回按钮ID, 没有返回 -1
int searchButton(int x, int y, const CircleButton buttonArray[], int length);

// 绘制
void draw();

#define BUTTON_SIZE 8
#define BUTTON_ID_NONE -1

//定义按钮,确定区域
CircleButton buttonArray[BUTTON_SIZE];

// 悬停按钮ID
int hoveredButtonId = BUTTON_ID_NONE;

int main()
{
   
	initgraph(640, 480, INIT_RENDERMANUAL);
	setbkcolor(WHITE);
	setbkmode(TRANSPARENT);
	ege_enable_aa(true);

	for (int i = 0; i < BUTTON_SIZE; i++) {
   
		buttonArray[i].x = (i % 2 * 2 + 1) * 640 / 4;
		buttonArray[i].y = (i / 2) * 320 / 3 + 60;
		buttonArray[i].radius = 50;
		buttonArray[i].hovered = false;
	}

	hoveredButtonId = BUTTON_ID_NONE;

	int xMouse = 0, yMouse = 0;
	bool redraw = true;

	for (; is_run(); delay_fps(60)) {
   
		bool mouseMoved = false;

		//记录鼠标最后移动的位置

		while (mousemsg()) {
   
			mouse_msg msg = getmouse();

			if (msg.is_move())
			{
   
				mouseMoved = true;
				xMouse = msg.x;
				yMouse = msg.y;
			}
		}

		//当鼠标移动
		if (mouseMoved) {
   
			//查找悬停的按钮
			int btnId = searchButton(xMouse, yMouse, buttonArray, BUTTON_SIZE);

			// 悬停按钮改变
			if (btnId != hoveredButtonId) {
   
				// 标记原先的按钮为非悬停状态
				if (hoveredButtonId != BUTTON_ID_NONE) {
   
					buttonArray[hoveredButtonId].hovered = false;
				}

				// 标记当前悬停的按钮为悬停状态
				if (btnId != BUTTON_ID_NONE) {
   
					buttonArray[btnId].hovered = true;
				}

				hoveredButtonId = btnId;
				redraw = true;
			}
		}

		// 判断是否需要重绘,减少不必要的绘制操作
		if (redraw) {
   
			cleardevice();
			draw();
			redraw = false;
		}
	}

	return 0;
}


bool insideButton(const CircleButton* button, int x, int y)
{
   
	int dx = x - button->x, dy = y - button->y;
	return (dx * dx + dy * dy) <= (button->radius * button->radius);
}

void drawButton(const CircleButton buttonArray[], int length)
{
   

	setfillcolor(EGEARGB(0xFF, 0x1E, 0x90, 0xFF));
	setcolor(WHITE);
	settextjustify(CENTER_TEXT, CENTER_TEXT);
	setfont(36, 0, "");

	color_t lastFillColor = getfillcolor();

	for (int i = 0; i < length; i++) {
   
		//根据状态进行不同的绘制,这里按状态改变颜色
		color_t curColor;
		if (buttonArray[i].hovered) {
   
			curColor = EGEARGB(0xFF, 0x1E, 0x90, 0xFF);
		}
		else {
   
			curColor = EGEARGB(0xFF, 0x40, 0xE0, 0xD0);
		}

		//为了减少颜色设置操作进行的优化操作,少量绘制可有可无
		if (lastFillColor != curColor) {
   
			setfillcolor(curColor);
			lastFillColor = curColor;
		}

		// 绘制按钮
		ege_fillellipse(buttonArray[i].x - buttonArray[i].radius,
			buttonArray[i].y - buttonArray[i].radius,
			2 * buttonArray[i].radius,
			2 * buttonArray[i].radius);

		xyprintf(buttonArray[i].x, buttonArray[i].y, "%d", i);
	}
}

int searchButton(int x, int y, const CircleButton buttonArray[], int length)
{
   
	int buttonId = BUTTON_ID_NONE;

	for (int i = 0; i < length; i++) {
   
		if (insideButton(&buttonArray[i], x, y)) {
   
			buttonId = i;
			break;   //退出,已经检测到,后面的按钮不再检测
		}
	}

	return buttonId;
}

void draw()
{
   
	//绘制
	drawButton(buttonArray, BUTTON_SIZE);
	setcolor(BLACK);
	setfont(24, 0, "");
	settextjustify(LEFT_TEXT, TOP_TEXT);
	xyprintf(240, 360, "悬停按钮ID:%d", hoveredButtonId);
}

2.3 状态变化:按下状态

  按下状态:是指鼠标在按钮的点击区域内按下,还没有抬起的状态。

  一般的做法是,鼠标在按钮的点击区域按下后,就将按钮设置为按下状态,如果鼠标没有松开,即使鼠标离开按钮点击区域,按钮依然是处于按下状态,鼠标抬起后,才解除按键状态。

在这里插入图片描述

#include <graphics.h>

// 圆形按钮
struct CircleButton
{
   
	int x, y;		/* 圆心*/
	int radius;		/* 半径*/
	bool pressed;	/* 是否按下*/
};

// 判断点(x, y)是否在按钮点击区域内部
bool insideButton(const CircleButton* button, int x, int y);

// 绘制所有按钮
void drawButton(const CircleButton buttonArray[], int length);

// 查找 (x, y) 所在的按钮,返回按钮ID, 没有返回 -1
int searchButton(int x, int y, const CircleButton buttonArray[], int length);

// 绘制
void draw();

#define BUTTON_SIZE 8
#define BUTTON_ID_NONE -1

//定义按钮,确定区域
CircleButton buttonArray[BUTTON_SIZE];

// 按下按钮ID
int pressButtonId = BUTTON_ID_NONE;

int main()
{
   
	initgraph(640, 480, INIT_RENDERMANUAL);
	setbkcolor(WHITE);
	setbkmode(TRANSPARENT);
	ege_enable_aa(true);

	for (int i = 0; i < BUTTON_SIZE; i++) {
   
		buttonArray[i].x = (i % 2 * 2 + 1) * 640 / 4;
		buttonArray[i].y = (i / 2) * 320 / 3 + 60;
		buttonArray[i].radius = 50;
		buttonArray[i].pressed = false;
	}

	pressButtonId = BUTTON_ID_NONE;

	bool redraw = true;

	for (; is_run(); delay_fps(60)) {
   

		while (mousemsg()) {
   
			mouse_msg msg = getmouse();

			// 判断鼠标左键按下(左键按下确定位置,同时判断是否为按钮区域
			// 抬起则解除按下状态
			if (msg.is_left()) {
   
				if (msg.is_down()) {
   
					// 检查是否有按钮被按下
					int btnId = searchButton(msg.x, msg.y, buttonArray, BUTTON_SIZE);

					// 将被按下的按钮设置为按下状态
					if (btnId != BUTTON_ID_NONE) {
   
						pressButtonId = btnId;
						buttonArray[pressButtonId].pressed = true;
						redraw = true;
					}
				}
				else {
   
					//左键抬起,如果有按钮被按下,解除按下状态
					if (pressButtonId != BUTTON_ID_NONE) {
   
						buttonArray[pressButtonId].pressed = false;
						pressButtonId = BUTTON_ID_NONE;
						redraw = true;
					}
				}
			}
		}

		// 判断是否需要重绘,减少不必要的绘制操作
		if (redraw) {
   
			cleardevice();
			draw();
			redraw = false;
		}
	}

	return 0;
}


bool insideButton(const CircleButton* button, int x, int y)
{
   
	int dx = x - button->x, dy = y - button->y;
	return (dx * dx + dy * dy) <= (button->radius * button->radius);
}

void drawButton(const CircleButton buttonArray[], int length)
{
   

	setfillcolor(EGEARGB(0xFF, 0x1E, 0x90, 0xFF));
	setcolor(WHITE);
	settextjustify(CENTER_TEXT, CENTER_TEXT);
	setfont(36, 0, "");

	color_t lastFillColor = getfillcolor();

	for (int i = 0; i < length; i++) {
   
		//根据状态进行不同的绘制,这里按状态改变颜色
		color_t curColor;
		if (buttonArray[i].pressed) {
   
			curColor = EGEARGB(0xFF, 0x1E, 0x90, 0xFF);
		}
		else {
   
			curColor = EGEARGB(0xFF, 0x40, 0xE0, 0xD0);
		}

		//为了减少颜色设置操作进行的优化操作,少量绘制可有可无
		if (lastFillColor != curColor) {
   
			setfillcolor(curColor);
			lastFillColor = curColor;
		}

		// 绘制按钮
		ege_fillellipse(buttonArray[i].x - buttonArray[i].radius,
			buttonArray[i].y - buttonArray[i].radius,
			2 * buttonArray[i].radius,
			2 * buttonArray[i].radius);

		xyprintf(buttonArray[i].x, buttonArray[i].y, "%d", i);
	}
}

int searchButton(int x, int y, const CircleButton buttonArray[], int length)
{
   
	int buttonId = BUTTON_ID_NONE;

	for (int i = 0; i < length; i++) {
   
		if (insideButton(&buttonArray[i], x, y)) {
   
			buttonId = i;
			break;   //退出,已经检测到,后面的按钮不再检测
		}
	}

	return buttonId;
}

void draw()
{
   
	//绘制
	drawButton(buttonArray, BUTTON_SIZE);
	setcolor(BLACK);
	setfont(24, 0, "");
	settextjustify(LEFT_TEXT, TOP_TEXT);
	xyprintf(240, 360, "按下按钮ID:%d", pressButtonId);
}

2.4 完整状态交互

状态 描述 样式
不可用 无法交互 灰色按钮
不可见 按钮不可见 文字指示
焦点 点击按钮后获得焦点。 外围圆圈标记
不可选 按钮选中状态无法通过点击进行切换
选中 按钮被点击后切换 左边选框
悬停 鼠标移动到按钮上方时设置,离开取消 颜色加深
按下 鼠标按下设置,松开取消 颜色切换

在这里插入图片描述

#include <graphics.h>
#include <math.h>

struct ButtonStates
{
   
	bool enable;	/* 可用状态 */
	bool visible;	/* 可见状态 */
	bool pressed;	/* 按下状态 */
	bool checkable; /* 可选状态 */
	bool checked;	/* 选中状态 */
	bool hovered;	/* 悬停状态 */
	bool focused;	/* 焦点状态 */
};

// 圆形按钮
struct CircleButton
{
   
	unsigned int id;
	int x, y;		/* 圆心*/
	int radius;		/* 半径*/
	color_t normalColor;
	color_t pressedColor;
	const char* text;
	ButtonStates state;
};

void initButton(CircleButton* button, int x, int y, int radius);

void initAllButtons();

//初始化按钮状态
void initButtonState(CircleButton* button);

// 判断点(x, y)是否在按钮点击区域内部
bool insideButton(const CircleButton* button, int x, int y);

CircleButton* findButton(unsigned int id);

// 绘制按钮
void drawButton(const CircleButton* buttonArray);

// 绘制所有按钮
void drawAllButtons();

// 查找 (x, y) 所在的按钮,返回按钮ID, 没有返回 -1
int searchButton(int x, int y);

// 绘制
void draw();

// 颜色插值, t 范围为 (0.0 ~ 1.0),分别对应colorA和colorB
color_t interpColor(color_t colorA, color_t colorB, float t);

#define BUTTON_SIZE 8
#define BUTTON_ID_ZERO ((unsigned int)0)
#define BUTTON_MIN_ID 1
#define BUTTON_MAX_ID BUTTON_SIZE

//定义按钮,确定区域
CircleButton buttonArray[BUTTON_SIZE];
int buttonNum = BUTTON_SIZE;

// 按下按钮ID
int pressButtonId   = BUTTON_ID_ZERO;
int hoveredButtonId = BUTTON_ID_ZERO;
int focusedButtonId = BUTTON_ID_ZERO;

int windowWidth = 640, windowHeight = 480;

int main()
{
   
	
	initgraph(windowWidth, windowHeight, INIT_RENDERMANUAL);
	setbkcolor(WHITE);
	setbkmode(TRANSPARENT);
	ege_enable_aa(true);

	initAllButtons();

	int xMouse = 0, yMouse = 0;
	int xSearched = -1, ySearched = -1;
	unsigned int idSearched = BUTTON_ID_ZERO;
	bool redraw = true;

	for (; is_run(); delay_fps(60)) {
   

		bool mouseMoved = false;

		while (mousemsg()) {
   
			mouse_msg msg = getmouse();

			// 判断鼠标左键按下(左键按下确定位置,同时判断是否为按钮区域
			// 抬起则解除按下状态
			if (msg.is_left()) {
   
				if (msg.is_down()) {
   
					
					int btnId = BUTTON_ID_ZERO;

					// 检查位置对应的按钮ID
					btnId = searchButton(msg.x, msg.y);
					 
					if ((btnId != BUTTON_ID_ZERO) && (findButton(btnId)->state.enable)) {
   
						// 将被按下的按钮设置为按下状态
						if (btnId != BUTTON_ID_ZERO) {
   
							pressButtonId = btnId;
							findButton(pressButtonId)->state.pressed = true;
							redraw = true;
						}
					}
				}
				else {
   
					//左键抬起,如果有按钮被按下
					if (pressButtonId != BUTTON_ID_ZERO) {
   
						unsigned btnId = pressButtonId;
						CircleButton* button = findButton(btnId);
						
						// 取消之前按钮的焦点状态
						if (focusedButtonId != BUTTON_ID_ZERO)
						{
   
							findButton(focusedButtonId)->state.focused = false;
						}

						//设置当前按钮为焦点状态
						button->state.focused = true;
						focusedButtonId = btnId;

						// 解除按下状态
						button->state.pressed = false;
						pressButtonId = BUTTON_ID_ZERO;
						
						// 切换选中
						if (button->state.checkable)
							button->state.checked = !(button->state.checked);
						
						redraw = true;
					}
				}
			}
			else if (msg.is_move()) {
   
				mouseMoved = true;
				xMouse = msg.x;
				yMouse = msg.y;
			}
		}

		//当鼠标移动
		if (mouseMoved) {
   
			//查找悬停的按钮
			int btnId = searchButton(xMouse, yMouse);

			// 悬停按钮改变
			if (btnId != hoveredButtonId) {
   
				// 标记原先的按钮为非悬停状态
				if (hoveredButtonId != BUTTON_ID_ZERO) {
   
					findButton(hoveredButtonId)->state.hovered = false;
				}

				// 标记当前悬停的按钮为悬停状态
				if (btnId != BUTTON_ID_ZERO) {
   
					findButton(btnId)->state.hovered = true;
				}

				hoveredButtonId = btnId;
				redraw = true;
			}
		}

		// 判断是否需要重绘,减少不必要的绘制操作
		if (redraw) {
   
			cleardevice();
			draw();
			redraw = false;
		}
	}

	return 0;
}


bool insideButton(const CircleButton* button, int x, int y)
{
   
	int dx = x - button->x, dy = y - button->y;
	return (dx * dx + dy * dy) <= (button->radius * button->radius);
}

unsigned int generateId()
{
   
	static unsigned int id = 0;
	return ++id;
}

CircleButton* findButton(unsigned int id)
{
   
	return (id == BUTTON_ID_ZERO) ? NULL : &buttonArray[id - 1];
}

unsigned int getButtonId(const CircleButton* button)
{
   
	return button->id;
}

// 绘制按钮
void drawButton(const CircleButton* button)
{
   
	if (button != NULL) {
   
		if (button->state.visible) {
   
			setfillcolor(EGEARGB(0xFF, 0x1E, 0x90, 0xFF));
			setcolor(WHITE);
			settextjustify(CENTER_TEXT, CENTER_TEXT);
			setfont(24, 0, "");

			//根据状态进行不同的绘制
			color_t color;

			if (!(button->state.enable)) {
   
				color = DARKGRAY;
			}
			else
			{
   
				if (button->state.pressed) {
   
					color = button->pressedColor;
				}
				else {
   
					color = button->normalColor;
				}

				if (button->state.hovered) {
   
					color = interpColor(color, BLACK, 0.125f);
				}
			}

			setfillcolor(color);

			// 绘制按钮
			ege_fillellipse(button->x - button->radius, button->y - button->radius,
				2 * button->radius, 2 * button->radius
			);

			// 选中则绘制外环边框
			if (button->state.focused)
			{
   
				setcolor(interpColor(color, BLACK, 0.25f));
				setlinewidth(4);

				int borderRadius = button->radius + 4;

				ege_ellipse(button->x - borderRadius, button->y - borderRadius,
					2 * borderRadius, 2 * borderRadius
				);
			}


			int radiusCheckBox = 14;
			int xCheckBox = button->x - button->radius - 2 * radiusCheckBox;
			int yCheckBox = button->y;

			if (button->state.checked) {
   
				setfillcolor(button->pressedColor);
				ege_fillellipse(xCheckBox - radiusCheckBox, yCheckBox - radiusCheckBox,
					2 * radiusCheckBox, 2 * radiusCheckBox
				);
			}
			else {
   
				setcolor(button->pressedColor);
				setlinewidth(2);
				ege_ellipse(xCheckBox - radiusCheckBox, yCheckBox - radiusCheckBox,
					2 * radiusCheckBox, 2 * radiusCheckBox
				);
			}

			setcolor(WHITE);
			xyprintf(button->x, button->y, "%s", button->text);
		}
		else {
   
			setcolor(BLACK);
			settextjustify(CENTER_TEXT, CENTER_TEXT);
			setfont(24, 0, "");
			xyprintf(button->x, button->y, "不可见");
		}
	}
}


// 绘制所有按钮
void drawAllButtons()
{
   
	for (int i = 0; i < buttonNum; i++) {
   
		unsigned int btnId = BUTTON_MIN_ID + i;
		drawButton(findButton(btnId));
	}
}

int searchButton(int x, int y)
{
   
	int buttonId = BUTTON_ID_ZERO;

	for (int i = 0; i < buttonNum; i++) {
   
		unsigned int btnId = BUTTON_MIN_ID + i;
		CircleButton* button = findButton(btnId);

		if ((button != NULL) && (insideButton(button, x, y))) {
   
			buttonId = btnId;
			break;   //退出,已经检测到,后面的按钮不再检测
		}
	}

	return buttonId;
}

void draw()
{
   
	//绘制
	drawAllButtons();
	setcolor(BLACK);
	setfont(24, 0, "");
	settextjustify(LEFT_TEXT, TOP_TEXT);
	xyprintf(240, 360, "按下按钮ID:%d", pressButtonId);
}

color_t interpColor(color_t colorA, color_t colorB, float t)
{
   
	if (t > 1)
		t = 1;
	else if (t < 0)
		t = 0;

	int r = roundf((1 - t) * EGEGET_R(colorA) + t * EGEGET_R(colorB));
	int g = roundf((1 - t) * EGEGET_G(colorA) + t * EGEGET_G(colorB));
	int b = roundf((1 - t) * EGEGET_B(colorA) + t * EGEGET_B(colorB));

	return EGERGB(r, g, b);
}


void initButtonState(CircleButton* button)
{
   
	button->state.enable = true;
	button->state.visible = true;
	button->state.pressed = false;
	button->state.checkable = true;
	button->state.checked = false;
	button->state.hovered = false;
	button->state.focused = false;
}

void initButton(CircleButton* button, int x, int y, int radius)
{
   
	if (button != NULL) {
   
		button->id = generateId();
		button->x = x;
		button->y = y;
		button->radius = radius;
		button->normalColor  = EGEARGB(0xFF, 0x40, 0xE0, 0xD0);
		button->pressedColor = EGEARGB(0xFF, 0x1E, 0x90, 0xFF);
		button->text = "Button";

		initButtonState(button);
	}
}

void initAllButtons()
{
   
	int colNum = 2;

	for (int i = 0; i < buttonNum; i++) {
   
		int id = BUTTON_MIN_ID + i;
		int x = (int)(((i % colNum) + 0.5f) * (windowWidth / colNum));
		int y = (int)(((i / colNum) + 0.5f) * (windowHeight / ((buttonNum + colNum - 1) / colNum)));

		initButton(findButton(id), x, y, 50);
	}

	CircleButton* btn;
	btn = findButton(BUTTON_MIN_ID);
	btn->state.enable = false;
	btn->text = "不可用";

	btn = findButton(BUTTON_MIN_ID + 1);
	btn->state.visible = false;

	btn = findButton(BUTTON_MIN_ID + 2);
	btn->state.checkable = false;
	btn->state.checked = false;
	btn->state.focused = true;
	btn->text = "不可选";

	btn = findButton(BUTTON_MIN_ID + 3);
	btn->state.checkable = false;
	btn->state.checked = true;
	btn->text = "不可选";

	btn = findButton(BUTTON_MIN_ID + 4);
	btn->state.pressed = true;

	btn = findButton(BUTTON_MIN_ID + 5);
	btn->state.checked = true;

	btn = findButton(BUTTON_MIN_ID + 6);
	btn->state.pressed = true;
	btn->state.checked = true;

	focusedButtonId = BUTTON_MIN_ID + 2;
}

EGE专栏:EGE专栏

上一篇:EGE绘图之(五) 按钮(上)

下一篇:

编程小号
上一篇 2025-02-08 23:11
下一篇 2025-02-10 22:40

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/106601.html