GTK+ — 4. Події та сигнали

Березень 25, 2009

У цій частині я розповім про систему подій (events) та сигналів у бібліотеці GTK+. Власне, бібліотека GTK+ є “event driven system”, тобто, такою, що цілком побудована на основі системи подій та сигналів на них. Адже усі графічні додатки є “event driven”, тобто такими, мета яких реагувати на певні дії користувача (події), надсилати своєму коду сигнали, і обробляти їх.

Усе починається з того, що програма запускає головний цикл, який неперервно перевіряє наявність нових подій. Якщо ніяких подій не відбувається, програма тихенько собі спить, і нічогісінько не робить. У GTK+ повідомленнями про події є повідомлення від сервера X. Коли віджет генерує якусь подію, програма може на неї відреагувати. Програміст GTK+ може з’єднувати специфічні колбеки (callback) та сигнали. Сам callback є нічим іншим, як вказівником на звичайнісіньку функцію, яка реагуватиме на сигнал. Наприклад, маємо віджет “кнопка”, подію “натискання на кнопку”, і колбек (функцію), яка викликається при обробці події (натискання на кнопку).

У версії 2.0 сигнальну систему було перенесена з GTK до GLib, ось чому функції і типи, що описуються в цьому розділі мають префікс “g_” а не “gtk_”. Ми не будемо заглиблюватись в деталі, що до додаткових можливостей, які дає сигнальна система GLib 2.0 порівняно з сигнальною системою GTK 1.2.

Read the rest of this entry »


Реєстрація в інтернет-магазинах або за що ви так ненавидите своїх клієнтів?

Березень 21, 2009

Я не розумію, чим керуються програмісти, які змушують користувачів інтернет-магазинів обов’язково реєструватись при оформленні покупки? Невже не очевидно, що до біса мені здалась ваша реєстрація, коли я просто хочу замовити довбану книжку, і далі займатись своїми справами?

Може на стільки прості й очевидні, навіть для мене, людини, яка досить погано розбирається у зручності користувацьких інтерфейсів, речі не пишуть у книжках по usability? Та ні, пишуть, і не просто пишуть, а ще й розповідають реальні історії про цю ідіотську реєстрацію. Просто їм, схоже, до шмиги здалося читати усю цю “теоретичну херню”.

Ну, хіба це так складно, додати кнопку “Продовжити без реєстрації”?

registration_form_in_internet_shops-3

Може вони збуджуються дивлячись на те, що отримуване по запиту `SELECT COUNT(id) FROM users;` число стає усе більшим, і більшим, не усвідомлюючи або ж просто ігноруючи той факт, що більшість цих облікових записів є одноразовими?

Власне, злість уже проходить, та й писати далі немає сенсу, бо суть зрозуміла (і вдома уже досить багато років), тож НЕ РОБІТЬ ТАКОГО!!!


The Practice of Programming

Березень 12, 2009

Практика програмування

Автори: Браян Керніґан, Роб Пайк
Видавництво: Addison-Wesley
Рік видання: 2004

Це просто меґа унікальна книжка. Чим? Ну, перш за все, її написали легендарні Браян Керніган і Роб Пайк. По друге, це не книжки про щось конкретне, чи навіть щось досить широке по своїй суті, але таке, що належить до однієї теми, на кшталт: проектування, рефакторинг коду, оптимізація, відлагодження, тестування, тощо. Це книжка про усе це! Але автори не приділяють кожному з цих питань по 200 сторінок, вони не доколупуються до найдрібніших деталей, не розповідають читачеві про предмет з нуля, і не дають основи описуваних понять, чи навпаки, приклади “вищого пілотажу”.

Ні, вони усього лиш на досить простих, і, що дуже важливо, практичних життєвих прикладах, покладаючись на свою дійсно багаторічну професійну практику, показують читачу, як слід, а, як не слід робити повсякденні проґрамерські речі: дотримуватись стилю програмування, обирати вірні структури даних і алгоритми, проектувати, реалізовувати, тестувати, відлагоджувати, тощо. І роблять це таким чином, що у тебе просто дах їде, бо це змушує наново поглянути, на здавалося б, такі прості і звичні для кожного програміста речі.

