Давно уже хотел написать по поводу wxJavaScript. По-моему сейчас как раз пришло время для этого, т.к. проект уже успел развиться до такого состояния, когда все работает более-менее стабильно.
Итак, что же это за зверь wxJavaScript? Проект начинался как обычный порт wxWidgets на JavaScript, но, со временем, “оброс” библиотеками, которых в wxWidgets отродясь не было. Это модули curl, sqlite, mysql и др. Также проект получил реинкарнацию в виде модуля к Apache, который может использоваться для создания динамических HTML-страниц. Но об этом потом. Сейчас мне бы хотелось рассказать о том, как этим всем можно пользоваться для достижения собственных корыстных целей.
wxJavaScript поставляется в виде исполняемого файла интерпретатора и дополнительных модулей в виде динамических библиотек. Перечень используемых модулей может изменяться в конфигурационном файле. Это значит, что если на вашей машине используются скрипты только для доступа к базам данных, то нет никакой необходимости подключать, например библиотеку для создания графического интерфейса. Это позволяет экономить память, используемую движком wxJavaScript.
Минимальное приложение для wxJS выглядит так:
minimal.js
print("Hello World !!!");
Запустить скрипт на выполнение можно командой
wxjs minimal.js
Теперь рассмотрим, как создать минимальное приложение с графическим интерфейсом.
minimal_gui.js
wxTheApp.onInit = init;
function init()
{
var frame = new wxFrame(null, -1, "Minimal");
frame.visible = true;
wxTheApp.topWindow = frame;
return true;
}
Для того, чтобы наше приложение запустилось, нам необходимо включить поддержку графического интерфейса в конфигурационном файле:
modules.js
...
wxjs.modules.io = new Module("../modules/wxjs_gui.dll");
wxjs.modules.io.load();
...

В принципе, API очень схож с wxWidgets API для C++, но есть некоторые особенности. Например, обработчики событий от меню навешиваются к объекту меню через массив actions, а не к форме.
Давайте рассмотрим более сложный пример программы с графическим интерфейсом, использующий обработчики событий.
advanced_gui.js
// Указываем что при инициализации приложения должна
// вызваться функция init
wxTheApp.onInit = init;
function OnFileNew()
{
this.textCtrl.value = "";
}
function OnFileOpen()
{
// Создаем диалог открытия файла
var fileDialog = new wxFileDialog(this, "Open a file");
// Устанавливаем стиль диалога
fileDialog.style = wxFileDialog.OPEN;
// Если диалог отработал успешно...
if(fileDialog.showModal() == wxId.OK)
{
// Загружаем файл в текстовое поле
this.textCtrl.loadFile(fileDialog.path);
}
}
function OnFileSave()
{
var fileDialog = new wxFileDialog(this, "Save file");
fileDialog.style = wxFileDialog.SAVE;
if(fileDialog.showModal() == wxId.OK)
{
this.textCtrl.saveFile(fileDialog.path);
}
}
function OnFileExit()
{
this.close();
}
function CreateMenuBar(parent)
{
// Создаем строку меню
var menuBar = new wxMenuBar(parent);
// Создаем меню "Файл"
var fileMenu = new wxMenu;
// Добавляем в меню элементы
fileMenu.append(wxId.NEW, "New\tCtrl+N", "Create new file");
fileMenu.append(wxId.OPEN, "Open\tCtrl+O", "Open existing file");
fileMenu.appendSeparator();
fileMenu.append(wxId.SAVE, "Save\tCtrl+S", "Save file");
fileMenu.appendSeparator();
fileMenu.append(wxId.EXIT, "Exit\tAlt+F4", "Exit this application");
// Назначаем обработчики событий
fileMenu.actions[wxId.NEW] = OnFileNew;
fileMenu.actions[wxId.OPEN] = OnFileOpen;
fileMenu.actions[wxId.SAVE] = OnFileSave;
fileMenu.actions[wxId.EXIT] = OnFileExit;
// Добавляем меню в строку меню
menuBar.append(fileMenu, "File");
return menuBar;
}
// Функция создания главной формы
function CreateFrame()
{
// Создаем форму
var frame = new wxFrame(null, -1, "Minimal");
// Создаем строку меню с помощью функции CreateMenuBar()
frame.menuBar = CreateMenuBar();
// Создаем строку состояния с двумя панелями
frame.createStatusBar(2);
// Создаем главный сайзер
var mainSizer = new wxBoxSizer(wxOrientation.VERTICAL);
// Создаем текстовое поле
var textCtrl = new wxTextCtrl(frame, wxId.HIGHEST+1, "",
wxDefaultPosition, wxDefaultSize, wxTextCtrl.MULTILINE);
// Добавляем текстовое поле в сайзер
mainSizer.add(textCtrl, 1, wxStretch.EXPAND, 0);
// Кладем сайзер на форму
frame.sizer = mainSizer;
// Устанавливаем значение переменной textCtrl в главной форме
frame.textCtrl = textCtrl;
return frame;
}
// Инициализация приложения
function init()
{
// Создаем форму с помощью функции CreateFrame();
var frame = CreateFrame();
// Делаем форму вилимой
frame.visible = true;
// Делаем форму главной
wxTheApp.topWindow = frame;
return true;
}

