為了在回呼中訪問其他小部件,我將它們打包在一個定義如下的結構中:
typedef struct SettingsModel
{
bool SyncEn;
int DeviceId;
int MeasurementId;
GtkWidget *measurement_type_box;
GtkWidget *sync_switch;
GtkWidget *device_type_box;
} SettingsModel;
目的是在單擊保存按鈕時更新設定。相關代碼片段:
static void click_save(GtkButton *self, gpointer user_data)
{
SettingsModel *local_data = user_data;
local_data->DeviceId = gtk_combo_box_get_active(GTK_COMBO_BOX(local_data->device_type_box));
local_data->MeasurementId = gtk_combo_box_get_active(GTK_COMBO_BOX(local_data->measurement_type_box));
local_data->SyncEn = gtk_switch_get_active(GTK_SWITCH(local_data->sync_switch));
}
save_settings_button = gtk_button_new_with_label("Save");
reset_settings_button = gtk_button_new_with_label("Reset");
SettingsModel settings;
settings.device_type_box = device_type_box;
settings.measurement_type_box = measurement_type_box;
settings.sync_switch = sync_enabled_switch;
g_signal_connect(save_settings_button, "clicked", G_CALLBACK(click_save), &settings);
g_signal_connect(reset_settings_button, "clicked", G_CALLBACK(click_reset), &settings);
但是,當我單擊保存按鈕時,我收到以下錯誤:
(gui:28351): GLib-GObject-WARNING **: 16:52:26.673: invalid cast from 'GdkButtonEvent' to 'GtkComboBox'
(gui:28351): Gtk-CRITICAL **: 16:52:26.673: gtk_combo_box_get_active: assertion 'GTK_IS_COMBO_BOX (combo_box)' failed
zsh: segmentation fault ./gui
似乎是結構初始化錯誤,或者 GTK 以某種方式認為回呼應該采用 GdkButtonEvent?
這里的最小可重復示例:
#include <gtk/gtk.h>
enum
{
COL_ID = 0,
COL_NAME,
NUM_COLS
};
typedef struct SettingsModel
{
bool SyncEn;
int DeviceId;
int MeasurementId;
GtkWidget *measurement_type_box;
GtkWidget *sync_switch;
GtkWidget *device_type_box;
} SettingsModel;
static void click_save(GtkButton *self, gpointer user_data)
{
SettingsModel *local_data = user_data;
local_data->DeviceId = gtk_combo_box_get_active(GTK_COMBO_BOX(local_data->device_type_box));
local_data->MeasurementId = gtk_combo_box_get_active(GTK_COMBO_BOX(local_data->measurement_type_box));
local_data->SyncEn = gtk_switch_get_active(GTK_SWITCH(local_data->sync_switch));
}
static void click_reset(GtkButton *btn_reset, gpointer user_data)
{
SettingsModel *local_data = user_data;
local_data->DeviceId = 0;
local_data->MeasurementId = 0;
local_data->SyncEn = false;
gtk_switch_set_active(GTK_SWITCH(local_data->sync_switch), FALSE);
gtk_combo_box_set_active(GTK_COMBO_BOX(local_data->device_type_box), 0);
gtk_combo_box_set_active(GTK_COMBO_BOX(local_data->measurement_type_box), 0);
}
static void app_activate(GApplication *app, gpointer *user_data)
{
GtkWidget *win;
GtkWidget *grid;
g_assert(GTK_IS_APPLICATION(app));
win = gtk_application_window_new(GTK_APPLICATION(app));
grid = gtk_grid_new();
GtkWidget *device_type_box;
GtkWidget *measurement_type_box;
GtkWidget *save_settings_button;
GtkWidget *reset_settings_button;
GtkWidget *sync_enabled_switch;
GtkListStore *list_store_device;
GtkListStore *list_store_measurement;
GtkCellRenderer *column;
list_store_device = gtk_list_store_new(NUM_COLS, G_TYPE_INT, G_TYPE_STRING);
gtk_list_store_insert_with_values(list_store_device, NULL, -1, COL_ID, 0, COL_NAME, "foo", -1);
device_type_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(list_store_device));
g_object_unref(list_store_device);
column = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(device_type_box), column, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(device_type_box), column,
"text", 1,
NULL);
gtk_combo_box_set_active(GTK_COMBO_BOX(device_type_box), 0);
list_store_measurement = gtk_list_store_new(NUM_COLS, G_TYPE_INT, G_TYPE_STRING);
gtk_list_store_insert_with_values(list_store_measurement, NULL, -1, COL_ID, 0, COL_NAME, "foo", -1);
gtk_list_store_insert_with_values(list_store_measurement, NULL, -1, COL_ID, 0, COL_NAME, "bar", -1);
gtk_list_store_insert_with_values(list_store_measurement, NULL, -1, COL_ID, 0, COL_NAME, "something", -1);
measurement_type_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(list_store_measurement));
g_object_unref(list_store_measurement);
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(measurement_type_box), column, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(measurement_type_box), column,
"text", 1,
NULL);
gtk_combo_box_set_active(GTK_COMBO_BOX(measurement_type_box), 2);
save_settings_button = gtk_button_new_with_label("Save");
reset_settings_button = gtk_button_new_with_label("Reset");
sync_enabled_switch = gtk_switch_new();
SettingsModel settings;
settings.device_type_box = device_type_box;
settings.measurement_type_box = measurement_type_box;
settings.sync_switch = sync_enabled_switch;
g_signal_connect(save_settings_button, "clicked", G_CALLBACK(click_save), &settings);
g_signal_connect(reset_settings_button, "clicked", G_CALLBACK(click_reset), &settings);
gtk_grid_attach(GTK_GRID(grid), device_type_box, 1, 1, 1, 1);
gtk_grid_attach(GTK_GRID(grid), measurement_type_box, 1, 2, 1, 1);
gtk_grid_attach(GTK_GRID(grid), sync_enabled_switch, 1, 3, 1, 1);
gtk_grid_attach(GTK_GRID(grid), reset_settings_button, 4, 4, 1, 1);
gtk_grid_attach(GTK_GRID(grid), save_settings_button, 5, 4, 1, 1);
gtk_window_set_child(GTK_WINDOW(win), grid);
gtk_widget_show(win);
}
int main (int argc, char **argv) {
GtkApplication *app;
int stat;
app = gtk_application_new("simon.app", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(app_activate), NULL);
stat = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return stat;
}
uj5u.com熱心網友回復:
您正在訪問非法記憶體,因為您將非靜態物件的地址傳遞給您的回呼:
static void app_activate(GApplication *app, gpointer *user_data)
{
...
SettingsModel settings;
g_signal_connect(save_settings_button, "clicked", G_CALLBACK(click_save), &settings);
g_signal_connect(reset_settings_button, "clicked", G_CALLBACK(click_reset), &settings);
...
}
當您的信號處理程式被呼叫時,該函式app_activate已經回傳給呼叫者并且settings不再有效。您必須提供一些靜態記憶體物件的地址,或者您需要為您的設定動態分配記憶體。
我建議將定義更改settings為static SettingsModel settings;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/407543.html
標籤:
