Немного лирики или с чего всё началось. Глядя на красивый KDE в Linux, мне хотелось научится писать программы и для него. Так я узнал о Qt. Всё хорошо, потихоньку изучаю, но «давит» гигантизм и запутанность С++. Хочется чего то компактного, быстрого и интелектуального. На глаза попадается D созданный Уолтером Брайтом. В своё время я начал изучение С++ с Zortech C++ (позже ставшего Symantec C++, а затем Digital Mars C++) и ни каких проблем с ним я не имел. Начал изучение D, который отлично работает в Windows/Linux, но вот проблема, хочется доступа к Qt. В инете есть QtD, но сколько я не пытался его реанимировать, ничего не получилось. Вот и решил я сделать что то для себя, благо ни куда не торопился.
QtE5 – это биндинг (обертка) функций Qt-5 в функции D. Сразу подчеркиваю, что Qt огромен, а QtE5 всего лишь очень маленькая его часть. Да, я постоянно дописываю новые функции, по мере изучения Qt и по мере необходимости в них, так как все свои проекты пишу на D + QtE5 + Qt. На момент написания статьи функций Qt в QtE5 около 400 штук.
QtE5 проверена и работает на Windows 32 (Win XP, 7, 10), Windows 64 ( Win 7, 10), Linux 32/64 (Fedora 23), Mac Os X 64 (Хакинтош Mavericks 10.9).
Примеры ниже – это Win 32 (Win 7). Для работы нам понадобится D (dmd) и RunTime Qt-5. Устанавливать Qt из дистрибутива нет необходимости, если вы не собираетесь расширять QtE5. Скачать QtE5 + RunTime Qt-5 можно с репозитория гитхаба. Для понимания работы исходного кода желательно иметь представление о работе Qt. Имена методов и классов в QtE5 повторяют имена в Qt, что позволяет пользоваться справочной системой самой Qt.
Первое приложение – классика. Привет мир! Сохраним текст в файле ex2.d
// ex2.d import qte5; // Подключим QtE5 import core.runtime; // Разбор аргументов ком.строки int main(string[] args) { // Загрузим и инициализируем QtE5 if (1 == LoadQt(dll.QtE5Widgets, true)) return 1; // Создадим объект приложения QApplication app = new QApplication(&Runtime.cArgs.argc, Runtime.cArgs.argv, 1); // Создадим виджет Label QLabel lb = new QLabel(null); // Добавим в него текст (поддерживается HTML) и обобразим lb.setText("Привет мир!
").show(); // Начнем цикл обработки графических событий app.exec(); // Закончим программу return 0; }
Компиляция и запуск:
dmd ex2 qte5 ex2
Результат:
Тут даже комментировать нечего, все прозрачно и просто. Самое время перейти к более сложному примеру. Для себя я его называю:
Нажми на кнопку и получишь результат!
Сразу несколько замечаний. Что мы хотим и должны получить. Будем изготавливать форму (простенькую) с двумя кнопками и надписью. При нажатии на кнопку будем выводить текст в консоль Windows русскими буквами и отображать окно сообщения.
Файл Ex5.d
// ex5.d import qte5; // Подключим QtE5 import asc1251; // Работа с русскими буквами в консоли Windows import core.runtime; import std.stdio; // Обработчики событий extern (C) { void on_acKn1() { string s = "Нажата кнопка № 1"; writeln(toCON(s)); msgbox(s); } void on_acKn2() { string s = "Нажата кнопка № 2"; writeln(toCON(s)); msgbox(s); } } class Forma : QWidget { QVBoxLayout vblAll; // Общий вертикальный выравниватель QHBoxLayout hblKn; // Горизонтальный выравниватель для кнопок QLabel lb; // Надпись QPushButton kn1, kn2; // Кнопки QAction acKn1, acKn2; // События кнопок // ________________ this(QWidget parent, QtE.WindowType fl) { super(parent, fl); resize(300, 100); setWindowTitle("Пример работы кнопок"); // Горизонтальный и вертикальный выравниватели vblAll = new QVBoxLayout(); hblKn = new QHBoxLayout(); // Надпись lb = new QLabel(this); lb.setText("Работа с кнопками
"); // Кнопки kn1 = new QPushButton("Кнопка № 1", this); kn2 = new QPushButton("Кнопка № 2", this); // События acKn1 = new QAction(this, &on_acKn1, null); acKn2 = new QAction(this, &on_acKn2, null); // Связываем нажатие кнопок с обработчиками событий connects(kn1, "clicked()", acKn1, "Slot()"); connects(kn2, "clicked()", acKn2, "Slot()"); // Кнопки в горизонтальный выравниватель hblKn.addWidget(kn1).addWidget(kn2); // Всё в вертикальный выравниватель vblAll.addWidget(lb).addLayout(hblKn); // Вертикальный выравниватель в форму setLayout(vblAll); } } int main(string[] args) { if (1 == LoadQt(dll.QtE5Widgets, true)) return 1; QApplication app = new QApplication(&Runtime.cArgs.argc, Runtime.cArgs.argv, 1); Forma f1 = new Forma(null, QtE.WindowType.Window); f1.show(); app.exec(); return 0; }
Компиляция и запуск:
dmd ex5 qte5 asc1251 ex5
Результат:
В этом примере несколько интересных моментов. Первое, это обработчики события. Они обязательно должны быть объявляны как Extern (C) … Это связано с тем, что QtE5 может работать с любым языком программтрования поддерживающим такие обратные вызовы. Второе, это
connects(kn1, "clicked()", acKn1, "Slot()");
Это стандартная связка сигналов и слотов в Qt. Очень большое достижение QtE5 в том, что с одной стороны она позволяет обойтись без метакомпилятора Qt, а с другой стороны сохраняет механизм сигналов/слотов, тем самым обеспечивая очень гибкую структуру взаимодействия различных частей программы друг с другом. И последний момент, на который хотелось бы обратить внимание. Это «сложность» компиляции приложения. Ни огромных Make файлов, ни длинных ключей компилятора, да и время компиляции – мгновенно. Чудес конечно не бывает, и за это приходится платить отсутствием гибкости в других моментах, но для обычных, рядовых программ это не существенно.
Считаю, что QtE5 хорошее дополнение к D, что бы сделать его изучение приятным и полезным.
Создатель QtE5 Мохов Геннадий Владимирович (MGW)
От администрации блога: благодарим Геннадия Владимировича за прекрасную статью и очень важную для развития D библиотеку-связку с Qt5!