GTK绘图区域旋转文本框后四角检测失效问题排查
GTK文本框旋转后四角检测失效问题

在GTK绘图区域中旋转文本框后,四角检测功能失效,因为顶点的x、y坐标仍保留原值。我使用以下代码更新坐标,但从图片可见问题仍存在,光标在未悬停左上角圆形手柄时也会改变形状。
按钮释放事件代码
static gboolean button_release_event(GtkWidget *widget, GdkEventButton *event, TextBox *textbox) { if (event->button == GDK_BUTTON_PRIMARY) { textbox->button_pressed = FALSE; if (textbox->action == IS_ROTATING) { double dx = -textbox->width / 2; double dy = -textbox->height / 2; double cx = textbox->x - dx; double cy = textbox->y - dy; double a = atan2(dy,dx); double m = sqrt(dx * dx + dy * dy); double angle = a + (textbox->angle * G_PI / 180.0); //Update the x,y coords after the rotation textbox->x = cx + m * cos(angle); textbox->y = cy + m * sin(angle); g_print("After the rotation: x,y %2.0f %2.0f\n",textbox->x,textbox->y); } textbox->action = NONE; if (textbox->corner != GDK_FLEUR) gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); } return FALSE; }
鼠标区域检测代码
gint x,y; x = event->x * cos(-textbox->angle) - event->y * sin(-textbox->angle); y = event->y * sin(-textbox->angle) + event->y * cos(-textbox->angle); //Check if the mouse pointer is hovering the rotate circle if (textbox->draw_rect && x >= textbox->x + (textbox->width/2) && x <= (textbox->x + (textbox->width/2)) + 5 && y>= textbox->y+textbox->height && y + 9 <= textbox->y+textbox->height + 22) { textbox->action = IS_ROTATING; textbox->corner = GDK_EXCHANGE; gdk_window_set_cursor(gtk_widget_get_window(widget), gdk_cursor_new_for_display(gdk_display_get_default(), textbox->corner )); } //If mouse pointer is inside the visible text frame change the cursor shape accordingly else if (!textbox->button_pressed && textbox->draw_rect && x >= textbox->x && x <= textbox->x + textbox->width && y >= textbox->y && y <= textbox->y + textbox->height) { if (x >= textbox->x && x <= textbox->x + 5 && y >= textbox->y && y <= textbox->y + 5) { textbox->action = IS_RESIZING; textbox->corner = GDK_TOP_LEFT_CORNER; } else if (x >= textbox->x + textbox->width - 3 && x <= textbox->x + textbox->width && y >= textbox->y && y <= textbox->y + 5) { textbox->corner = GDK_TOP_RIGHT_CORNER; textbox->action = IS_RESIZING; } else if (x >= textbox->x && x <= textbox->x + 5 && y >= textbox->y + textbox->height - 3 && y <= textbox->y + textbox->height) { textbox->corner = GDK_BOTTOM_LEFT_CORNER; textbox->action = IS_RESIZING; } else if (x >= textbox->x + textbox->width - 3 && x <= textbox->x + textbox->width && y >= textbox->y + textbox->height - 5 && y <= textbox->y + textbox->height) { textbox->corner = GDK_BOTTOM_RIGHT_CORNER; textbox->action = IS_RESIZING; } else { textbox->corner = GDK_FLEUR; textbox->action = IS_DRAGGING; } gdk_window_set_cursor(gtk_widget_get_window(widget), gdk_cursor_new_for_display(gdk_display_get_default(), textbox->corner )); }
请问我哪里出错了?
问题分析与修复方案
- 坐标转换公式笔误+弧度转换缺失
检测代码中计算转换后y坐标的公式错误,第二个项误用了event->y两次;同时cos/sin函数需要传入弧度值,直接用角度计算会导致坐标完全偏移。正确转换代码:
double angle_rad = -textbox->angle * G_PI / 180.0; // 角度转弧度 gint x = event->x * cos(angle_rad) - event->y * sin(angle_rad); gint y = event->x * sin(angle_rad) + event->y * cos(angle_rad);
- 旋转后坐标更新逻辑错误
当前代码的旋转原点计算错误,应该以文本框中心作为旋转基准,而非左上角偏移。正确的更新逻辑:
if (textbox->action == IS_ROTATING) { // 计算文本框中心坐标 double cx = textbox->x + textbox->width / 2.0; double cy = textbox->y + textbox->height / 2.0; // 左上角点相对于中心的偏移 double dx = textbox->x - cx; double dy = textbox->y - cy; // 将角度转为弧度 double angle_rad = textbox->angle * G_PI / 180.0; // 旋转偏移量 double new_dx = dx * cos(angle_rad) - dy * sin(angle_rad); double new_dy = dx * sin(angle_rad) + dy * cos(angle_rad); // 更新左上角坐标 textbox->x = cx + new_dx; textbox->y = cy + new_dy; g_print("After the rotation: x,y %2.0f %2.0f\n",textbox->x,textbox->y); }
旋转手柄检测未适配旋转状态
当前检测旋转手柄的逻辑基于原始未旋转位置,旋转后手柄实际位置已改变,需基于文本框中心重新计算手柄的绝对位置,或者对手柄相对坐标做旋转转换。光标重置逻辑不完整
当鼠标离开所有检测区域时,没有重置光标状态,导致光标可能停留在之前的形状。需在所有条件分支外添加:
else { textbox->action = NONE; textbox->corner = GDK_FLEUR; gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); }
内容的提问来源于stack exchange,提问作者GiuTor
相关产品推荐
相关产品推荐

