Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
User interface GTK在用户输入时更改文本_User Interface_Gtk - Fatal编程技术网

User interface GTK在用户输入时更改文本

User interface GTK在用户输入时更改文本,user-interface,gtk,User Interface,Gtk,在gui中,我想修改用户在GTK中插入的文本。例如,如果用户输入“joHn doe”,我的gui应该会看到这不是一个格式良好的名称,并将其更改为“joHn doe” 我将a处理程序连接到“已更改”信号,如eg中所述。出现的问题是,如果我更改信号处理程序中的条目,“更改的”信号会一次又一次地发出,直到王国到来 目前,我通过进行字符串比较来防止这种情况的发生,并且仅当文本“namified”版本与条目中的文本不相等时,才更改GtkEntryBuffer中的文本。不过,我觉得作为程序员,我应该能够更改

在gui中,我想修改用户在GTK中插入的文本。例如,如果用户输入“joHn doe”,我的gui应该会看到这不是一个格式良好的名称,并将其更改为“joHn doe”

我将a处理程序连接到“已更改”信号,如eg中所述。出现的问题是,如果我更改信号处理程序中的条目,“更改的”信号会一次又一次地发出,直到王国到来

目前,我通过进行字符串比较来防止这种情况的发生,并且仅当文本“namified”版本与条目中的文本不相等时,才更改GtkEntryBuffer中的文本。不过,我觉得作为程序员,我应该能够更改条目中的文本,而不必反复调用更改后的处理程序

已更改的信号处理程序是:

void nameify_entry ( GtkEditable* editable, gpointer data )
{
    gchar* nameified;
    const gchar *entry_text;

    entry_text = gtk_entry_get_text( GTK_ENTRY(editable) );
    nameified = nameify(entry_text);

    /*is it possible to change the buffer without this using this string
      comparison, without the "change" signal being emitted over and over again?*/
    if ( g_strcmp0(entry_text, nameified) != 0 ){
        GtkEntryBuffer* buf = gtk_entry_get_buffer(GTK_ENTRY(editable) );
        gtk_entry_buffer_set_text( buf, nameified, -1 );
    }
    g_free(nameified);
}
我的命名功能是:

/*removes characters that should not belong to a name*/
gchar*
nameify ( const char* cstr )
{
    const char* c;
    gchar* ret_val;
    GString* s = g_string_new("");

    gboolean uppercase_next = TRUE;
    g_debug( "string = %s", cstr);

    for ( c = cstr; *c != '0'; c = g_utf8_next_char(c) ) {
        gunichar cp = g_utf8_get_char(c); 
        if ( cp == 0 ) break;
        if ( g_unichar_isalpha( cp ) ){
            if ( uppercase_next ){
                g_string_append_unichar( s, g_unichar_toupper(cp) );
                uppercase_next = FALSE;
            }
            else{
                g_string_append_unichar(s,g_unichar_tolower(cp));
            }
        }
        if ( cp == '-' ){
            g_string_append_unichar( s, cp);
            uppercase_next = TRUE;
        }
        if ( cp == ' '){
            g_string_append_unichar( s, cp);
            uppercase_next = TRUE;
        }
    }

    ret_val = s->str;
    g_string_free(s, FALSE);
    return ret_val;
}

非常欢迎任何帮助。

我认为最快的解决方案是暂时阻止您的回调被调用

g\u signal\u connect
函数组每个函数都返回一个类型为
gulong
的“handler\u id”。您必须存储此id,使用“userdata”参数将其传递给回调函数(或者只使用全局静态变量),然后将文本操作代码放在/对之间。

对于您的需求信号来说似乎更合适<代码>插入文本可用于在输入文本之前对文本进行可能的更改。您可以使用回调函数模板
insert\u text\u handler
的部分说明。您可以使用
nameify
对函数进行更改(因为您不会得到整个文本,而是部分文本或字符;最简单的修改可能是声明
uppercase\u next
static)来修改文本。

希望这有帮助

连接到“已更改”信号并不十分方便,但更适合连接到“插入文本”信号。最好让默认的“插入文本”处理程序更新条目。而不是在“插入文本”信号上使用来更新条目中的文本,这样可以防止更改后的信号无限运行。这也应该对“删除文本”信号执行,因为如果用户删除大写字母,则应删除大写字母,并将第二个大写字母大写

因此,在创建运行时:

g_signal_connect_after( entry, "insert-text", G_CALLBACK(name_insert_after), NULL );
g_signal_connect_after( entry, "delete-text", G_CALLBACK(name_delete_after), NULL );
然后,您可以使用以下信号处理程序:

void
name_insert_after (GtkEditable* edit,
                   gchar* new_text,
                   gint new_length,
                   gpointer position,
                   gpointer data)
{
    /*prevent compiler warnings about unused variables*/
    (void) new_text; (void) new_length; (void) position; (void) data;
    const gchar* content = gtk_entry_get_text( GTK_ENTRY(edit) );
    gchar* modified = nameify( content);
    gtk_entry_set_text(GTK_ENTRY(edit),modified);
    g_free(modified);
}

void
name_delete_after (GtkEditable* edit,
                   gint start_pos,
                   gint end_pos,
                   gpointer data)
{
    /*no op cast to prevent compiler warnings*/
    (void) start_pos; (void) end_pos; (void) data;
    /*get text and modify the entry*/
    int cursor_pos = gtk_editable_get_position(edit);
    const gchar* content = gtk_entry_get_text( GTK_ENTRY(edit) );
    gchar* modified = nameify( content);
    gtk_entry_set_text(GTK_ENTRY(edit),modified);
    gtk_editable_set_position(edit, cursor_pos);
    g_free(modified);
}
而这些可以与原始帖子中的nameify函数一起使用。
您甚至可以提供一个指向数据的函数指针,而不是“NULL”,以便将此处理程序与能够修改条目中字符串的不同函数一起使用。

连接到
插入文本和
删除文本是正确的想法,但您希望使用
g\u信号\u连接来连接。如果在
之后使用
g\u signal\u connect\u,则在更正之前已经显示了不正确的文本,这可能会导致显示屏闪烁。此外,在调用
gtk\u entry\u set\u text
时,您需要阻止信号处理程序,因为这会发出
删除文本
,然后是
插入文本
。如果不阻止信号,则将递归调用信号处理程序。记住,GObject信号只是函数调用。发出信号与直接从代码调用处理程序相同

我建议为
insert text
设置一个处理程序,查看是否需要更改新输入。如果确实如此,则创建一个新字符串,并按照GtkEditable文档执行此操作

g_signal_handlers_block_by_func (editable, insert_text_handler, data);
gtk_editable_insert_text (editable, new-text, g_strlen(new_text) , position);
g_signal_handlers_unblock_by_func (editable, insert_text_handler, data);

g_signal_stop_emission_by_name (editable, "insert_text");
如果不需要更改输入,只需返回

对于
deletetetext
处理程序,我想看看是否需要更改文本(记住还没有删除任何内容),如果需要,则使用

g_signal_handlers_block_by_func (editable, insert_text_handler, data);
g_signal_handlers_block_by_func (editable, delete_text_handler, data);
gtk_entry_set_text (GKT_ENTRY (editable), new-text);
g_signal_handlers_unblock_by_func (editable, delete_text_handler, data);
g_signal_handlers_unblock_by_func (editable, insert_text_handler, data);

g_signal_stop_emission_by_name (editable, "delete_text");

如果不需要更改文本,请再次返回。

比阻止和取消阻止信号更简单,只需使用布尔值:

myHandler(...){
static int recursing=0;
if(recursing){
    recursing=0;
    return;
}
... logic to decide if a change is needed
recursing=1;
gtk_entru_set_text(...);
... will recurse to your hander, which will clear the recursing variable and resume here
}

嗨,安库里奥,谢谢你的努力,但如果我没有弄错的话,这并没有真正的帮助,因为如果我阻止并解除阻止处理程序中的处理程序,处理程序在完成时就会被解除阻止。在我的处理程序完成gtk_entry_(buffer_)set_后,文本仍然会发出信号,然后我再次进行循环。我真的在寻找一种方法来更新一个没有信号的条目。事实上它是静态循环的,这样光标甚至不再闪烁。@ HeePePePrim-HM你是对的,我甚至认为这是一个bug。太糟糕了=/I尝试了一对断开/连接,但由于信号发射延迟,也无法工作。+1获取有关使用“插入文本”信号的注释。但是我们也应该考虑当有人删除一个字符时会发生什么,并且“插入文本”信号不会只查看条目中已经存在的字符,而是那些新插入的字符,因此我将发布一个稍微替代的解决方案,防止使用静态或全局变量。+1正确!我错过了删除部分:“请考虑接受你的答案,如果它解决了你的问题,这将有助于将来可能面对这个问题的人:”