我正在编写一个简单的指示器,它应该在Unity面板中显示每个CPU Core的图标,这将根据温度范围改变颜色。
这需要我在同一个程序上有多个AppIndicator,因为我认为没有办法让一个AppIndicator有多个图标或使用gtk_container来保存它们并将它附加到AppIndicator。我实际上尝试使用1个AppIndicator作为菜单(使用“Quit”选项)和1个AppIndicator用于每个CPU核心。
该程序只有一个AppIndicator(主要的)没有Gtk警告,但在我添加了为每个CPU Core创建其他2个AppIndicator的代码(两者都有不同的唯一ID)后,Gtk开始抛出一些警告和关键消息。指标显示在面板中就像它们应该的那样,但我不想简单地忽略这些消息,因为它们可能隐藏了一些真正的问题。
检查代码,我认为唯一可以触发这些警告和关键消息的是app_indicator_new()
不止一次被调用,实际上我删除了所有菜单和menu_item的创建例程以获取这些额外的指标,只留下app_indicator_new()
来电,我仍然会收到这些消息(在第一个消息后每个额外的app_indicator_new()
呼叫一个消息):
(process:8040): Gtk-CRITICAL **: IA__gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(process:8040): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(process:8040): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
当我添加创建菜单并与额外的AppIndicator相关联的代码时,会出现一些额外的错误:
(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(process:8681): Gtk-CRITICAL **: IA__gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(process:8681): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(process:8681): Gtk-CRITICAL **: IA__gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(process:8681): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(TempI:8681): Gtk-WARNING **: Screen for GtkWindow not set; you must always set
a screen for a GtkWindow before using the window
(TempI:8681): Gdk-CRITICAL **: IA__gdk_screen_get_display: assertion 'GDK_IS_SCREEN (screen)' failed
(TempI:8681): Gdk-CRITICAL **: IA__gdk_keymap_get_for_display: assertion 'GDK_IS_DISPLAY (display)' failed
(TempI:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(TempI:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(TempI:8681): Gtk-WARNING **: Screen for GtkWindow not set; you must always set
a screen for a GtkWindow before using the window
(TempI:8681): Gdk-CRITICAL **: IA__gdk_screen_get_display: assertion 'GDK_IS_SCREEN (screen)' failed
(TempI:8681): Gdk-CRITICAL **: IA__gdk_keymap_get_for_display: assertion 'GDK_IS_DISPLAY (display)' failed
(TempI:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance
(TempI:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
如果有必要,我可以发布程序的代码,但是没有这样做,因为它会使问题更大。这就是我正在创建额外的AppIndicators的块:
for(int i=0; i<TempI_Main.Cores_Counter; i++){
TempI_Main.Core[i].Gtk_Menu_Root=gtk_menu_new();
//The core name ("Core " + number)
char IndicatorName[TEMPI_MAX_CHARS];
snprintf(IndicatorName, TEMPI_MAX_CHARS,"TempI_Core %u",i);
TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(IndicatorName);
gtk_menu_append(GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root),TempI_Main.Core[i].Gtk_Menu_Root_Description);
gtk_widget_set_sensitive(GTK_WIDGET(TempI_Main.Core[i].Gtk_Menu_Root_Description),FALSE);
gtk_widget_show(TempI_Main.Core[i].Gtk_Menu_Root_Description);
TempI_Main.Core[i].Gtk_Indicator=app_indicator_new(IndicatorName,"indicator-messages",APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
app_indicator_set_status(TempI_Main.Core[i].Gtk_Indicator, APP_INDICATOR_STATUS_ACTIVE);
//Need to set icon
//Need to set attention icon
app_indicator_set_menu(TempI_Main.Core[i].Gtk_Indicator,GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root));
}
任何线索可能是什么原因? 每个程序不支持多个AppIndicator ?
修改
在@ Jean-FrançoisFabre回答之后更正了代码。
for(int i=0; i<TempI_Main.Cores_Counter; i++){
TempI_Main.Core[i].Gtk_Menu_Root=gtk_menu_new();
//The core name ("Core " + number)
char IndicatorName[TEMPI_MAX_CHARS];
//MAX_CHARS - 6 ("Core "+'\0') is the limit for appending
snprintf(IndicatorName, TEMPI_MAX_CHARS,"TempI_Core %u",i);
TempI_Main.Core[i].Gtk_Indicator_Name=strdup(IndicatorName);
TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(TempI_Main.Core[i].Gtk_Indicator_Name);
gtk_menu_append(GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root),TempI_Main.Core[i].Gtk_Menu_Root_Description);
gtk_widget_set_sensitive(GTK_WIDGET(TempI_Main.Core[i].Gtk_Menu_Root_Description),FALSE);
gtk_widget_show(TempI_Main.Core[i].Gtk_Menu_Root_Description);
TempI_Main.Core[i].Gtk_Indicator=app_indicator_new(TempI_Main.Core[i].Gtk_Indicator_Name,"indicator-messages",APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
app_indicator_set_status(TempI_Main.Core[i].Gtk_Indicator, APP_INDICATOR_STATUS_ACTIVE);
//Need to set icon
//Need to set attention icon
app_indicator_set_menu(TempI_Main.Core[i].Gtk_Indicator,GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root));
}
EDIT2:
明确创建单个核心指标的代码。仍在抛出警告和关键信息:
TempI_Main.Core[0].Gtk_Menu_Root=gtk_menu_new();
TempI_Main.Core[0].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label("Core1");
gtk_menu_append(GTK_MENU(TempI_Main.Core[0].Gtk_Menu_Root),TempI_Main.Core[0].Gtk_Menu_Root_Description);
gtk_widget_set_sensitive(GTK_WIDGET(TempI_Main.Core[0].Gtk_Menu_Root_Description),FALSE);
gtk_widget_show(TempI_Main.Core[0].Gtk_Menu_Root_Description);
TempI_Main.Core[0].Gtk_Indicator=app_indicator_new("Core1","indicator-messages",APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
app_indicator_set_status(TempI_Main.Core[0].Gtk_Indicator, APP_INDICATOR_STATUS_ACTIVE);
//Need to set icon
//Need to set attention icon
app_indicator_set_menu(TempI_Main.Core[0].Gtk_Indicator,GTK_MENU(TempI_Main.Core[0].Gtk_Menu_Root));
答案 0 :(得分:1)
循环中的那个很糟糕:
char IndicatorName[TEMPI_MAX_CHARS];
snprintf(IndicatorName, TEMPI_MAX_CHARS,"TempI_Core %u",i);
TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(IndicatorName);
...
TempI_Main.Core[i].Gtk_Indicator=app_indicator_new(IndicatorName, ...
您在循环中将IndicatorName
声明为自动变量,但将其传递给期望gtk_menu_item_new_with_label
的{{1}},意味着:它只会存储字符串的地址。
不仅内存将被重复用于进一步的迭代,并且所有菜单在循环内都具有相同的指示符名称,但是退出循环,内存将被分配给其他变量并且名称将被删除=&gt;未定义的行为
你应该像这样制作字符串的副本:
const char *
(当然更好的方法是存储复制的字符串,以便在需要时能够解除分配)
答案 1 :(得分:0)
我找到了问题的根源,并且很难说,但我只是错放了创建AppIndicator的功能。 之前正在调用 gtk_init()
,以便所有这些错误来自哪里。首先我有:
TempI_Set_Core_Indicator();
//Starts gtk
gtk_init(&argc,&argv);
TempI_Set_Main_Indicator();
并简单地将其替换为:
//Starts gtk
gtk_init(&argc,&argv);
TempI_Set_Main_Indicator();
TempI_Set_Core_Indicator();
足以解决问题。我非常关注功能本身,我没有停下来看它被调用的地方。