Перейти к содержимому
Zer0Galaxy

"Лёгкая" библиотека GUI

Рекомендуемые сообщения

На элементы форм моих нервов не хватило. Весь день занимался интимными делами с своей сетью, пытался заставить её разбивать пакеты более 8 килобайт на несколько, со всеми вытекающими. Так что единственное, что я сделал с библиотекой - дописал одну строчку, позволяющую задать функцию, которая будет вызвана после отрисовки элемента.

function TComponent:draw()
  if self.parent then self.X=self.parent.X+self.left-1 self.Y=self.parent.Y+self.top-1
  else self.X=self.left self.Y=self.top end
  gpu.setBackground(self.color)
  gpu.setForeground(self.fontColor)
  local brd=nil
  if self.border==1 then brd={"┌","─","┐","└","│","┘"}
  elseif self.border==2 then brd={"╔","═","╗","╚","║","╝"}
  end
  if brd then
    gpu.set(self.X,self.Y, brd[1]..string.rep(brd[2],self.W-2)..brd[3])
    for i=self.Y+1,self.Y+self.H-2 do
      gpu.set(self.X,i, brd[5]..string.rep(" ",self.W-2)..brd[5])
    end
    gpu.set(self.X,self.Y+self.H-1, brd[4]..string.rep(brd[2],self.W-2)..brd[6])
  else gpu.fill(self.X,self.Y,self.W,self.H," ") end
  self:paint()
  if self.elements then
    for i=1,#self.elements do
      if self.elements[i].visible then self.elements[i]:draw() end
	end
  end
  if self.onDraw then self.onDraw() end -- Вот эта строчка
end

Остальным займусь, когда приду в себя.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@AlexCatze, не могу представить зачем нужно событие перерисовки элемента. Ну допустим, я хочу просто посчитать сколько раз была отрисована та или иная кнопка. Лучше сделать это не влезая в метод TComponent:draw, поскольку TComponent:draw вызывается абсолютно для всех компонентов, а меня интересует только одна кнопка. Это делается при помощи магии ООП, называемой полиморфизм. Вот пример кода:

Btn1=Form1:addButton(65,21,"Кнопка") -- создаем кнопку
Cnt1=Form1:addLabel(10,5,0) -- создадим метку со счетчиком событий

function Btn1.onDraw()        -- определяем событие onDraw для кнопки Btn1,
  Cnt1.caption=Cnt1.caption+1 -- которое увеличивает счетчик
  Cnt1:redraw()               -- и перерисовывает метку
end

function Btn1:draw()          -- переопределяем метод draw для кнопки Btn1, в котором
  TButton.draw(self)          -- вызываем родительский метод
  if self.onDraw then self.onDraw() end -- и если надо, обработчик события onDraw
end

В этом случае выполнять проверку if self.onDraw не обязательно, поскольку переопределенный метод draw работает только для кнопки Btn1. А метод TComponent:draw остается без изменений.

Но поковыряться в библиотеке forms таки придется. Дело в том, что объект TButton является локальным и недоступен во внешних модулях. 

Просто убери слово local в этой строке:

------------------Button----------------
local TButton=setmetatable({W=10, H=1, color=0x606060, type=function() return "Button" end},TComponent)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 28.02.2021 в 14:12, Zer0Galaxy сказал:

TButton.draw(self) -- вызываем родительский метод

А можешь сделать так,чтобы у экземпляров кнопок было поле super, содержащее базовую таблицу? Это бы уменьшило вероятность ошибки и позволило бы писать более обобщенный код(не зависящий от конкретного базового класса)

Изменено пользователем hohserg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@hohserg, а что должна содержать базовая таблица? Что ты имеешь в виду под "более обобщенным кодом"? Приведи пример, пожалуйста.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Щас можно написать че-то вроде

function Btn1:draw()
  TButton.draw(self) -- вызываем родительский метод
end

Насколько я понимаю, с точки зрения семантики это одно и тоже что и отсутствие переопределения

В коде выше для переопределения метода у Btn1 нужно знать, экземпляр какого класса является Btn1.

Допустим, мы хотим переопределять методы произвольных экземпляров произвольных классов. Че-то вроде

function addCallback(formElement, methodName, callback)
  formElement[methodName] = function(self, ...)
    baseClass[methodName](self, ...) --где взять значение baseClass, если formElement - экземпляр проивзольного класса формочек?
    callback(self)
  end
end

Если бы self содержал в себе ссылку на базовый класс, это можно было бы решить так:

function addCallback(formElement, methodName, callback)
  formElement[methodName] = function(self, ...)
    self.super[methodName](self, ...)
    callback(self)
  end
end

 

Изменено пользователем hohserg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кажется понял о чем ты. Нужно дать возможность получать доступ к родительскому объекту. В принципе, этот доступ есть через метатаблицу:

getmetatable(self).draw(self)      -- вызываем родительский метод

Коряво, конечно. Нужно будет подумать над чем-то вроде:

self.inherited:draw()

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Как правильно завершить приложение с формами? Попробовал 

