Автор: Philippe Fremy
Перевод: Andi Peredri
Для ознакомления с этим исследованием, пожалуйста, загрузите исходный код.
Вот небольшой пример кода, написанный с поочередным использованием Gtk, Qt и PyQt. В нем нет ничего особо интересного, просто я хочу подчеркнуть, насколько Gtk и Qt имеют похожую структуру.
void gui_draw_pixmap(char *target, gint x, gint y){ GdkRectangle area; int value; gdk_draw_pixmap(buffer, space->style->black_gc, tiles_pixmap, get_piece_nr(target,x,y)*TILE_SIZE, 0, x*TILE_SIZE, y*TILE_SIZE, TILE_SIZE, TILE_SIZE); if(get_piece_id(target,x,y)=='*'){ if(get_piece_id(orig_map,x,y)=='.') value = 20; else value = 22; gdk_draw_pixmap(buffer, space->style->black_gc, tiles_pixmap, value*TILE_SIZE+10,10, x*TILE_SIZE+10, y*TILE_SIZE+10,8,8); } area.x = x*TILE_SIZE; area.y = y*TILE_SIZE; area.width = TILE_SIZE; area.height = TILE_SIZE; gtk_widget_draw (space, &area); }
Для переноса Gnotski с Gtk/C на Qt/C++ мне потребовалось 3 часа. Это был первый этап: я попробовал максимизировать общий код и структуру. Я не использовал настоящий C++, а лишь обернул C++ вокруг C-функций ( отсюда название C-Klotski ). Перенос оказался чрезвычайно простым. Gtk и Qt имеют похожую структуру виджетов и механизм сигналов и слотов.
void Klotski::gui_draw_pixmap(char *target, int x, int y) { int value; bitBlt( buffer, 0, 0, tiles_pixmap, get_piece_nr(target,x,y)*TILE_SIZE, 0, TILE_SIZE, TILE_SIZE, Qt::CopyROP); if(get_piece_id(target,x,y)=='*'){ if(get_piece_id(orig_map,x,y)=='.') value = 20; else value = 22; bitBlt( buffer, 8, 8, tiles_pixmap, value*TILE_SIZE+10,10, 8, 8, Qt::CopyROP); } QPainter p( space ); p.drawPixmap( x*TILE_SIZE, y*TILE_SIZE, *buffer ); p.end(); }
Вот тот же самый фрагмент кода:
void Board::gui_draw_pixmap(int x, int y) { int value; bitBlt( buffer, 0, 0, tiles_pixmap, map->piece_nr(x,y)*TILE_SIZE, 0, TILE_SIZE, TILE_SIZE, Qt::CopyROP); if(map->piece_id(x,y)=='*'){ if(map->is_goal(x,y)) value = 20; else value = 22; bitBlt( buffer, 8, 8, tiles_pixmap, value*TILE_SIZE+10,10, 8, 8, Qt::CopyROP); } QPainter p( this ); p.drawPixmap( x*TILE_SIZE, y*TILE_SIZE, *buffer ); p.end(); }
def gui_draw_pixmap(self,x, y) : bitBlt( self.buffer, 0, 0, self.tiles_pixmap, self.map.piece_nr(x,y)*TILE_SIZE, 0, TILE_SIZE, TILE_SIZE, Qt.CopyROP) if self.map.piece_id(x,y)=='*' : if self.map.is_goal(x,y) : value = 20 else: value = 22 bitBlt( self.buffer, 8, 8, self.tiles_pixmap, value*TILE_SIZE+10, 10, 8, 8, Qt.CopyROP) p = QPainter( self ) p.drawPixmap( x*TILE_SIZE, y*TILE_SIZE, self.buffer ); p.end()
83:void game_score(); 90:void score_cb(GtkWidget *, gpointer); 453: GNOMEUIINFO_MENU_SCORES_ITEM (score_cb, NULL), 482: gnome_score_init(APPNAME); 571: game_score(); 617:void score_cb(GtkWidget *widget, gpointer data){ 618: gnome_scores_display (_(APPNAME_LONG), APPNAME, current_level, 0); 619:} 620: 621:void game_score(){ 622: gint pos; 623: pos = gnome_score_log(moves,current_level,FALSE); 624: gnome_scores_display(_(APPNAME_LONG), APPNAME, current_level, pos); 625:}
В итоге это составляет:
Lines | Characters |
14 | 435 |
Вот результаты:
Files | Lines | Characters | ||
Gnotski | Declarations | Gnotski-declaration.h | 91 | 2454 |
Level+Menu | gnotski-levels.h | 381 | 8978 | |
Pure code | 568 | 13829 | ||
Total | pieces.h gnotski-without-score.c | 1040 | 25266 |
Files | Lines | Characters | ||
C-Klotski | Declarations | klotski.h | 126 | 3019 |
Level+Menu | klotski-levels-menu.h | 327 | 6528 | |
Pure code | 505 | 10453 | ||
Total | pieces.h klotski.h levels.h klotski.cpp | 958 | 19990 |
Files | Lines | Characters | ||
Cpp-Klotski | Declarations | klotski.h | 157 | 3136 |
Level+Menu | levels-menu.h | 319 | 6502 | |
Pure code | 492 | 9394 | ||
Total | pieces.h klotski.h levels.h klotski.cpp | 968 | 19032 |
Files | Lines | Characters | ||
PyQt-Klotski | Declarations | 0 | 0 | |
Level+Menu | levels-menu.py | 315 | 6270 | |
Pure code | 391 | 9357 | ||
Total | levels.py klotski.py pieces.py | 706 | 15633 |
Во-вторых, эта программа слишком коротка и проста. Поэтому наши выводы не определяют лучший инструментарий, а лишь являются первым впечатлением от их сравнения.
Различия между C-Klotski и Cpp-Klotski не вызывают удивления. Все объекты C-Klotski имеют неограниченный доступ друг к другу. Это не настоящая объектно-ориентированная программа. В Cpp-Klotski я определил, насколько мне это удалось, объекты с методами для доступа к другим объектам. То есть, объекты не могут получить свободный доступ к другим. Это более безопасно, но это также означает, что для связи объектов Вам потребуется больше методов. Это моя личная интерпретация.
Результат таков:
Я был немного удивлен столь относительно большим различием между C-Klotski и Cpp-Klotski. Это можно объяснить тем, что при более чистом коде Вы можете делать то же самое проще.
Без сомнения, лидирует PyQt-Klotski. На 100 строк меньше, чем в C-Klotski или Cpp-Klotski. Но почти то же самое число символов, что и в Cpp-Klotski. Я думаю, что это из-за необходимости использования 'self.' для доступа к членам класса, что немного неудобно.
toolkits-comparison > cat gnotski/*.h gnotski/*.c | wc 1054 3011 25696 > cat gnotski/*.h gnotski/*.c | sed -e 's/gtk_//g' -e 's/gdk_//g' -e 's/_//g' | wc 1054 3011 24645
toolkits-comparison > cat pyqt-klotski/*.py | wc 706 2156 15633 toolkits-comparison > cat pyqt-klotski/*.py | sed -e 's/self//g' | wc 706 2151 14737
VeePee содержит эквивалентный код для Gnome и KDE. Ответ автора из FAQ :
Разве не тяжело разрабатывать пользовательский графический интерфейс одновременно для нескольких инструментариев?
В действительности все инструментарии GUI обеспечивают похожий набор возможностей, однако реализуют их каждый по-своему. В настоящей версии VeePee 74% кода не зависит от GUI, 15% кода специфичны для Gnome и 11% - для KDE.
Таким образом, Gnome-код на 33% больше эквивалентного KDE-кода.
Одним из преимуществ Qt является более краткий синтаксис. Для Gtk приходится вводить на 30% больше символов, чем для Qt/C++. Это может занять довольно большой отрезок времени.
Теперь перейдем к PyQt. Python - отличный язык, очень простой и мощный одновременно. Переход от Qt/C++ к PyQt достаточно прост, поскольку все имена сохраняются. Он может быть осуществлен даже Python-сценарием. К тому же Вы можете использовать всю обширную документацию Qt.
Если Вы желаете использовать чистый C, используйте Gtk. Он был сделан именно для Вас. Но разве Gtk - это настоящий C ? Это C с конструкторами, деструкторами, объектами, наследованием и т.д. Это C с объектной реализацией. Вы не думаете, что истинный объектно-ориентированный язык мог бы упростить разработку и отладку вашей программы?
Если Вы согласны использовать C++, я настоятельно рекомендую Qt. Доступна обширная превосходная документация, а Ваша программа будет короче. C++ является родным языком для Qt, поэтому отсутствуют задержки в выходе новых версий и проблемы, связанные с обертками ( wrappers ). Один из бывших разработчиков Gtk-- ( привязок C++ для Gtk ) Гуиллаум Лаурент ( Guillaume Laurent ) сейчас с успехом использует Qt/KDE. И напоследок, Qt более развит, чем Gtk. Qt уже не один год обладает теми возможностями, которые были реализованы в последних версиях Gtk: уникод, двумерная графика ( canvas ), XML, потоки и т.д.
Если для Вашего приложения не критично время его выполнения, я рекомендую PyQt даже больше чем Qt. PyQt очень тесно интегрирован с Qt. К тому же Python - великолепный язык! Вы выиграете в размере и читаемости кода, во времени компиляции ( его нет ) и в эффективности. Поскольку язык изначально очень мощный, Вы можете без проблем использовать более сложные конструкции. И не забывайте, что PyQt можно непосредственно использовать в Windows и Linux.
Я признаю, что предпочитаю использовать Qt, но на протяжении этого исследования я старался оставаться нейтральным, насколько это было возможным, за исключением разделов, помеченных как "Личные".
Вам понравилась игра? Тогда посетите написанные мной настоящие klotski. Они созданы с нуля с использованием QCanvas, обладают множеством возможностей и не имеют почти ничего общего с этими klotski.
Было бы великолепно перенести эту же программу на другие инструментарии или языки. Для более интересного исследования мне действительно хотелось бы иметь, например, PyGtk и GtkAda версии.
Источник: From Gtk to PyQt