Ось її зміст:
1. Style
2. Algorithms and Data Structures
3. Design and Implementation
4. Interfaces
5. Debugging
6. Testing
7. Perfomance
8. Portability
9. Notation

Висновок: книжка досить малого об’єму =~ 250 сторінок, відомих авторів, і з просто суперовим стилем викладу матеріалу, а тому, однозначно, MUST READ!!!

Оцінка: відмінно


GTK+ — 3. Керування позиціонуванням віджетів

Лютий 8, 2009

У цій “лекції” я спробую пояснити, яким чином додавати на вікно нові віджети, та організувати їхнє бажане для вас позиціонування на ньому.

Власне, річ ось у чім — у GTK+, як і в усіх інших бібліотеках графічних віджетів для UNIX ви не можете (взагалі то можете, але про це, можливо, згодом) тупо накидати будь які віджети (кнопки, мітки, чекбокси, едітбокси, тощо) на форму, встановити зручні для вас розміри і місцерозташування цих віджетів, як, скажімо, у VLC.

UNIX’ові бібліотеки графічних віджетів використовують інших підхід до розміщення елементів на формі. Елементи розміщуються не лише по відношенню до верхнього лівого кута. Їхній розмір ще й задається по відношенню до висоти і ширини форми.

Тобто, якщо ви розмістите на формі лиш одну кнопку, то вона, за замовчуванням, матиме висоту і ширину рівну, відповідно, висоті і ширині форми. Не лякайтесь, ви звісно ж, можете чітко задати позицію та розміри кнопки, однак, даний підхід має низку переваг. Сподіваюсь, пояснити вам їх по ходу…

GtkFixed

Даний контейнер поміщає віджети у чітко фіксовані позиції і задає для них чітко фіксовані розміри. Даний контейнер не виконує автоматичну схему управління позицією та розміром віджетів. За звичай, він використовується досить рідко, наприклад, у програмах, де можна змінювати розміри віджетів або ж міняти їхню позицію.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <gtk /gtk.h>
 
 
int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *fixed;
 
    GtkWidget *button1;
    GtkWidget *button2;
    GtkWidget *button3;
 
    gtk_init(&argc, &argv);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "GtkFixed");
    gtk_window_set_default_size(GTK_WINDOW(window), 290, 200);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
    fixed = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), fixed);
 
    button1 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);
    gtk_widget_set_size_request(button1, 80, 35);
 
    button2 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button2, 15, 15);
    gtk_widget_set_size_request(button2, 80, 35);
 
    button3 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button3, 100, 100);
    gtk_widget_set_size_request(button3, 80, 35);
 
    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
    gtk_widget_show_all(window);
 
    gtk_main();
 
    return 0;
}
</gtk>

У даному прикладі, ми створюємо три кнопки, і поміщаємо їх на чітко вказані координати. Коли ми змінюємо розміри вікна, кнопки залишаються на своїх місцях.

Тут ми створюємо віджет контейнер GtkFixed:

fixed = gtk_fixed_new();

А тут, за допомогою функції gtk_fixed_put() поміщаємо першу кнопку у позиц

gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);

gtkfixed

Read the rest of this entry »


Зневадження коду за допомогою strace

Лютий 8, 2009

Ви коли небуть ломали собі голову над пошуком помилки? Помилки, яку ніяк не вдається знайти у джерельних текстах, але яка часто проявляється після компіляції і запуску програми. Знайомтесь: strace. strace — це утиліта, яка дозволяє вам трасувати системні виклики і сигнали конкретної команди. Якої команди? А які у вас є?

