вопрос по программированию gtk+

Все о программировании под *nix
Anonymous

вопрос по программированию gtk+

Сообщение Anonymous »

вопрос по программированию gtk+

есть vbox (VBOX), содержащий hbox и кнопку.
hbox содержит два виджета разделенных separator'ом.
Один из этих виджетов - лист (см. GtkWidget a()).
Вопрос: необходимо, чтобы по нажатию кнопки (button) обновилось содержимое
виджета Leftwidget. Что для этого нужно прописать в xxx и, возможно,
добавить в g_signal_connect?

//---------------------------------------------------
static void xxx (GtkWidget *button, gpointer data) { ??? }
//---------------------------------------------------
int main(int argc, char *argv[]) {
...
GtkWidget *VBOX = gtk_vbox_new (FALSE, 1);
GtkWidget * hbox = gtk_hbox_new(FALSE, 0);
GtkWidget *Separator = gtk_vseparator_new();
GtkWidget *button = gtk_button_new_with_label("Hi!");
GtkWidget *Lefwidget = a();

gtk_box_pack_start (GTK_BOX (VBOX), hbox, TRUE, TRUE, 0);

gtk_box_pack_start (GTK_BOX (hbox), Lefwidget, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), Separator, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), Rigwidget, TRUE, TRUE, 0);

g_signal_connect(button, "clicked", xxx, NULL);

gtk_box_pack_start (GTK_BOX (VBOX), button, FALSE, FALSE, 0);
...
}
//---------------------------------------------------
GtkWidget a(){
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
GtkWidget *tree_view = gtk_tree_view_new ();
GtkListStore *list = gtk_list_store_new ( ... );
GtkTreeIter iter;
gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (list));
gtk_widget_show (tree_view);
for ( ... ) { //заполняем лист
gtk_list_store_append (GTK_LIST_STORE (list), &iter);
gtk_list_store_set (GTK_LIST_STORE (list), &iter, ..., -1);
}
GtkCellRenderer *cell;
GtkTreeViewColumn *column;
//
column = gtk_tree_view_column_new_with_attributes ("столбец1", cell, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));

column = gtk_tree_view_column_new_with_attributes ("столбец2", cell, "text", 1, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));


return scrolled_window;
}
//---------------------------------------------------

Anonymous

Re: вопрос по программированию gtk+

Сообщение Anonymous »

Как я понял по кнопке должно обновлятся содержимое листа?

Тогда делай так:

Выноси во внешние переменные все что надо для того чтобы записывать
содержимое в лист.

Выноси загрузку содержимого листа в отдельную функцию и пользуйся ей в a(), когда надо загрузить содержимое в лист.

А также ставь ее в xxx.
Чтобы по нажатию кнопки опять загружался список.

Anonymous

Сообщение Anonymous »

//Задам вопрос по-другому, на конкретном работающем примере.
//Есть лист заполненный 10 элементами, при нажатии кнопки "enter"
//на любом элементе выводится сообщение "Hello". Как сделать чтобы
//вместо вывода сообщения 1)лист "очистился" от всех элементов 2)в лист добавилось
//несколько новых элементов (напр. 3 элемента "opennet")?
//gcc file.c -o file -Wall `pkg-config gtk+-2.0 --cflags --libs`

#include <stdio.h>
#include <gtk/gtk.h>

