2

Unity パネルの各 CPU コアのアイコンを表示することになっている単純なインジケーターをプログラミングしています。これは、温度範囲に応じて色が変わります。

複数のアイコンを持つ 1 つの AppIndicator を持つ方法や、gtk_container を使用してそれらを保持し、それを AppIndicator に追加する方法はないと思うので、同じプログラムに複数の AppIndicator を持つ必要があります。私は実際に、メニューに 1 つの AppIndicator (「Quit」オプションを使用) と、各 CPU コアに 1 つの AppIndicator を使用しようとしています。

プログラムには、AppIndicator (メインのもの) が 1 つだけの Gtk 警告はありませんでしたが、CPU コアごとに他の 2 つの AppIndicator (両方とも異なる一意の ID) を作成するためのコードを追加した後、Gtk はいくつかの警告と重要なメッセージをスローし始めました。インジケーターは本来あるべきようにパネルに表示されますが、カーテンの下にいくつかの実際の問題が隠されている可能性があるため、これらのメッセージを単純に無視したくありません。

コードをチェックすると、これらの警告と重要なメッセージをトリガーする可能性があると思われる唯一のことは、app_indicator_new()複数回呼び出されていることです。実際には、これらの追加のインジケーターのすべてのメニューと menu_item の作成ルーチンを削除し、app_indicator_new()呼び出しだけを残しましたが、まだそれらのメッセージが表示されます (最初の呼び出しの後の余分な呼び出しごとに 1 つ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));
}

何が原因なのか手がかりはありますか?プログラムごとに複数の AppIndicators はサポートされていませんか?

編集:

@Jean-François Fabreの回答後のコードを修正しました。

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:

単一の Core インジケーターを明示的に作成するためのコード。引き続き警告と重大なメッセージが表示されます:

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

2 に答える 2

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, ...

ループ内で auto 変数として宣言していますが、 ,を期待するIndicatorNameに渡します。つまり、文字列のアドレスを格納するだけです。gtk_menu_item_new_with_labelconst char *

メモリがさらなる反復のために再利用されるだけでなく、すべてのメニューがループ内で同じインジケータ名を持つだけでなく、ループを終了すると、メモリは他の変数に割り当てられ、名前は破棄されます => 未定義の動作

次のように文字列のコピーを作成する必要があります。

TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(strdup(IndicatorName));

(もちろん、コピーされた文字列を保存して、必要に応じて割り当てを解除できるようにすることをお勧めします)

于 2016-09-14T20:20:44.457 に答える
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();

問題を解決するには十分でした。私は関数自体に集中していたので、関数が呼び出されている場所を見るのをやめませんでした。

于 2016-09-14T22:34:16.690 に答える