strace — вільне програмне забезпечення, що розповсюджується на умовах ліцензії, подібної до ліцензії BSD. Спершу утиліта була написана Полом Краненбургом (Paul Kranenburg) для SunOS за мотивами іншої утиліти для SunOS, trace. На Linux її портував Бранко Ланкестер (Branko Lankester), котрий, окрім цього, реалізував її підтримку в ядрі. У 1993, Рік Следкі (Rick Sladkey) об’єднав strace 2.5 для SunOS з другою версією strace для Linux, додавши при цьому багато можливостей truss(1) з SVR4. В результаті, з’явилася strace, котра працювала на обох платформах. Сьогодні, strace підтримується Уічертом Аккерманом (Wichert Akkerman) і Роландом МакҐрасом (Roland McGrath).

Трасування helloworld

Робота strace полягає у перехопленні і записі системних викликів, виконаних процесом, а також отриманих ним сигналів. Для кожного системного виклику, до стандартного файлу помилок, або ж до будь якого іншого заданого файлу, виводиться його ім’я, аргументи і код виклику. Як щодо кількох прикладів?

Щоб не ускладнювати роботу strace, я використав найпростішу з можливих програм.

1
2
3
4
5
6
7
#include <stdio .h>
 
main()
{
    printf("Hello World n");
}
</stdio>

Компілюємо її:

# gcc -o helloworld helloworld.c

Готово! Запускаємо: ./helloworld, і отримаємо на стандартний вихід:

Hello World

Виглядає надзвичайно просто. Тепер запустимо strace. strace протрасує, і виведе на stderr усі системні виклики і сигнали:

# strace ./helloworld

Вивід команди `strace ./helloworld`:

 1  execve("./helloworld", ["./helloworld"], [/* 22 vars */]) = 0
 2  uname({sys="Linux", node="knuth", ...}) = 0
 3  brk(0)                                  = 0x81f7000
 4  access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
 5  open("/etc/ld.so.cache", O_RDONLY)      = 3
 6  fstat64(3, {st_mode=S_IFREG|0644, st_size=73856, ...}) = 0
 7  old_mmap(NULL, 73856, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fed000
 8  close(3)                                = 0
 9  open("/lib/tls/libc.so.6", O_RDONLY)    = 3
10  read(3, "177ELF111331 ?B00"..., 512) = 512
11  fstat64(3, {st_mode=S_IFREG|0755, st_size=1454835, ...}) = 0
12  old_mmap(0x40f000, 1215644, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x40f000
13  old_mmap(0x532000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x123000) = 0x532000
14  old_mmap(0x536000, 7324, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x536000
15  close(3)                                = 0
16  old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fec000
17  mprotect(0x532000, 4096, PROT_READ)     = 0
18  mprotect(0x40b000, 4096, PROT_READ)     = 0
19  set_thread_area({entry_number:-1 -> 6, base_addr:0xb7fec940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
20  munmap(0xb7fed000, 73856)               = 0
21  fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
22  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fff000
23  write(1, "Hello World n", 13)          = 13
24  munmap(0xb7fff000, 4096)                = 0
25  exit_group(13)                          = ?

Перше, що ми бачимо — це execve. execve() виконує програму, задану ім’ям файлу. Далі, uname() отримує ім’я і тип системи, яку я використовував для тесту. Після цього, наша програма запитує певну кількість пам’яті і мапи розміщення розділюваних бібліотек, необхідних для роботи, наприклад, динамічний завантажувач і libc. До всієї цієї інформації ми скоро повернемося, а поки подивимося, що відбувається далі. Рядок 23 виводу трасування, нарешті відкриває нам призначення нашої програми helloworld (як би ми не бачили джерельного коду): вивести у файловий дескриптор 1 (STDOUT), повідомити кількість байт у виведеній інформації та їх значення. Не складно здогадатися, що застосування трасування може допомогти вам відстежити у програмі конкретний виклик або сигнал. Чим же це корисно? Якщо ви пишете програму трохи більш складну, ніж helloworld.c, і вона дає збій, видаючи мінімум, або взагалі не видаючи інформації про те, що з нею сталося, трасування може вам допомогти виявити причину, яка викликає збій у процесі роботи.

Read the rest of this entry »


Get Adobe Flash playerPlugin by wpburn.com wordpress themes