forms.stop()
require("term").clear()
os.execute("cls")

В итоге экран остается залит цветом форм

~~~

Сделал через кастомное сохранение цвета в начале и восстановление в конце

Изменено пользователем hohserg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@hohserg, очистку экрана можно ставить не после forms.stop(), а после forms.run(). Стопов может быть много, а run только один.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

У меня это финальная форма, после которой нужно выйти из программы. И хотелось ,чтобы после программы экран не содержал остатков рендера форм. Проблема в том, что openos восстанавливает цвет когда-то позже моего require("term").clear() и экран очищается с использованием цветов форм.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

В 24.03.2021 в 09:44, Zer0Galaxy сказал:

Стопов может быть много, а run только один.

Правильно ли я понимаю, что вызов stop вернет управление в точку после вызова run?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
4 часа назад, hohserg сказал:

 

Правильно ли я понимаю, что вызов stop вернет управление в точку после вызова run?

Совершенно верно. Дело в том, что вся работа библиотеки выполняется внутри функции run, а stop просто прерывает это выполнение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте, я хочу сделать авторизацию через PIM но после столкнулся с проблемой, что либо не меняется форма после наступания, либо после того как ушел с PIM.

Скрытый текст


while true do
    e, nick, uuid, adr  = event.pull('player_off')
    Form1:setActive()
end

while true do
    e, nick, uuid, adr  = event.pull('player_on')
    Form2:setActive()
end

forms.run(Form1)

 

Изменено пользователем bes_zensuri1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@bes_zensuri1, в GUI Forms обработку событий следует выполнять при помощи компонента Event.

EventOn=Form1:addEvent('player_on', function() Form2:setActive() end)
EventOff=Form2:addEvent('player_off', function() Form1:setActive() end)
forms.run(Form1)

В том же коде, который привел ты мы сразу попадаем в бесконечный цикл while true do. Если мы каким то чудом из него выйдем, то тут же попадем во второй. И только потом запустится GUI, но циклы, обрабатывающие события уже не работают:(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 Cпасибо, сейчас сделал кнопку и как бы я функцию не ставил, не хочет активироваться кнопка

Скрытый текст

local function stop()
forms.stop()
end

-----------------------------------------------------------------------------------------

Button1=Form2:addButton(6,14,"ВЫЙТИ", stop)
Button1.W = 15
Button1.H = 3
Button1.border = 1
Button1.color = 0x303030
Button1.fontColor = 0x4cb01e

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

Что бы кнопка работала, она должна находиться на активной форме. Убедись, что Form2 активна.

2 часа назад, bes_zensuri1 сказал:

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

Функция-обработчик нажатия на кнопку принимает два параметра: указатель на кнопку и имя игрока, нажавшего ее

function onClick(self,name)
  -- name - имя игрока
end

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, Zer0Galaxy сказал:

Что бы кнопка работала, она должна находиться на активной форме. Убедись, что Form2 активна

Так у меня Form2 и кнопки вместе появляются, когда она активной становится.

Скрытый текст

forms=require("forms")
require("component").gpu.setResolution(80, 25)
local lUser = ("bes_zensuri") 
money = 1000
local computer = require("computer")
local component = require("component")
local event=require("event")
local pim = component.proxy("89416d95-d129-4b4e-b3f1-51672446e900")
local me = component.proxy("c407cada-c80d-441d-933e-f78faa413262")
logUser = pim.getInventoryName()
local color = {
    pattern = "%[0x(%x%x%x%x%x%x)]",
    background = 0x000000,
    pim = 0x46c8e3,
 
    gray = 0x303030,
    lightGray = 0x999999,
    blackGray = 0x1a1a1a,
    lime = 0x68f029,
    blackLime = 0x4cb01e,
    orange = 0xf2b233,
    blackOrange = 0xc49029,
    blue = 0x4260f5,
    blackBlue = 0x273ba1,
    red = 0xff0000
}

local me_side = "DOWN"
local pim_side = "UP"
local items = {}
local emLost = 0
local ironLost = 0
local fileName = "items.txt"
 -----------------------------------------------------------------------

Form1=forms.addForm()
Form1.border = 2
Form1.W=80
Form1.H=25
Frame1=Form1:addFrame(27.5,7,0)
Frame1.W = 28
Frame1.H = 14
Frame1.color = 0x68f029
Frame2=Form1:addFrame(29,8,0)
Frame2.W = 24
Frame2.H = 12
Frame2.color = 0x999999
Label1=Form1:addLabel(27,5,"Встаньте на PIM, чтобы войти")
Label1.centered = true 
Label1.fontColor = 0x4cb01e
Label2=Form1:addLabel(26.5,3," Добро пожаловать в PIMcasino")
Label2.fontColor = 0x4cb01e
Label2.centered = true
Label3=Form1:addLabel(20,23,"Разработал ReiVanSTR, доработал bes_zensuri")
Label3.centered = true
Label3.fontColor = 0xf2b233

---------------------------------------------------------------------------
Form2=forms.addForm()
Form2.border = 0
Form2.W=80
Form2.H=25
Form2.color= 0x303030
Frame3=Form2:addFrame(1,1,1)
Frame3.H=25
Frame3.W=25
Frame3.color= 0x1a1a1a
Frame4=Form2:addFrame(26,1,1)
Frame4.H=25
Frame4.W=55
Frame4.color= 0x1a1a1a
Label4=Frame4:addLabel(15,3,"ПРИВЕТСТВУЕМ ... !")
Label4.color= 0x1a1a1a
Label4.fontColor = 0xf2b233
Label5=Frame3:addLabel(2,3," ВАШ БАЛАНС: "..money.."$")
Label5.color= 0x1a1a1a
Label5.fontColor = 0xf2b233
Label6=Frame3:addLabel(2,5," СТОИМОСТЬ ИГРЫ:")
Label6.color= 0x1a1a1a
Label6.fontColor = 0xf2b233
Label7=Frame3:addLabel(2,7," ОДНА ПОПЫТКА - 1$")
Label7.color= 0x1a1a1a
Label7.fontColor = 0xf2b233
Label8=Frame3:addLabel(2,9," 1$ = 3 ЖБ")
Label8.color= 0x1a1a1a
Label8.fontColor = 0xf2b233
Label9=Frame3:addLabel(2,11," 1$ = 1 ЭМ")
Label9.color= 0x1a1a1a
Label9.fontColor = 0xf2b233
Frame5=Form2:addFrame(30,5,1)
Frame5.H=17
Frame5.W=47
Frame5.color= 0x000000
Label10=Frame4:addLabel(52,13,"<<")
Label10.color= 0x1a1a1a
Label10.fontColor = 0x999999
Label11=Frame4:addLabel(3,13,">>")
Label11.color= 0x1a1a1a
Label11.fontColor = 0x999999
-----------------------------------------------------------------------------------------

WinLabel19=Frame5:addLabel(18,9,"Драконий посох")
WinLabel19.fontColor = 0xff0000
WinLabel19.centered = true 

-----------------------------------------------------------------------------------------
function login()
    while true do
        e, nick, uuid, adr  = event.pull()
        if e == 'player_on' then
                Label4.caption = "ПРИВЕТСТВУЕМ, "..nick.." !"
                Form2:setActive() 
        elseif e == 'player_off' then
            Form1:setActive() 
        end
    end
end


function onClick(self,name)
        Form3:setActive()    
end

-----------------------------------------------------------------------------------------

Button1=Form2:addButton(6,14,"ПОПОЛНИТЬ", onClick)
Button1.W = 15
Button1.H = 3
Button1.border = 1
Button1.color = 0x303030
Button1.fontColor = 0x4cb01e
Button2=Form2:addButton(6,18,"ПРИЗЫ", onClick)
Button2.W = 15
Button2.H = 3
Button2.border = 1
Button2.color = 0x303030
Button2.fontColor = 0x4cb01e
Button3=Form2:addButton(6,22,"ПОМОЩЬ", onClick)
Button3.W = 15
Button3.H = 3
Button3.border = 1
Button3.color = 0x303030
Button3.fontColor = 0x4cb01e
Button4=Form2:addButton(38,22,"НАЖМИТЕ, ЧТОБЫ НАЧАТЬ ИГРАТЬ", onClick)
Button4.W = 30
Button4.H = 3
Button4.border = 1
Button4.color = 0x303030
Button4.fontColor = 0x4cb01e

---------------------------------------------------------------------------
Form3=forms.addForm()
Form3.border = 2
Form3.W=80
Form3.H=25
---------------------------------------------------------------------------

login()
forms.run(Form1)

 

Изменено пользователем bes_zensuri1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, bes_zensuri1 сказал:

Button1=Form2:addButton(6,14,"ПОПОЛНИТЬ", onClick)

...

Button2=Form2:addButton(6,18,"ПРИЗЫ", onClick)

...

Вместо onClick нужно указывать функцию, которая должна вызываться при нажатии кнопки. Они что, одинаковые для всех кнопок?

Так же до выполнения forms.run(Form1) дело не дойдет, т.к. застрянет на бесконечном цикле в функции login().

Не используй бесконечные циклы когда пользуешься GUI

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
30 минут назад, Zer0Galaxy сказал:

Вместо onClick нужно указывать функцию, которая должна вызываться при нажатии кнопки.

Да. я делал другие названия, но то на этой форме даже с анонимной функцией :

Скрытый текст

Button1=Form2:addButton(6,14,"ПОПОЛНИТЬ", function() Form3:setActive() end)

Скрытый текст

function my_fynction(self,name)
        Form3:setActive()    
end
Button2=Form2:addButton(6,18,"ПРИЗЫ", my_fynction)

Не работает. Хотя появляется она с помощью Form2:setActive()  значит она активная

Изменено пользователем bes_zensuri1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ты уверен, что дело доходит до forms.run и не застреёт где-то на while true do?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
14 минуты назад, Zer0Galaxy сказал:

Ты уверен, что дело доходит до forms.run и не застреёт где-то на while true do?

А, извиняюсь, протупил. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...