Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Уроки и примеры по ЯП-у Vala  (Прочитано 12382 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн alsoijw

  • Автор темы
  • Старожил
  • *
  • Сообщений: 4099
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Управление памятью в Vala. Часть №0
« Ответ #15 : 06 Апрель 2016, 14:57:37 »
В Vala используется автоматическое управление памятью. Это значит что программисту не нужно думать о том, чтобы возвращать память в систему, когда объект больше не будет использоваться. Можно сравнить код на Vala и код на C++
Код: Vala
  1. void method() {
  2.     var a = new Node();
  3. }
Код: C++
  1. void method() {
  2.     auto a = new Node();
  3.     delete a; // если забыть написать данную строку, произойдёт утечка памяти
  4. }
Управление памятью основано на подсчёте количества ссылок. Когда создаётся переменная, количество ссылок равно 1. Когда одна переменная приравнивается к другой, количество ссылок инкрементируется. Когда какая-то переменная выходит из области видимости, количество ссылок декреметируется. Когда количество ссылок становится равно 0, то область памяти освобождается.
Код: Vala
  1. class Test : Object {}
  2.  
  3. void main() {
  4.         var a = new Test();
  5.         stdout.printf(@"$(a.ref_count)  "); //1
  6.         var b = a;
  7.         stdout.printf(@"$(a.ref_count)  "); //2
  8.         {
  9.                 var c = a;
  10.                 stdout.printf(@"$(a.ref_count)  "); //3
  11.         }
  12.         stdout.printf(@"$(a.ref_count)  "); //2
  13.         b = new Test();
  14.         stdout.printf(@"$(a.ref_count)  "); //1
  15. } //0
  16. // Переменная вышла из области видимости и память возращена системе
У данной системы есть достоинства и недостатки. Достоинства это хорошая скорость работы и простота реализации. Недостатки - всё ещё можно создать утечку памяти.
Код: Vala
  1. class Node : Object {
  2.         public Node prev;
  3.         public Node next;
  4.        
  5.         public Node (Node? prev = null) {
  6.                 this.prev = prev;
  7.                 if (prev != null) {
  8.                         prev.next = this;
  9.                 }
  10.         }
  11. }
  12.  
  13. void main() {
  14.         while (true) {
  15.                 var n1 = new Node ();
  16.                 var n2 = new Node (n1);
  17.                 Thread.usleep (1000); // Чтобы не нагружал цп на 100%
  18.         }
  19. }
В чём проблема? После выполнения строки var n2 = new Node (n1); На участок памяти на который указывает n1 есть две ссылки. Первая это n1. Вторая это n2.prev. Точно так же и на n2 - n2 и n1.next. После того как заканчивается очередная итерация, n1 и n2 уходят из обласи видимости, но по прежднему количество ссылок на эти области памяти не равно нулю. Учитываются ссылки на следующий и предыдущий элементы.  /-->
n1    n2
  <--/
Как боротся с такими утечками памяти? Для этого надо объявить класс так
Код: Vala
  1. class Node : Object {
  2.         public weak Node prev;
  3.         public Node next;
  4.        
  5.         public Node (Node? prev = null) {
  6.                 this.prev = prev;
  7.                 if (prev != null) {
  8.                         prev.next = this;
  9.                 }
  10.         }
  11. }
При объявлении переменной с ключевым словом weak образуется слабая ссылка. Это означает что приравнивание такой перменной не увеличит счётчик ссылок.
Код: Vala
  1. class Test : Object {}
  2.  
  3. void main() {
  4.         var a = new Test();
  5.         stdout.printf(@"$(a.ref_count)  "); // 1
  6.         weak Test b = a;
  7.         stdout.printf(@"$(a.ref_count)  "); // 1
  8. }
А что произойдёт если попытатся приравнять слабой ссылке новый объект?
Код: Vala
  1. weak Test b = new Test();
Компилятор укажет на ошибку.error: Invalid assignment from owned expression to unowned variableЕсли бы у нас была бы возможность присвоить новый объект слабой ссылке, то тогда он сразу же бы удалялся. Возникла бы логическая ошибка.
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

Оффлайн alsoijw

  • Автор темы
  • Старожил
  • *
  • Сообщений: 4099
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Об устройстве окон в Gtk
« Ответ #16 : 11 Декабрь 2016, 01:13:12 »
Спустя некоторое время возвращаюсь к теме примеров и уроков по языку Vala.
Для создания графического интерфейса многие программисты используют Gtk.
Gtk окна састоят из самых разных виджетов. И переключатели и кнопик и окна - всё еаследуется от этого класса. В Gtk как правило не надо явно указывать в какой точке должен находится тот или иной виджет и какого он размера. Достаточно просто описать как виджеты связаны друг с другом. Можно вспомнить hello world
Код: Vala
  1. using Gtk;
  2.  
  3. int main (string[] args) {
  4.     Gtk.init (ref args);
  5.  
  6.     var window = new Window (); // создаём окно
  7.     window.title = "First GTK+ Program";
  8.     window.border_width = 10;
  9.     window.window_position = WindowPosition.CENTER;
  10.     window.set_default_size (350, 70);
  11.     window.destroy.connect (Gtk.main_quit);
  12.  
  13.     var button = new Button.with_label ("Click me!");
  14.     button.clicked.connect (() => {
  15.         button.label = "Thank you";
  16.     });
  17.  
  18.     window.add (button); // указываем что внутри окна должна быть кнопка
  19.     window.show_all ();
  20.  
  21.     Gtk.main ();
  22.     return 0;
  23. }
Класс Window унаследован от абстрактного класса Bin, который может содержать только один виджет. А что, если нам нужно добавить в окно несколько кнопок? Рассмотрим следующий пример.
Код: Vala
  1. spin_box = new SpinButton.with_range (0, 130, 1); // создаём несколько виджетов
  2. slider = new Scale.with_range (Orientation.HORIZONTAL, 0, 130, 1);
  3. var hbox = new Box (Orientation.HORIZONTAL, 5); // создаём контейнер спосбный хранить несколько виджетов
  4. hbox.add (spin_box); // добавляем виджеты в контейнер
  5. hbox.add (slider);
  6. add (hbox); // добавляем контейнер в окно
Существует несколько контейеров. К примеру Box позволяет расположить элеметы управления один за другим строго по горизонтали либо по вертикали, а FlowBox позволяет создать нечто вроде таблицы, в которой виджеты будут переносится на новую строку, если им не хватает места. Вам не нужно об этом волноватся об этом, Gtk сделает это самостоятельно.
Как быть если какой-то виджет не влезает на экран? Специально для таких целей существует ScrolledWindow. Вот пример.
Иногда возникает ситуация, когда нужно поместить какой-то достаточно длинный текст на кнопку или метку. В этом случае возникает проблема - невозможно уменьшить размер окна, если какой то виджет не влазит. Как быть в этом случае? У Label есть нужеое нам свойство. А как быть с кнопкой? Возможно, вы уже обратили внимание, что кнопка унаследована от Bin. Это означает, что кнопка содержит внутри себя виджет. Но как узнать какого он типа? У Bin есть один единственный метод, позволяющий получить этот виджет. А взяв виджет можно узнать его тип
Код: Vala
  1. using Gtk;
  2.  
  3. void main(string[] args) {
  4.         Gtk.init(ref args);
  5.         var b = new Button.with_label("Click me (0)");
  6.         stdout.printf(@"$(b.get_child().get_type().name())\n");
  7. }
Собирав и запустив полуаем результат
GtkLabelЗначит точно так же можно уменьшить размер кнопки -
Код: Vala
  1. ((Gtk.Label)button.get_child()).ellipsize = Pango.EllipsizeMode.END;
Спасибо за внимание.
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

 

Страница сгенерирована за 0.159 секунд. Запросов: 23.