void sss( gpointer data) { puts("Hello"); }
//--------------------------------------------------------------------
GtkWidget *create_list( void ) {

GtkWidget *scrolled_window, *tree_view;
GtkListStore *model;
GtkTreeIter iter;
GtkCellRenderer *cell;
GtkTreeViewColumn *column;
int i;
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
model = gtk_list_store_new (1, G_TYPE_STRING);
tree_view = gtk_tree_view_new ();
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), tree_view);
gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));
gtk_widget_show (tree_view);
for (i = 0; i < 10; i++) {
gchar *msg = g_strdup_printf ("Message #%d", i);
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, msg, -1);
g_free (msg);
}
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Messages", cell, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));
g_signal_connect (G_OBJECT (tree_view), "select-cursor-row", G_CALLBACK (sss), NULL);
return scrolled_window;
}
//---------------------------------------------------------------------
int main( int argc, char *argv[])
{
GtkWidget *window, *list;

gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hi");
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (GTK_WIDGET (window), 450, 400);
list = create_list ();
gtk_container_add (GTK_CONTAINER (window), list);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

Anonymous

Сообщение Anonymous »

В append_item добавляется элемент списка.

gtk_list_store_clear(model) - очищает список

GtkListStore *model - я вынес во внешние переменные

int count - чтобы было понятно что потом по enter'у загрузка нового списка то же происходит

[code]
#include <stdio.h>
#include <gtk/gtk.h>

GtkListStore *model;
int count = 0;

void append_item(gchar *msg)
{
GtkTreeIter iter;

gtk_list_store_append (GTK_LIST_STORE (model), &iter);
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, msg, -1);
}

void sss( gpointer data)
{
int i;

count++;

gtk_list_store_clear(model);

for (i=1; i<=3; i++){
gchar *msg = g_strdup_printf ("(%d) opennet %d", count, i);

append_item(msg);

g_free (msg);
}

}

GtkWidget *create_list(void)
{
GtkWidget *scrolled_window, *tree_view;
GtkCellRenderer *cell;
GtkTreeViewColumn *column;

int i;

scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
model = gtk_list_store_new (1, G_TYPE_STRING);
tree_view = gtk_tree_view_new ();
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), tree_view);
gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));

gtk_widget_show (tree_view);

for (i = 0; i < 10; i++) {
gchar *msg = g_strdup_printf ("Message #%d", i);

append_item(msg);

g_free (msg);
}
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Messages", cell, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));

g_signal_connect (G_OBJECT (tree_view),
"select-cursor-row",
G_CALLBACK (sss),
NULL);


return scrolled_window;
}

int main( int argc, char *argv[])
{
GtkWidget *window, *list;

gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hi");

g_signal_connect (G_OBJECT (window),
"destroy",
G_CALLBACK (gtk_main_quit),
NULL);

gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (GTK_WIDGET (window), 450, 400);

list = create_list ();

gtk_container_add (GTK_CONTAINER (window), list);

gtk_widget_show_all (window);

gtk_main ();

return 0;
}
[/code]

Anonymous

Сообщение Anonymous »

Cпасибо, уважаемый Gnome. Вы мне здорово помогли.
Осмелюсь задать еще несколько вопрсов:

------1------
В моей программе в зависимости от типа элементы списка должны закрашиваться в разные цвета.
Например, если в GtkWidget *create_list(void) после инициализации cell = gtk_cell_renderer_text_new ();
добавить g_object_set(G_OBJECT(cell), "foreground", "red", NULL); названия всех ячеек будут иметь красный цвет.
Как сделать, чтобы при запуске программы первые 5 элементов "Message #%d" были одного цвета, остальные - другого?

------2------
И еще вопрос по поводу листа. По умолчанию названия ячеек используют большой (относительно) шрифт и занимают слишком много места.
Чтобы решить эту проблему я в GtkWidget *create_list(void) после инициализации cell = gtk_cell_renderer_text_new (); добавил следующие строки:
PangoFontDescription *font_desc = pango_font_description_from_string("MiscFixed");
g_object_set(G_OBJECT(cell), "font-desc", font_desc, NULL);
g_object_set(G_OBJECT(cell), "size-set", TRUE, NULL);
g_object_set(G_OBJECT(cell), "size-points",8.2, NULL);
g_object_set(G_OBJECT(cell), "size", 8000, NULL);
В принципе это принесло положительный эффект, однако если присмотреться, текст в ячейке занимает почти все место, но не все (имеется ввиду высота текста).
Под и над текстом в ячейке остается свободное место - 2-3 пиксела. Что необходимо предпринять, чтобы свободного места не было (чтобы ячейки были впритык,
чтобы текст соседних ячеек был пиксел к пикселу но не налазил друг на друга)?

------3------
На какую функцию следует обратить внимание чтобы изменить цвет текста и фон названия колонки (в нашем случае это колонка "Messages").

------4------
Чем чревато использование deprecated-функций?

------5------
Могли бы вы порекомендовать приличную литературу, интернет-ресурсы, дающие исчерпывающее описание gtk+-2.0, а то GTK+ Reference Manual
читается (точнее понимается) с трудом, хорошо хоть кое-где встречаются примеры. Ну еще gtk-demo. freshmeat & sourceforge конечно хорошо,
но на разбор чужого текста уходит слишком много времени.

------6------
Есть ли договоренность или стандарт на размещение файлов относящихся к одной программе в файловой системе линукс?
Напр. mozilla инсталлируются в /usr/lib/, opera - куда только можно и т.д.

------7------
Вы случайно не знаете есть ли такая open-source библиотечка или программа, которые реализуют следующий виджет (под gtk+):
Такой же лист (список) как и в нашем случае, но с одним отличием: он многоколоночный, точнее колонка одна, но
в несколько рядов (скроллинг горизонтальный). Ширина колонки = ширине самой длинной ячейки. Чтоб было понятней о чем это я,
возьмите какое-нибудь kde-приложение и запустите диалог "Открыть" или "Сохранить как". Виджет, отображающий файлы - и есть
то, о чем я говорил.


Не сочтите меня за наглеца (так много вопросов), просто нет знакомых gtk-кодеров (да и вообще линуксоидов).
Еще раз спасибо.

Аватара пользователя
Llama
Неотъемлемая часть форума
Сообщения: 9749
Зарегистрирован: 06 фев 2002, 11:40
Откуда: Менск

Сообщение Llama »

manny21 писал(а):
------6------
Есть ли договоренность или стандарт на размещение файлов относящихся к одной программе в файловой системе линукс?
Напр. mozilla инсталлируются в /usr/lib/, opera - куда только можно и т.д.
Называется Linux Standart Base - LSB. Также есть Debian Policy где тоже не мало информации по поводу размещения файлов и создания пакетов.
Опыт растет прямо пропорционально выведенному из строя оборудованию

Anonymous

Сообщение Anonymous »

------1------
В моей программе в зависимости от типа элементы списка должны закрашиваться в разные цвета.
Например, если в GtkWidget *create_list(void) после инициализации cell = gtk_cell_renderer_text_new ();
добавить g_object_set(G_OBJECT(cell), "foreground", "red", NULL); названия всех ячеек будут иметь красный цвет.
Как сделать, чтобы при запуске программы первые 5 элементов "Message #%d" были одного цвета, остальные - другого?

Если ты хочешь знать есть ли какая-либо функция чтобы можно было задать с какой по какую строку и какой цвет,
то я незнаю есть ли такая.

------2------
И еще вопрос по поводу листа. По умолчанию названия ячеек используют большой (относительно) шрифт и занимают слишком много места.
Чтобы решить эту проблему я в GtkWidget *create_list(void) после инициализации cell = gtk_cell_renderer_text_new (); добавил следующие строки:
PangoFontDescription *font_desc = pango_font_description_from_string("MiscFixed");
g_object_set(G_OBJECT(cell), "font-desc", font_desc, NULL);
g_object_set(G_OBJECT(cell), "size-set", TRUE, NULL);
g_object_set(G_OBJECT(cell), "size-points",8.2, NULL);
g_object_set(G_OBJECT(cell), "size", 8000, NULL);
В принципе это принесло положительный эффект, однако если присмотреться, текст в ячейке занимает почти все место, но не все (имеется ввиду высота текста).
Под и над текстом в ячейке остается свободное место - 2-3 пиксела. Что необходимо предпринять, чтобы свободного места не было (чтобы ячейки были впритык,
чтобы текст соседних ячеек был пиксел к пикселу но не налазил друг на друга)?

g_object_set(G_OBJECT(cell), "size-points",0.0, NULL);
вроде расстояние уменьшилось.

------3------
На какую функцию следует обратить внимание чтобы изменить цвет текста и фон названия колонки (в нашем случае это колонка "Messages").

Извини, не знаю.
------4------
Чем чревато использование deprecated-функций?

deprecated-функции и deprecated-виджеты, это то, что осталось
в какой-либо версии gtk+ для совместимости с предыдущей. И скорее
всего они буду убраны в последующих версиях. Настоятельно не рекомендую использовать их в новых программах.

------5------

Могли бы вы порекомендовать приличную литературу, интернет-ресурсы, дающие исчерпывающее описание gtk+-2.0, а то GTK+ Reference Manual
читается (точнее понимается) с трудом, хорошо хоть кое-где встречаются примеры. Ну еще gtk-demo. freshmeat & sourceforge конечно хорошо,
но на разбор чужого текста уходит слишком много времени.

Кроме GTK+ Reference Manual, по gtk2 не знаю, но можешь почитать "Программирование Gnome/GTK+(Артур Гриффитс)" там
про gtk1, но если ты начинаешь то основы я думаю от туда взять можно.

------7------
Вы случайно не знаете есть ли такая open-source библиотечка или программа, которые реализуют следующий виджет (под gtk+):
Такой же лист (список) как и в нашем случае, но с одним отличием: он многоколоночный, точнее колонка одна, но
в несколько рядов (скроллинг горизонтальный). Ширина колонки = ширине самой длинной ячейки. Чтоб было понятней о чем это я,
возьмите какое-нибудь kde-приложение и запустите диалог "Открыть" или "Сохранить как". Виджет, отображающий файлы - и есть
то, о чем я говорил.

Извини у меня нет возможности запустить kde, приложения.
Но заочно могу сказать что левых виджетов для gtk, не так уж много.
Есть модифицированный текстовый с подсветкой синтаксиса, но самая
главная либа это гном, его виджеты то же по сути дела надстройка над gtk.

В принципе если ты кинешь здесь маленький скриншот того виджета в kde, то я
смогу более определенно ответить.

--------
Не сочтите меня за наглеца (так много вопросов), просто нет знакомых gtk-кодеров (да и вообще линуксоидов).
Для этого и существует форум, чтобы вопросы задавать:)

Anonymous

Сообщение Anonymous »

Спасибо Gnome & Llama за ответы.
2 Gnome: по поводу вопроса 7 - не знаю как на форум скриншот кинуть, но подобный лист можно увидеть под ms windows при запуске стандартного диалога "Открыть файл".

Anonymous

Сообщение Anonymous »

Код: Выделить всё


//возникло еще пару вопросов - см. ниже в комментариях

#include <stdio.h>
#include <gtk/gtk.h>

GtkListStore *model;

void append_item(gchar *msg) {
  GtkTreeIter iter;
  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
  gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, msg, -1);
}

void sss( gpointer data){
  puts("hi");
}

GtkWidget *create_list(void) {
  GtkWidget *scrolled_window, *tree_view;
  GtkCellRenderer *cell;
  GtkTreeViewColumn *column;

  int i;

  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  model = gtk_list_store_new (1, G_TYPE_STRING);
  tree_view = gtk_tree_view_new ();
  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), tree_view);
  gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));

  gtk_widget_show (tree_view);

  for (i = 0; i < 10; i++) {
    gchar *msg = g_strdup_printf ("Message #%d", i);
    append_item(msg);
    g_free (msg);
  }
  cell = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes ("Messages", cell, "text", 0, NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));

  GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
  //делаем возможным выбор нескольких полей
  //выбор осуществляется с помощью зажатого SHIFT + UP/DOWN
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);  

  return scrolled_window;
}

int main( int argc, char *argv[]) {
  GtkWidget *window, *list;

  gtk_init (&argc, &argv);
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Hello");
  g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
  gtk_widget_set_size_request (GTK_WIDGET (window), 450, 400);
  list = create_list ();

  GtkWidget
    *box = gtk_vbox_new(FALSE, 1),
    *button = gtk_button_new_with_label("press me");  

  //нажимаеи кнопку, активируем sss, которая выводит сообщение "hi"
  //Вопрос 1: как сделать, чтобы по нажатию кнопки выводились имена ячеек листа, которые выбраны.
  //Вопрос 2: как сделать, чтобы по нажатию ENTER выводилось имя ячейки над которой находится
  //"прозрачный курсор" -  курсор, который не заполняет цветом ячейку над которой он находится
  //(некоторые gtk-engines (напр."Океанская греза") почему-то вообще не отображают такой курсор). 
  //Чего я хочу на примере: запускаем программу, выделяем первые 4 элемента (SHIFT+DOWN), зажимаем CONTROL, жмем
  //несколько раз DOWN пока прозр. курсор не дойдет до последней ячейки.
  //Жмем "press me" -> вывод "Message #1 Message #2 Message #3 Message #4"
  //Жмем ENTER -> вывод "Message #9"
  g_signal_connect (G_OBJECT (button), "pressed", G_CALLBACK (sss), NULL);

  gtk_box_pack_start (GTK_BOX (box), list, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (box), button, 0, TRUE, 0);

  gtk_container_add (GTK_CONTAINER (window), box);
  
  gtk_widget_show_all (window);
  
  gtk_main ();

  return 0;
}


Anonymous

Сообщение Anonymous »

На счет прозрачного курсора, на самом деле когда я нажимаю Enter,
фокус падает на тот элемент списка, над которым находиться прозрачный курсор, так что не вижу трудности.

На счет выделения нескольких объектов списка вот листинг:

Код: Выделить всё

#include <gtk/gtk.h>

enum
{
   COLUMN
};

GtkListStore *model;
GtkTreeSelection *selection;

void append_item(gchar *msg) {
  GtkTreeIter iter;
  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
  gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, msg, -1);
}


void  get_names(GtkTreeModel *model,GtkTreePath *path,
                GtkTreeIter *iter, gpointer data)
{

 gchar *s;

 gtk_tree_model_get (model, iter, COLUMN, &s, -1);
 g_print ("You selected: %s\n", s);
 g_free (s);

}

void sss(GtkWidget *w, gpointer data)
{
 gtk_tree_selection_selected_foreach (selection, get_names,
                                             NULL);
}

GtkWidget *create_list(void) {
  GtkWidget *scrolled_window, *tree_view;
  GtkCellRenderer *cell;
  GtkTreeViewColumn *column;

  int i;

  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  model = gtk_list_store_new (1, G_TYPE_STRING);
  tree_view = gtk_tree_view_new ();
  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), tree_view);
  gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));

  gtk_widget_show (tree_view);

  for (i = 0; i < 10; i++) {
    gchar *msg = g_strdup_printf ("Message #%d", i);
    append_item(msg);
    g_free (msg);
  }
  cell = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes ("Messages", cell, "text", COLUMN, NULL);

  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); 

  return scrolled_window;
}

int main( int argc, char *argv[]) {
  GtkWidget *window, *list;

  gtk_init (&argc, &argv);
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Hello");
  g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
  gtk_widget_set_size_request (GTK_WIDGET (window), 450, 400);
  list = create_list ();

  GtkWidget
    *box = gtk_vbox_new(FALSE, 1),
    *button = gtk_button_new_with_label("press me"); 

  g_signal_connect (G_OBJECT (button), "pressed", G_CALLBACK (sss), NULL);

  gtk_box_pack_start (GTK_BOX (box), list, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (box), button, 0, TRUE, 0);

  gtk_container_add (GTK_CONTAINER (window), box);
 
  gtk_widget_show_all (window);
 
  gtk_main ();

  return 0;
} 

Anonymous

Сообщение Anonymous »

Это то что надо! Спасибо.

Ответить