Подробности в документации и гифки

This commit is contained in:
Igor Timofeev 2017-08-08 21:13:45 +03:00
parent ff3abf8679
commit ede07256fb

View File

@ -29,12 +29,12 @@
| [GUI.textBox](#guitextboxx-y-width-height-backgroundcolor-textcolor-lines-currentline-horizontaloffset-verticaloffset-table-textbox) |
| [GUI.codeView](#guicodeview-x-y-width-height-lines-fromsymbol-fromline-maximumlinelength-selections-highlights-highlightluasyntax-indentationwidth--table-codeview) |
| [GUI.chart](#guichart-x-y-width-height-axiscolor-axisvaluecolor-axishelperscolor-chartcolor-xaxisvalueinterval-yaxisvalueinterval-xaxispostfix-yaxispostfix-fillchartarea-values--table-chart) |
| [Практические примеры](#Практический-пример-1) |
| [    Практический пример #1](#Практический-пример-1) |
| [    Практический пример #2](#Практический-пример-2) |
| [    Практический пример #3](#Практический-пример-3) |
| [    Практический пример #4](#Практический-пример-4) |
| [    Практический пример #5](#Практический-пример-5) |
| [Практические примеры](#Практические-примеры) |
| [    Пример #1: Кнопочки](#Пример-1-Кнопочки) |
| [    Пример #2: Окно авторизации](#Пример-2-Окно-авторизации) |
| [    Пример #3: Создание собственного виджета](#Пример-3-Создание-собственного-виджета) |
| [    Пример #4: Углубленная работа с Layout](#Пример-4-Углубленная-работа-с-Layout) |
| [    Пример #5: Анимация собственного виджета](#Пример-5-Анимация-собственного-виджета) |
О библиотеке
@ -1169,16 +1169,22 @@ mainContainer:startEventHandling()
![enter image description here](http://i91.fastpic.ru/big/2017/0402/5b/66ff353492298f6a0c9b01c0fc8a525b.png)
Практический пример #1
Практические примеры
======
Ниже приведены подробно прокомментированные участки кода и иллюстрации, позволяющие во всех деталях разобраться с особенностями библиотеки. Не стесняйтесь изменять их под свой вкус и цвет.
Пример #1: Кнопочки
======
В качестве стартового примера возьмем простейшую задачу: расположим на экране 5 кнопок по вертикали и заставим их показывать окно с порядковым номером этой кнопки при нажатии на нее. Напишем следующий код:
Возьмем простейшую задачу: расположим на экране 5 кнопок по вертикали и заставим их показывать окно с порядковым номером этой кнопки при нажатии на нее. Напишем следующий код:
```lua
-- Подключаем необходимые библиотеки
local buffer = require("doubleBuffering")
local GUI = require("GUI")
------------------------------------------------------------------------------------------
-- Создаем полноэкранный контейнер
local mainContainer = GUI.fullScreenContainer()
-- Добавляем на окно темно-серую панель по всей его ширине и высоте
@ -1191,9 +1197,12 @@ for i = 1, 5 do
mainContainer:addChild(GUI.button(2, y, 30, 3, 0xEEEEEE, 0x2D2D2D, 0x666666, 0xEEEEEE, "This is button " .. i)).onTouch = function()
GUI.error("You've pressed button " .. i .. "!")
end
y = y + 4
end
------------------------------------------------------------------------------------------
-- Отрисовываем содержимое окно
mainContainer:draw()
-- Отрисовываем содержимое экранного буфера
@ -1203,76 +1212,105 @@ mainContainer:startEventHandling()
```
При нажатии на любую из созданных кнопок будет показываться дебаг-окно с информацией, указанной в методе *.onTouch*:
![enter image description here](http://i90.fastpic.ru/big/2017/0402/32/90656de1b96b157284fb21e2467d9632.png)
![enter image description here](http://i.imgur.com/GChy5UA.gif)
![enter image description here](http://i91.fastpic.ru/big/2017/0402/c3/e02d02fb39a28dd17220b535e59292c3.png)
Практический пример #2
Пример #2: Окно авторизации
======
Поскольку в моде OpenComputers имеется интернет-плата, я написал небольшой клиент для работы с VK.com. Разумеется, для этого необходимо реализовать авторизацию на серверах, вводя свой e-mail/номер телефона и пароль к аккаунту. В качестве тренировки привожу часть кода, отвечающую за это.
Поскольку в моде OpenComputers имеется интернет-плата, я написал небольшой клиент для работы с VK.com. Разумеется, для этого необходимо реализовать авторизацию на серверах, вводя свой e-mail/номер телефона и пароль к аккаунту. В качестве тренировки привожу часть кода, отвечающую за это:
```lua
-- Подключаем библиотеки
local image = require("image")
local buffer = require("doubleBuffering")
local GUI = require("GUI")
------------------------------------------------------------------------------------------
-- Задаем базовые параметры - минимальную длину пароля и регулярное выражение для проверки валидности адреса почты
local minimumPasswordLength = 2
local emailRegex = "%w+@%w+%.%w+"
-- Для примера также задаем "корректные" данные пользователя
local userEmail = "cyka@gmail.com"
local userPassword = "1234567"
------------------------------------------------------------------------------------------
-- Создаем контейнер с синей фоновой панелью
local mainContainer = GUI.fullScreenContainer()
mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x002440))
-- Добавляем в него layout с размерностью сетки 1x1
local layout = mainContainer:addChild(GUI.layout(1, 1, mainContainer.width, mainContainer.height, 1, 1))
-- Указываем размеры полей ввода текста и кнопок
local elementWidth, elementHeight = 40, 3
local x, y = math.floor(mainContainer.width / 2 - elementWidth / 2), math.floor(mainContainer.height / 2) - 2
-- Добавляем в layout поле для ввода почтового адреса
local emailInputField = layout:addChild(GUI.inputField(1, 1, 40, 3, 0xEEEEEE, 0x555555, 0x888888, 0xEEEEEE, 0x262626, nil, "E-mail", false, nil, nil, nil))
-- Добавляем красный текстовый лейбл, показывающийся только в том случае, когда адрес почты невалиден
local invalidEmailLabel = layout:addChild(GUI.label(1, 1, mainContainer.width, 1, 0xFF5555, "Incorrect e-mail")):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top)
invalidEmailLabel.hidden = true
-- Загружаем и добавляем изображение логотипа "нашей компании"
local logotype = image.load("/MineOS/Applications/VK.app/Resources/VKLogo.pic")
mainContainer:addChild(GUI.image(math.floor(mainContainer.width / 2 - image.getWidth(logotype) / 2) - 2, y - image.getHeight(logotype) - 1, logotype)); y = y + 2
-- Добавляем аналогичное текстовое поле с лейблом для ввода пароля
local passwordInputField = layout:addChild(GUI.inputField(1, 1, 40, 3, 0xEEEEEE, 0x555555, 0x888888, 0xEEEEEE, 0x262626, nil, "Password", false, "*", nil, nil))
local invalidPasswordLabel = layout:addChild(GUI.label(1, 1, mainContainer.width, 1, 0xFF5555, "Password is too short")):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top)
invalidPasswordLabel.hidden = true
-- Добавляем кнопку, ползволяющую осуществлять авторизацию
local loginButton = layout:addChild(GUI.button(1, 1, 40, 3, 0x3392FF, 0xEEEEEE, 0xEEEEEE, 0x3392FF, "Login"))
-- По умолчанию кнопка имеет неактивное состояние, а также серый цвет
loginButton.disabled = true
loginButton.colors.disabled.background = 0xAAAAAA
loginButton.colors.disabled.text = 0xDDDDDD
-- При нажатии на кнопку логина идет сверка введенных данных с переменными выше, и выводится дебаг-сообщение
loginButton.onTouch = function()
GUI.error(emailInputField.text == userEmail and passwordInputField.text == userPassword and "Login successfull" or "Login failed")
end
-- Создаем две переменных, в которых будут храниться состояния валидности введенных данных
local emailValid, passwordValid
-- Данная функция будет вызываться ниже после обращения к одному из текстовых полей, она необходима
-- для контроля активности кнопки логина
local function checkLoginButton()
loginButton.disabled = not emailValid or not passwordValid
-- Создаем поле для ввода адреса почты
local emailTextBox = mainContainer:addChild(GUI.inputTextBox(x, y, elementWidth, elementHeight, 0xEEEEEE, 0x777777, 0xEEEEEE, 0x2D2D2D, nil, "E-mail", false, nil, nil, nil))
-- Создаем красный текстовый лейбл, показывающийся только в том случае, когда адрес почты неверен
local invalidEmailLabel = mainContainer:addChild(GUI.label(emailTextBox.localPosition.x + emailTextBox.width + 2, y + 1, mainContainer.width, 1, 0xFF5555, "Invalid e-mail")); y = y + elementHeight + 1
invalidEmailLabel.isHidden = true
-- Создаем callback-функцию, вызывающуюся после ввода текста и проверяющую корректность введенного адреса
emailTextBox.onInputFinished = function(text)
invalidEmailLabel.isHidden = text:match("%w+@%w+%.%w+") and true or false
mainContainer:draw()
buffer.draw()
end
-- Создаем поле для ввода пароля
mainContainer:addChild(GUI.inputTextBox(x, y, elementWidth, elementHeight, 0xEEEEEE, 0x777777, 0xEEEEEE, 0x2D2D2D, nil, "Password", false, "*", nil, nil)); y = y + elementHeight + 1
-- Добавляем малоприметную кнопку для закрытия программы
mainContainer:addChild(GUI.button(mainContainer.width, 1, 1, 1, 0x002440, 0xEEEEEE, 0x002440, 0xAAAAAA, "X")).onTouch = function()
-- Создаем callback-функцию, вызывающуюся после ввода текста и проверяющую корректность введенного адреса
emailInputField.onInputFinished = function()
emailValid = emailInputField.text and emailInputField.text:match(emailRegex)
invalidEmailLabel.hidden = emailValid
checkLoginButton()
end
-- Аналогично поступаем с полем для ввода пароля
passwordInputField.onInputFinished = function()
passwordValid = passwordInputField.text and passwordInputField.text:len() > minimumPasswordLength
invalidPasswordLabel.hidden = passwordValid
checkLoginButton()
end
-- Добавляем заодно кнопку для закрытия программы
layout:addChild(GUI.button(1, 1, 40, 3, 0x336DBF, 0xEEEEEE, 0xEEEEEE, 0x336DBF, "Exit")).onTouch = function()
mainContainer:stopEventHandling()
buffer.clear(0x0)
buffer.draw(true)
end
-- Добавляем кнопку для логина
mainContainer:addChild(GUI.button(x, y, elementWidth, elementHeight, 0x666DFF, 0xEEEEEE, 0xEEEEEE, 0x666DFF, "Login")).onTouch = function()
-- Код, выполняемый при успешном логине
end
------------------------------------------------------------------------------------------
mainContainer:draw()
buffer.draw(true)
mainContainer:startEventHandling()
```
Результат:
![enter image description here](http://i.imgur.com/PT0AUGR.png?1)
![enter image description here](http://i.imgur.com/CWuCLop.gif)
![enter image description here](http://i.imgur.com/dphuFtb.png?1)
![enter image description here](http://i.imgur.com/LXfsT0o.png?1)
Практический пример #3
Пример #3: Создание собственного виджета
======
Для демонстрации возможностей библиотеки предлагаю создать собственный виджет с нуля. К примеру, панель, реагирующую на клики мыши, позволяющую рисовать на ней произвольным цветом по аналогии со школьной доской.
Одной из важнейших особенностей библиотеки является простота создания виджетов с нуля. К примеру, давайте сделаем панель, реагирующую на клики мыши и позволяющую рисовать на ней произвольным цветом по аналогии со школьной доской.
```lua
local buffer = require("doubleBuffering")
@ -1296,6 +1334,21 @@ local function myWidgetEventHandler(mainContainer, object, eventData)
end
end
-- Аналогичным образом поступим с функцией отрисовки виджета, храня ее в единственном экземпляре в памяти
local function myWidgetDraw(object)
-- Рисуем подложку цветом фона виджета
buffer.square(object.x, object.y, object.width, object.height, object.colors.background, 0x0, " ")
-- Перебираем пиксельную карту, отрисовывая соответствующие пиксели в экранный буфер
for y = 1, object.height do
for x = 1, object.width do
if object.pixels[y] and object.pixels[y][x] then
buffer.set(object.x + x - 1, object.y + y - 1, object.colors.paint, 0x0, " ")
end
end
end
end
-- Создаем метод, возвращающий наш виджет
local function createMyWidget(x, y, width, height, backgroundColor, paintColor)
-- Наследуемся от GUI.object, дополняем его параметрами цветов и пиксельной карты
@ -1303,56 +1356,39 @@ local function createMyWidget(x, y, width, height, backgroundColor, paintColor)
object.colors = {background = backgroundColor, paint = paintColor}
object.pixels = {}
-- Реализуем метод отрисовки виджета
object.draw = function(object)
-- Рисуем подложку цветом фона виджета
buffer.square(object.x, object.y, object.width, object.height, object.colors.background, 0x0, " ")
-- Перебираем пиксельную карту, отрисовывая соответствующие пиксели в экранный буфер
for y = 1, object.height do
for x = 1, object.width do
if object.pixels[y] and object.pixels[y][x] then
buffer.set(object.x + x - 1, object.y + y - 1, object.colors.paint, 0x0, " ")
end
end
end
end
-- Реализуем методы отрисовки виджета и обработки событий
object.draw = myWidgetDraw
object.eventHandler = myWidgetEventHandler
return object
end
---------------------------------------------------------------------
-- Добавляем темно-серую панель в контейнер
mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x2D2D2D))
-- Создаем экземпляр виджета-рисовалки и добавляем его в контейнер
mainContainer:addChild(createMyWidget(2, 2, 32, 16, 0x3C3C3C, 0xEEEEEEE))
-- Создаем 9 экземпляров виджета-рисовалки и добавляем их в контейнер
local x, y, width, height = 2, 2, 30, 15
for j = 1, 3 do
for i = 1, 3 do
mainContainer:addChild(createMyWidget(x, y, width, height, 0x3C3C3C, 0xEEEEEEE))
x = x + width + 2
end
x, y = 2, y + height + 1
end
mainContainer:draw()
buffer.draw(true)
mainContainer:startEventHandling()
```
---------------------------------------------------------------------
При нажатии на левую кнопку мыши в нашем виджете устанавливается пиксель указанного цвета, а на правую - удаляется.
![enter image description here](http://i89.fastpic.ru/big/2017/0402/fd/be80c13085824bebf68f64a329e226fd.png)
Результат:
Для разнообразия модифицируем код, создав несколько виджетов со случайными цветами:
```lua
local x = 2
for i = 1, 5 do
mainContainer:addChild(createMyWidget(x, 2, 32, 16, math.random(0x0, 0xFFFFFF), math.random(0x0, 0xFFFFFF)))
x = x + 34
end
```
В результате получаем 5 индивидуальных экземпляров виджета рисования:
![enter image description here](http://i90.fastpic.ru/big/2017/0402/96/96aba372bdb3c1e61007170132f00096.png)
![enter image description here](http://i.imgur.com/SodpPQo.gif)
Как видите, в создании собственных виджетов нет совершенно ничего сложного, главное - обладать информацией по наиболее эффективной работе с библиотекой.
Практический пример #4
Пример #4: Углубленная работа с Layout
======
Предлагаю немного попрактиковаться в использовании layout. В качестве примера создадим контейнер-окно с четырьмя кнопками, изменяющими его размеры. Вы убедитесь, что нам ни разу не придется вручную считать координаты.
@ -1426,7 +1462,7 @@ mainContainer:startEventHandling()
![Imgur](http://i.imgur.com/c8Ks91w.gif)
Практический пример #5
Пример #5: Анимация собственного виджета
======
Для демонстрации работы с анимациями привожу исходный код, позволяющий с абсолютного нуля создать виджет **switch** и добавить к нему анимацию перемещения.