如何通过GtkComboBoxText
“静态”方面和“动态”方面自定义的完成?静态方面是因为某些条目是已知的,并在构造时使用添加到了组合框文本中gtk_combo_box_text_append_text
。动态方面是因为我还需要通过一些回调函数来完成,也就是说,一旦键入了几个字符,即在创建窗口小部件之后
动态地 完成GtkComboBoxText
。
我的应用程序使用的是Boehm的GC(当然不包括GTK对象),例如Guile或SCM或Bigloo。它可以看作是一种实验 性的持久性
动态类型的编程语言实现,带有集成的编辑器,该集成的编辑器在Debian / Linux /
x86-64上编码,并带有系统GTK3.21库,它使用C99编码(其中一些已生成),并且用GCC6编译。
(我不在乎非Linux系统,GTK3库早于GTK3.20,GCC编译器早于GCC6)
我输入的GtkComboBoxText
是 name 或 object-id (输入)。
该 名称 是C-标识符状,但以字母开头,并且不能以下划线结束。例如comment
,if
,the_GUI
,the_system
,payload_json
,或者x1
是有效的名称(但
还是
_a0bcd
无效的名字,因为他们开始或以下划线结尾)。我目前有很多名字,但我可以有数千个。因此,只有键入了一个或两个字母后才提供补全是合理的,并且名称的补全可以静态发生,因为它们不多(因此,我想foobar_
gtk_combo_box_append_text
为每个名称打电话都很合理)。
的 对象的ID 以下划线开始后跟数字和具有正好18个字母数字(排序的随机的)字符。例如,_5Hf0fFKvRVa71ZPM0
,_8261sbF1f9ohzu2Iu
,_0BV96V94PJIn9si1K
是可能的对象的id。实际上,它几乎是96个随机位(可能只有2 94个)。object-id扮演UUID的角色(在某种意义上,假定它对不同的对象在全球范围内是唯一的),但是具有C友好的语法。我目前有几十个对象ID,但我可以有几十万个(也许一百万个)。但是给定四个字符的前缀,例如_6S3
或_22z
,我假设只有一个合理的数字(可能最多十二个,并且肯定不超过一千个) object-id 该前缀存在于我的应用程序中。当然, 事先 (静态地)注册所有对象ID 是不合理的(完成必须在键入四个字符后发生,并且应该动态发生)。
因此,我想要一个既能在名称上起作用的补全(例如,键入一个字母,可能再跟另一个字母数字字符就足以提出最多一百种选择的补全),又能在对象id上起作用(键入四个字符_826
就足以最多可能会触发几十个选择,如果不幸,可能会触发一千个选择。
因此,键入三个键p
a
tab
将提供带有一些诸如payload_json
或payload_vectval
等等的名称的补全,而键入五个键_
5
H
f
tab
将提供具有很少的对象ID的补全。_5Hf0fFKvRVa71ZPM0
到目前为止,我编写了以下代码:
static GtkWidget *
mom_objectentry (void)
{
GtkWidget *obent = gtk_combo_box_text_new_with_entry ();
gtk_widget_set_size_request (obent, 30, 10);
mo_value_t namsetv = mo_named_objects_set ();
我有Boehm垃圾收集的值,并且mo_value_t
是指向其中任何一个的指针。值可以标记为整数,指向字符串,对象或元组或对象集的指针。因此,namesetv
现在包含一组命名对象(可能少于数千个命名对象)。
int nbnam = mo_set_size (namsetv);
MOM_ASSERTPRINTF (nbnam > 0, "bad nbnam");
mo_value_t *namarr = mom_gc_alloc (nbnam * sizeof (mo_value_t));
int cntnam = 0;
for (int ix = 0; ix < nbnam; ix++)
{
mo_objref_t curobr = mo_set_nth (namsetv, ix);
mo_value_t curnamv = mo_objref_namev (curobr);
if (mo_dyncast_string (curnamv))
namarr[cntnam++] = curnamv;
}
qsort (namarr, cntnam, sizeof (mo_value_t), mom_obname_cmp);
for (int ix = 0; ix < cntnam; ix++)
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (obent),
mo_string_cstr (namarr[ix]));
至此,我已经对所有(最多几千个)名称进行了排序,并使用来“静态”添加它们gtk_combo_box_text_append_text
。
GtkWidget *combtextent = gtk_bin_get_child (GTK_BIN (obent));
MOM_ASSERTPRINTF (GTK_IS_ENTRY (combtextent), "bad combtextent");
MOM_ASSERTPRINTF (gtk_entry_get_completion (GTK_ENTRY (combtextent)) ==
NULL, "got completion in combtextent");
我惊讶地发现这gtk_entry_get_completion (GTK_ENTRY (combtextent))
是空的。
但是我被困在这里。我在想:
有一些mom_set_complete_objectid(const char*prefix)
这赋予了prefix
像"_47n"
至少四个字符将返回收集垃圾mo_value_t
代表着一套与前缀的对象。对于我来说,这很容易编写代码,并且几乎可以完成。
将我自己设置为本地GtkEntryCompletion* mycompl =
…,这将按我的意愿完成。然后我会把它在文本输入combtextent
我的 GTK的组合框,文本 使用gtk_entry_set_completion(GTK_ENTRY(combtextent), mycompl);
它应该使用gtk_combo_box_text_append_text
为“静态”名称完成角色添加的条目吗?我应该如何使用从我返回的动态设置值来动态完成mom_set_complete_objectid
;给定一些对象指针obr
和一些对象指针,char bufid[20];
我可以轻松,快速地obr
用mo_cstring_from_hi_lo_ids(bufid, obr->mo_ob_hid, obr->mo_ob_loid)
.. 填充该对象的对象ID 。
我不知道如何编写以上代码。作为参考,我现在只返回combo-box-text:
// if the entered text starts with a letter, I want it to be
// completed with the appended text above if the entered text starts
// with an undersore, then a digit, then two alphanum (like _0BV or
// _6S3 for example), I want to call a completion function.
#warning objectentry: what should I code here?
return obent;
} /* end mom_objectentry */
我的方法正确吗?
mom_objectentry
上面的功能用于填充寿命较短的模式对话框。
我偏爱简单代码而不是效率。实际上,我的代码是临时的(我希望引导我的语言,并生成所有C代码!),实际上,我可能只有数百个名称,最多只有几十万个对象ID。因此性能并不是很重要,但是简化编码(从概念上讲是“丢弃”代码)更为重要。
我不想(如果可能)添加自己的GTK类。我更喜欢使用现有的GTK类和小部件,并通过GTK信号和回调对其进行自定义。
我的应用程序是一种实验
性的持久
编程语言,其实现方式具有接近Scheme或Python(或JavaScript,忽略了原型方面,…)的 语义, 但 语法
却相差很大(尚未于2016 年9月7
日实现)。显示并在GTK小部件中输入),使用Boehm垃圾收集器收集值(包括对象,集合,元组,字符串…)…值(包括对象)通常是持久性的(与GTK相关的数据除外:应用程序以几乎是空的窗口)。整个语言堆以类似JSON的语法保存在某些Sqlite“数据库”(在应用程序出口中生成)中,转储到_momstate.sql
在应用程序启动时重新加载。对象ID可用于在GTK小部件中向用户显示对象引用,以实现持久性,并生成与对象相关的C代码(例如,ID的对象_76f7e2VcL8IJC1hq6
可能与mo_76f7e2VcL8IJC1hq6
某些生成的C代码中的标识符相关;这部分是为什么我有我的对象ID格式,而不是使用UUID。
PS。我的C代码是GPLv3免费软件,可在github上找到。它是MELT监视器,分支expjs,commit e2b3b99ef66394
…
注意:这里提到的对象暗含我的语言对象,而不是GTK对象。全部都有一个唯一的对象ID,其中一些(但不是大多数)被命名。
这是我的建议:
使用GtkListStore包含与当前前缀字符串匹配的GTK管理的字符串列表(实际上是标识符字符串的副本)。
(如记录所示gtk_list_store_set()
,一个G_TYPE_STRING
项目已被复制。我认为额外副本的开销在这里是可以接受的;无论如何,我认为它不会对现实世界的性能产生太大影响,因此,GTK
+将为我们管理引用计数。)
上面的代码是在GTK
+回调函数中实现的,该函数获得一个额外的指针作为有效负载(在创建或激活GUI时设置;建议您使用某种结构来保留生成匹配项所需的引用)。回调连接到组合框popup
信号,以便在扩展列表时调用它。
请注意,正如B8vrede在评论中指出的那样,GtkComboBoxText
不应通过其模型修改a
;这就是为什么一个人应该/必须使用一个GtkComboBox
代替物的原因。
实际例子
为简单起见,我们假设查找或生成匹配的所有已知标识符所需的所有数据都保存在一个结构中,例如
struct generator {
/* Whatever data you need to generate prefix matches */
};
然后组合框填充器助手功能类似于
static void combo_box_populator(GtkComboBox *combobox, gpointer genptr)
{
struct generator *const generator = genptr;
GtkListStore *combo_list = GTK_LIST_STORE(gtk_combo_box_get_model(combobox));
GtkWidget *entry = gtk_bin_get_child(GTK_BIN(combobox));
const char *prefix = gtk_entry_get_text(GTK_ENTRY(entry));
const size_t prefix_len = (prefix) ? strlen(prefix) : 0;
GtkTreeIter iterator;
/* Clear the current store */
gtk_list_store_clear(combo_list);
/* Initialize the list iterator */
gtk_tree_model_get_iter_first(GTK_TREE_MODEL(combo_list), &iterator);
/* Find all you want to have in the combo box;
for each const char *match, do:
*/
gtk_list_store_append(combo_list, &iterator);
gtk_list_store_set(combo_list, &iterator, 0, match, -1);
/* Note that the string pointed to by match is copied;
match is not referred to after the _set() returns.
*/
}
构建或激活UI时,您需要确保GtkComboBox
拥有一个条目(以便用户可以向其中写入文本)和一个GtkListStore
模型:
struct generator *generator;
GtkWidget *combobox;
GtkListStore *combo_list;
combo_list = gtk_list_store_new(1, G_TYPE_STRING);
combobox = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(combo_list));
gtk_combo_box_set_id_column(GTK_COMBO_BOX(combobox), 0);
gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(combobox), 0);
gtk_combo_box_set_button_sensitivity(GTK_COMBO_BOX(combobox), GTK_SENSITIVITY_ON);
g_signal_connect(combobox, "popup", G_CALLBACK(combo_box_populator), generator);
在我的系统上,默认的弹出加速器为Alt
+ Down
,但是我想您已经将其更改为Tab
。
我这里有一个粗糙的工作示例(.tar.xz
tarball,CC0):它从标准输入中读取行,并在组合框列表中(当弹出时)以相反的顺序列出与用户前缀匹配的行。如果该项为空,则组合框将包含所有输入行。我没有更改默认的加速器,因此Tab
,请尝试Alt+Down
。
我也有相同的示例,但这里使用了GtkComboBoxText
替代示例(也是CC0)。这不使用模型,而是使用和函数直接操作列表内容。(两个示例中只有几行不同。)不幸的是,文档并未明确说明此接口是引用还是复制字符串。尽管复制是唯一有意义的选项,并且可以从当前的Gtk
+来源进行验证,但是缺少明确的文档使我犹豫不决。GtkListStore
gtk_combo_box_text_remove_all()
gtk_combo_box_text_append_text()
比较上面链接到的两个示例(/usr/share/dict/words
如果使用进行编译和运行,都可以抓取500个随机单词make
),但看不到任何速度差异。两者都使用相同的简单方法从链接列表中选择前缀匹配,这意味着这两种方法(GtkComboBox
+模型或GtkComboBoxText
)应大致相同。
在我自己的计算机上,两者都令人讨厌地变慢,弹出窗口中的匹配项超过1000个左右。只需进行一百场或更少的比赛,就可以立即感受到。对我来说,这表明从链接列表中选择前缀匹配项的缓慢/幼稚方式不是罪魁祸首(因为在两种情况下都会遍历整个列表),但是GTK+组合框并不是专门为大型列表而设计的。(速度下降肯定比线性下降严重得多。)
我想在表单中使用jQuery.AutoComplete.js插件进行输入。我想在客户端进行搜索,不能使用Ajax。但我不想在数组中使用一些简单的基于“包含”的搜索算法。我要做的是用javascript编写一个自定义搜索函数,对结果进行搜索和排序。这可能吗?怎么可能? 谢谢你抽出时间。
我试图创建自己的自定义angular material组件,该组件能够使用控件。 除此之外,我希望该控件使用指令。 我的目的只是创建一个更好看的组件,该组件包含一个集成的clear按钮和自定义css箭头,如下图所示。我使用标准组件成功地获得了它,并添加了我想要的内容,但现在我想将它导出到泛型组件中。 null 即使正确选择了值,我的窗体也无效。 选择某个选项后,占位符自身设置不正确。 自动完成筛选
问题内容: 如何在Python脚本中与Shell选项卡完成协作? 在.py文件上设置了可执行标志后,预期结果应类似于: 问题答案: 看看argcomplete由安德烈Kislyuk。 通过以下方式安装: 导入模块并在调用之前在源代码中添加一行: 并确保bash知道此脚本,请使用 您应该将该行放在您的代码中,或遵循argcomplete的文档并激活“全局”完成。 之后,您可以根据要求完成工作。 其工
下面是我的FragmentActivity和DialogFragment。我尝试创建一个自定义AlertDialog。我已经部分实现了如下图所示。如何消除自定义AlertDialog周围的白色区域? 下面是我的alertdialog布局xml fragment_dialog.xml
我使用Wordpress类别创建了一个按城市划分的公司目录。类别是城市。自定义域是包含城市的区域。用于自定义域-用于构建自定义分类顺序的高级自定义域-WP术语顺序 I recurive: Wielkopolskie Poznan Wielkopolskie Bojanowo Mazoweckie Warszawa Dolnoslaskie Wrocóaw Dolnoslaskie Jawor 帮助
首先,我是卡蒙达的新手。。我在camunda中创建了一个自定义任务列表。我可以申请/取消申请任务等,这是可行的。 现在我想完成一项任务,但是当我打电话的时候: 似乎camunda希望在此上下文中进入下一步,而不是部署BPMN模式以及部署执行下一步所需的一切的上下文。所以我得到了“classNotFound”异常,因为我的customTasklist中没有相同的类。战争就像卡蒙达处理器一样。战争 我