You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 ));
    }

请问我哪里出错了?


问题分析与修复方案

  1. 坐标转换公式笔误+弧度转换缺失
    检测代码中计算转换后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);
  1. 旋转后坐标更新逻辑错误
    当前代码的旋转原点计算错误,应该以文本框中心作为旋转基准,而非左上角偏移。正确的更新逻辑:
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);
}
  1. 旋转手柄检测未适配旋转状态
    当前检测旋转手柄的逻辑基于原始未旋转位置,旋转后手柄实际位置已改变,需基于文本框中心重新计算手柄的绝对位置,或者对手柄相对坐标做旋转转换。

  2. 光标重置逻辑不完整
    当鼠标离开所有检测区域时,没有重置光标状态,导致光标可能停留在之前的形状。需在所有条件分支外添加:

else
{
    textbox->action = NONE;
    textbox->corner = GDK_FLEUR;
    gdk_window_set_cursor(gtk_widget_get_window(widget), NULL);
}

内容的提问来源于stack exchange,提问作者GiuTor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:44:53