Как видно из скриншота, приложение занимает 18 МБ памяти. Минимальное приложение занимало приблизительно 12 МБ. Эти 6 мегабайт разницы “съедает” поддержка Common Dialogs при первом обращении, а именно при открытии диалога открытия файла.
Кроме всего прочего, wxJS поддерживает работу с базами данных. Ниже приведен код примера, который выполняет соединение с базой данных SQLite, при необходимости, создает таблицы в базе данных, заполняет их данными и отображает содержимое таблиц.
database.js
// Открываем базу данных
var db = new sqlite.Database(script.root + "sample.db");
// Если база была открыта успешно...
if(db.opened)
{
print("Database opened successfully.\r\n");
// Хитрая проверка на наличие таблиц с помощью PRAGMA
var pragmaStmt = db.prepare("PRAGMA user_version");
var pragma = pragmaStmt.fetchArray();
if(pragma[0] == 0)
{
// Создаем таблицы в базе данных
print("Creating tables...\r\n");
print(db.exec("CREATE TABLE sample(id INTEGER PRIMARY KEY, somedata TEXT)"));
print("Inserting data...\r\n");
// Заполняем таблицы данными
print(db.exec("INSERT INTO sample(somedata) VALUES ('test 1')")+"\r\n");
print(db.exec("INSERT INTO sample(somedata) VALUES ('test 2')")+"\r\n");
// Устанавливаем флаг наличия таблиц
db.exec("PRAGMA user_version = 1");
}
// Получаем данные из таблицы
print("Fetching data...\r\n");
var stmt = db.prepare("SELECT * FROM sample");
// если получилось вытянуть данные...
if(stmt != null)
{
var row;
// Выводим все записи в консоль
while(row = stmt.fetchObject())
{
print(row.id + ": " + row.somedata + "\r\n");
}
}
else
{
print("Unable to fetch data.\r\n");
}
}
else
{
print("Error opening database.");
}
Ну вот, пока на этом все. Более подробно об API wxJavaScript можно почитать на официальном сайте.
6 Comments
Begemot
Yet another wxPython? 🙂
В чем глубинный смысл? какие преимущества? для чего он вообще нужен на десктопе? Тема не раскрыта:(
Вот в вебе возможно интересно, но помнится я смотрел сайт его – и так и не увидел не одного примера использования, расстроился и ушел 🙂
admin
Ммм? Ну вобще фраза “чем он лучше wxPython” из разряда “Кто сильнее, кит или слон?”. Он просто “другой”. Мне например нравится синтаксис, и кодинг на wxJS мне кажется более комфортным, но это ИМХО. А примеры использования. Ну то же самое что ты пишешь на C++, только компилить не надо. Плюс ко всему его можно использовать как скриптовый движок для своих приложений. Напишу еще об этом.
Т.е. если например тебе надо срочно наклепать какую-то утилиту “которая что-то делает” для собственных нужд, то для этого незачем иметь на машине компилятор. Я с собой wxJS на флешке таскаю. Он без установки работает
ЗЫ: В дистрибутиве есть гора примеров.
Begemot
ты сам конкретно что-то полезное для себя уже написал на нем?
“не машине на которой даже нет компилятора” ?:)
тоже самое что и с++ только компилить не надо кажется мне довольно спорным преимуществом – из проекта на с++ может выйти что-то полезно + можно использовать готовые наработки, тоже в принципе и с питоном, а “утилитка которая что-то для себя делает” на джава скрипт, такой и останется, по идеи.
Хотя может для небольших задач скриптов как раз то что надо. Но опять же новый язык учить 🙂
А вот как скриптовый язык это может быть интересным, но это небось толстый интерпретатор?
admin
Ммм? Вроде все интерпретаторы толстые, wxLua например тоже не маленький.
А по поводу “для себя” чего нормальное делал.. Когда-то делал адресную книгу на wxJS + SQLite, даже вроде пользовался какое-то время, потом не помню куда она делась 🙂 Может исходник еще смогу найти.
Я вроде где-то на wxForum’е видел описание какой-то неплохой фривары на wxJS, оно даже работало.
Begemot
поискал на форуме, про фривары на этом скрипте не нашел.:(
зато нашел упоминания про http://wxcode.sourceforge.net/components/wxscript/, но как-то ….
вообщем тема скриптов не раскрыта, можно сказать не паханая целина для новых постов:)
Кстати, по сабжу – только виндовс и убунту я так понял, мак отдыхает… еще один минус.
T-Rex
Я думаю поддержка мака не заявлена потому что автору собирать не на чем. Я по этой же причине тоже не делаю самплов под мак, мне другой человек собирает.
ЗЫ: Кстати под Windows 7 GUI модуль вываливается с ошибкой, по крайней мере без админской учетки.