Categories: wxJavaScript

wxJavaScript – Кросс-платформенный скриптинг десктопных приложений. Знакомство

Давно уже хотел написать по поводу 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 можно почитать на официальном сайте.

T-Rex

View Comments

  • Yet another wxPython? :)

    В чем глубинный смысл? какие преимущества? для чего он вообще нужен на десктопе? Тема не раскрыта:(

    Вот в вебе возможно интересно, но помнится я смотрел сайт его - и так и не увидел не одного примера использования, расстроился и ушел :)

    • Ммм? Ну вобще фраза "чем он лучше wxPython" из разряда "Кто сильнее, кит или слон?". Он просто "другой". Мне например нравится синтаксис, и кодинг на wxJS мне кажется более комфортным, но это ИМХО. А примеры использования. Ну то же самое что ты пишешь на C++, только компилить не надо. Плюс ко всему его можно использовать как скриптовый движок для своих приложений. Напишу еще об этом.
      Т.е. если например тебе надо срочно наклепать какую-то утилиту "которая что-то делает" для собственных нужд, то для этого незачем иметь на машине компилятор. Я с собой wxJS на флешке таскаю. Он без установки работает

      ЗЫ: В дистрибутиве есть гора примеров.

  • ты сам конкретно что-то полезное для себя уже написал на нем?
    "не машине на которой даже нет компилятора" ?:)

    тоже самое что и с++ только компилить не надо кажется мне довольно спорным преимуществом - из проекта на с++ может выйти что-то полезно + можно использовать готовые наработки, тоже в принципе и с питоном, а "утилитка которая что-то для себя делает" на джава скрипт, такой и останется, по идеи.

    Хотя может для небольших задач скриптов как раз то что надо. Но опять же новый язык учить :)

    А вот как скриптовый язык это может быть интересным, но это небось толстый интерпретатор?

    • Ммм? Вроде все интерпретаторы толстые, wxLua например тоже не маленький.
      А по поводу "для себя" чего нормальное делал.. Когда-то делал адресную книгу на wxJS + SQLite, даже вроде пользовался какое-то время, потом не помню куда она делась :) Может исходник еще смогу найти.
      Я вроде где-то на wxForum'е видел описание какой-то неплохой фривары на wxJS, оно даже работало.

  • поискал на форуме, про фривары на этом скрипте не нашел.:(
    зато нашел упоминания про http://wxcode.sourceforge.net/components/wxscript/, но как-то ....

    вообщем тема скриптов не раскрыта, можно сказать не паханая целина для новых постов:)

    Кстати, по сабжу - только виндовс и убунту я так понял, мак отдыхает... еще один минус.

    • Я думаю поддержка мака не заявлена потому что автору собирать не на чем. Я по этой же причине тоже не делаю самплов под мак, мне другой человек собирает.

      ЗЫ: Кстати под Windows 7 GUI модуль вываливается с ошибкой, по крайней мере без админской учетки.

Share
Published by
T-Rex

Recent Posts

Разработка кроссплатформенных модульных приложений на C++ с библиотекой wxWidgets

Введение Уже долгое время не пишу статьи о разработке, хотя сам процесс написания мне очень…

11 years ago

wxWidgets App With Plugins (Windows/Linux/Mac) – Sample Source Code

I can see that there is still a lot of topics at wxWidgets forums related…

11 years ago

wxToolBox is Now Open-Source!

I've just published the source code of wxToolBox component and a couple of sample apps at…

11 years ago

Microsoft Kinect Helper Library and Sample for wxWidgets

Microsoft released their Kinect SDK several days ago. So, for those wxWidgets developers who are…

13 years ago

wxJSON 1.1.0 Released

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to…

15 years ago

wxRuby. Оно даже работает!

Вдохновленнный читаемой нынче книгой My Job Went to India: 52 Ways to Save Your Job…

15 years ago