Форум программистов, компьютерный форум, киберфорум
Haskell
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.89/37: Рейтинг темы: голосов - 37, средняя оценка - 4.89
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9

Делаю GUI на Haskell

01.04.2017, 00:07. Показов 8056. Ответов 77
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам

Предпосылки
Нормального, кроссплатформенного, графического интерфейса в настоящий момент для Haskell нет. Имеющиеся обёртки к сишным либам (GTK+, WxWidgets) оставляют желать лучшего, мягко говоря. С каждой новой версией и сишной библиотеки, и обёртки вылезают баги их совместимости. Особенно это заметно под Windows, т.к. под этой ОС авторы обёрток не привыкли их проверять. Проблемы кросс-языковой совместимости, в принципе, это проблемы человеческого фактора. Но они реально достают.
Выбор
И так, я стал выбирать как можно более низкоуровневую кроссплатформенную библиотеку с тем, что бы она наименее мешалась, а практический весь GUI реализовать на Haskell. Такой подход, как я предполагаю, максимально снизит «обёрточные» проблемы, или, если угодно, они будут сосредоточены в одном Haskell пакете (или нескольких взаимосвязанных) где фиксить их будет куда проще. Кроме того, разработка новых компонент GUI-я, так же будет происходить в рамках одного языка, что, очевидно, удобнее.
Из рассматриваемых кандидатов я отклонил OpenGL как очень избыточную для целей обычного (2D) интерфейса. К тому же она медленна под Windows.
От использования браузера через JavaScript я отказался на основании некоторых, накладываемых на такой интерфейс ограничений.
Выбор я остановил на библиотеке SDL2. И, хотя это мультимедийная библиотека, якобы заточенная под геймдев, мне в ней понравился простой API для работы с окнами, мышью и клавиатурой. Под винду она использует DirectX (хотя может и OpenGL), под другие ОС только OpenGL. Допускается создание любого числа окон операционной системы, получение сообщений от устройств ввода через очередь сообщений. Возможность создавать свои сообщения (нужны для обновления интерфейса из потоков), возможность работать с весьма ограниченным набором примитивов и текстурами. Рендеринг текста и загрузка изображений из многих графических форматов реализована сопутствующими сишными библиотеками SDL_ttf и SDL2_image. В принципе, возможно подключить более «навороченную» библиотеку cairo в качестве дополнения, Haskell обёртки к которой есть, при чём даже специально к SDL, но я пока cairo в сам проектируемый GUI не заложил. Для GUI хватает и графических примитивов SDL2.


Упрощённо иерархия выглядит так.


Нудное описание
Базовый слой GUI поддерживает дерево Widget-ов общего назначения. Алгоритмы последовательности их отрисовки, доставку событий (в виде вызовов функций Widget-а) от мыши и клавиатуры, учёт наложений, скроллирования, взаимодействия между окнами приложения и прочие «общие» моменты. Базовый Widget представляет собой фиксированную запись с полями – свойствами Widget-а и набором полей – функций, создаваемых, предположительно, только при (даже перед) созданием самого виджета. Набор функций напоминает набор обработчиков событий в распространённых, ООП-ешных GUI. Конкретные виджеты (виджеты компоновок – layout-ы, надписи, кнопки и пр. представляют собой (на уровне данных) объединение в одном типе типа базового виджета и типа уникального для конкретного виджета. Т.е. данные описывающие более высокоуровневые виджеты имеют в качестве одного из полей запись виджета более низкоуровневого. Базовый виджет всегда хранится по ссылке (IORef). Так же, через
IORef он доступен в дереве виджетов базового слоя.
В известном чате мне советовали использовать FRP, но если посмотреть исходники FRP пакетов, то внутри там IORef-ы и есть. Пока воздержусь от использования в GUI. Может потом поумнею? (хм... куда уж там).
Про исходники (нет, я не копира...)
Исходники, к сожалению, я пока не готов выложить по следующим причинам:

- Ещё мало чего можно показать. Не хотелось бы что бы скачали, посмотрели и сказали «фи, опять какая то недоделка». Да, пока весьма недоделка, даже на базовом уровне по которой надо ходить опасно.

Вторая причина – нет комментариев. Да, надо бы их сразу писать, я знаю. Но я себе установил для начального этапа некоторые сроки, а дело двигается медленно, и времени нет, и редизайнил уже много раз.
Так что, как только хоть что то будет – так сразу.
Ну и зачем?
Зачем я это делаю? Ну, во первых «Мужик что бык: втемяшится В башку какая блажь — Колом ее оттудова
Не выбьешь» (с) Н. А. Некрасов. Потом, это, потенциально бесконечная работа. Если (а что крайне врят ли) кто не подключится, она меня переживёт. Чем то этот момент меня привлекает. (Видимо, тоже весеннее обострение. Кодить начал, аккурат 1 марта, хотя задумывался об этом давно).

Что бы было хоть ну на что то посмотреть приведу код (без import-ов) которым создаётся верхняя картинка.
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
mkExampleWidgetHelloWorld :: WidgetInit SimpleWidget
mkExampleWidgetHelloWorld = mkSimpleWidget (WidgetMarginXY 20 10) $ defNoChildrenFns{
        onCreate = (\widget -> notifyParentOnSizeChangedAndMarkForRedraw widget $ V2 0 80)
        ,onDraw=drawFn}
    where drawFn widget canvas = do
                canvasRect <- getCanvasRect widget
                setColor canvas $ V4 0 0 255 0
                fillRect canvas canvasRect
                setColor canvas $ V4 255 0 0 0
                drawRect canvas $ shrinkRect' 5 canvasRect
                fnt <- getFont canvas ""
                drawStrAligned canvas fnt AlignCenter DrawStrFine (V4 255 255 255 0) canvasRect 
                                             "Привет, мир!"
 
mkExampleWidgetPicture :: WidgetInit SimpleWidget
mkExampleWidgetPicture = mkSimpleWidget (WidgetMarginXY 20 10) $ defNoChildrenFns{
        onCreate = (\widget -> notifyParentOnSizeChangedAndMarkForRedraw widget $ V2 0 160)
        ,onDraw=(\widget canvas -> do
                    canvasRect <- getCanvasRect widget
                    drawStretchedTextureR canvas "snapshot_00.41.57.jpg" Nothing canvasRect
                )}
 
mkExampleTextGrid :: WidgetInit SimpleWidget
mkExampleTextGrid = mkSimpleWidget (WidgetMarginXY 20 10) $ defNoChildrenFns{
        onCreate = (\widget -> notifyParentOnSizeChangedAndMarkForRedraw widget $ V2 0 (-1))
        ,onDraw=drawFn}
  where drawFn widget canvas = do
            canvasRect@(   SDL.Rectangle (P (V2 l t)) (V2 w h)) <- getCanvasRect widget
            setColor canvas $ grayColor 200
            fillRect canvas canvasRect
            fnt <- getFont canvas ""
            let dx = 30
                dy = 20
                txtColor = (V4 0 100 0 0)
                txtFill r y =
                    let txtRow c x = when (x < w) $ do
                                drawStr canvas fnt txtColor (P (V2 x y)) [c,r]
                                txtRow (succ c) (x+dx)
                    in when (y < h) $ do
                        txtRow '0' l
                        txtFill (succ r) (y+dy)
            txtFill '0' t
 
main :: IO ()
main = runGUI defSkin [GuiFontDef "" "PTM55F.ttf" 14] $ \gui _ -> do
    win <- newWindow gui "GUI : vertical layout test" $ 
                       SDL.defaultWindow { SDL.windowInitialSize = V2 300 400 }
    vLayout <- (win $+) =<< mkVLayout WidgetMarginNone zero (grayColor 230)
    mapM_ (vLayout $+) [mkExampleWidgetHelloWorld, mkExampleWidgetPicture, mkExampleTextGrid]

И наконец.
Радужные перспективы.
Сделать более менее нормальный GUI со своей изюминкой, полностью типобезопасный, а потом, на нём сотворить, наконец, нормальное IDE для Haskell.
7
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.04.2017, 00:07
Ответы с готовыми решениями:

Списки в Haskell? Что я делаю не так?
Здравствуйте, я пишу маленькую программу в Haskell, которая получает String и заменяет все цифры в нем на единички, а остальные знаки на...

Место ФП и Haskell в компьютерной индустрии (Для чего он нужен, этот Haskell?)
&quot;У нас&quot; ? А где преподавание этой экзотики на высоте? Добавлено через 2 минуты А где такие &quot;пришедшие&quot; используют...

Как запустить qt gui программу, как демон, без gui, скрыв gui?
Как запустить qt gui программу, как демон, без gui, скрыв gui? В gui браузер выполняет определенные действия, и нужно запустить этот...

77
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
07.04.2017, 10:52  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от pycture Посмотреть сообщение
к либе кстати солидный док прилагается
Заметил. 13-ти летней давности. Ещё настораживает что на hackage не видно попыток порта в Haskell, а о самом clean на известном русскоязычном haskell чате упоминалали как "это ещё во времена clean было". Ну, я не то что бы с порога против того чего не видел, но демотивирует.

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от pycture Посмотреть сообщение
хе
Да. Вы быстро ищите. :)



Добавлено через 21 минуту
Бегло посмотрел про попытку порта в Haskell. Не, у меня, в отличии от Simon Peyton Jones-а , другой подход. Я за однотредовый GUI (который, конечно, можно будить из тредов). Да и старьё это. В ссылках только 90-ые годы.
0
1195 / 588 / 88
Регистрация: 20.09.2012
Сообщений: 1,881
07.04.2017, 10:58
Цитата Сообщение от KolodeznyDiver Посмотреть сообщение
Ещё настораживает что на hackage не видно попыток порта в Haskell
если почитать последный док то Пейтон упоминает что часть концепций клина компилятор хаскеля неосиливает.
как "это ещё во времена clean было"
во времена клина на нем было полноценное неглючное IDE с профайлером! из коробки под все оси и даже директиксовые игрушки. ну а то что не взлетел, так легко обяснимо. если б микрософт лил бабки не в хаскель, а в клин, никто б о хаскеле сейчас не знал в принципе. так что в данном случае как и везде, вопрос не качества, а связей/маркетинга/и пр.
0
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
07.04.2017, 11:16  [ТС]
Цитата Сообщение от pycture Посмотреть сообщение
во времена клина на нем было полноценное неглючное гуи с профайлером!
На haskell, сказывают, когда то lleksah под линь работал. Потом протух в связи с выходом новых версий ghc и зависимых пакетов. Мне самому удалось поймать момент когда один из плагинов к идее поддерживал даже пошаговую отладку. Недолго, конечно. Тоже протух. Вот это и надоело, по этому и решил взять всё в свои руки. Врят ли сделаю целый GUI за разумное время, но возможность решать задачу с такой дальней перспективой доставляет.

Не по теме:

Цитата Сообщение от pycture Посмотреть сообщение
если б микрософт лил бабки не в хаскель, а в клин
наверно у них были на то причины. В сущности, и что такое Haskell мало кто знает. Что взлетело и летает мы знаем - всякое разное с сишным синтаксисом. Вот, от писанины на нём я и отвлекаюсь Haskell-ом.

1
07.04.2017, 13:47

Не по теме:

Цитата Сообщение от pycture Посмотреть сообщение
в принципе от хаскеля почти не отличается
Прочитал "Quick impression" - выглядит симпатично.

0
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
01.05.2017, 01:04  [ТС]
И так, начался новый месяц. Отчитываюсь.

Не сколько сделано, сколько несколько раз редизайнил. Сейчас приступил к реализации прокручиваемых областей со скроллбарами. Делая их у меня даже возник вопрос . Кнопки со стрелками я, конечно, опционально объединю со скроллбаром (и, они могут быть с рамкой что вверху слева, а не с такими как на картинке, чёрными). GUI настраивается через Скин - запись со множеством полей задающая цвета, кой какие размеры, и где брать картинки, например , те что на кнопках. Шрифты, картинки, курсоры (пока только набор системных курсоров) кешируется. Т.е. их можно запросить один раз, и в следующий они бертся из кеша по текстовому ключу (для картинки, к примеру, ключ -
имя файла). Для работы программы с таким GUI предусматривается каталог с подкаталогами для картинок и пр. в положенном по XDG Base Directory Specification месте. Т.е. всё кроссплатформенно. Хотя, для Windows я бы мог это всё в ресурсы запихать, но будет не кросс...
По картинке. Собрал всякие последнии достижения из нескольких тестовых окошек. Трекбар, в действительности не такой попугайский - я его специально выделил. Теперь все виджеты при создании принимают первым параметром специфичную для типа виджета запись с настройками. Получается однотипненько, компактно (большая часть настроек по дефолту, т.е. из скина и не видна), и, в дальнейшем, может быть это поможет с сериализацией и взаимодействию с конструктором интерфейса.

Исходники пока не выкладываю. Не-а. Много редизайнил, сыро, сыро ... . А сейчас мне предстоит скроллы сделать. Для меня это сложно. Подразумевается, что в скроллируемой области могут быть те же элементы интерфейса, в том числе и другие скролл-области. Т.е. всё по взрослому. Не получится с наскока, полезу читать как это делается.

А пока посмотрите как выглядит построение вышеприведённого окошка в коде. Обратите внимание на обработку событий. Вполне можно справится без FRP, хотя я и не гарантирую что потом его не прикручу.
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
-- Простенький виджет, что бы показать как это делается.
framesTest :: MonadIO m => Widget -> Skin -> m (GuiWidget SimpleWidget)
framesTest parent Skin{..} = mkSimpleWidget (WidgetMarginXY 20 10) parent (defNoChildrenFns $ V2 250 80){
            onDraw= \ widget -> do
                visibleRect@( SDL.Rectangle p0 _) <- getVisibleRect widget
                setColor bkColor
                fillRect visibleRect
                let rect0 = SDL.Rectangle (p0 .+^ V2 10 10)  (V2 50 50)
                    ligthColor = grayColor 240
                    darkColor = grayColor 180
                draw3DBorder ligthColor darkColor 1 rect0
                draw3DBorder ligthColor darkColor 2 $ rectMove rect0 (V2 70 0)
                setColor $ grayColor 0
                drawRoundBorder $ rectMove rect0 (V2 140 0)
            }
 
main :: IO ()
main = runGUI defSkin
     -- Таблица предзагруженных шрифтов : ключ, имя файла, размер шрифта
        [GuiFontDef ""          "PTM55F.ttf" 14
        ,GuiFontDef "label"     "PTN57F.ttf" 15]
        $ \gui -> do
    win <- newWindow gui "GUI test" $ SDL.defaultWindow { SDL.windowInitialSize = V2 400 400
                                                        --, SDL.windowResizable = True
                                                        }
 
    vL <- win $+ vLayout def{layoutAlignment = AlignCenterTop}
 
    ~[hL0,hL1,hL2,hL3,hL4] <- replicateM 5 (vL $+ hLayout def)
    void $ hL0 $+ label def{labelSize=V2 200 20, labelAlignment=AlignCenter,
                          labelText="Рамки элементов интерфейса :"}
    void $ hL1 $+ framesTest
    lb0 <- hL2 $+ label def{labelSize=V2 70 20, labelAlignment=AlignLeftCenter,
                          labelText="Трекбар :"}
    trBar <- hL2 $+ linearTrackBarTest def{
                               linearTrackBarLn = 200
                             , linearTrackBarMargin = WidgetMarginXY 10 0
                             , linearTrackMinValue = 0
                             , linearTrackMaxValue = 1000
                             , linearTrackBarPos  = 300
                                          }
    let btTriangleDef = ButtonWithTriangleDef   { btTriangleFormItemDef = FormItemWidgetDef $ Just $
                                                                            WidgetMarginXY 3 0
                                                , btTriangleFlags = WidgetVisible .|. WidgetEnable
                                                , btTriangleOrientation = OrientationLeft
                                                , btTriangleSize = V2 16 16
                                                , btTriangleType = ButtonWithTriangleInForm
                                                }
    btnL <- hL2 $+ buttonWithTriangle btTriangleDef
    btnR <- hL2 $+ buttonWithTriangle btTriangleDef{btTriangleOrientation = OrientationRight}
    btnU <- hL2 $+ buttonWithTriangle btTriangleDef{btTriangleOrientation = OrientationUp}
    btnD <- hL2 $+ buttonWithTriangle btTriangleDef{btTriangleOrientation = OrientationDown}
    lb1 <- hL3 $+ label def{labelSize=V2 250 80, labelWrapMode= TextWrap 0 Nothing, labelAlignment=AlignCenter,
        labelText=
        "Пример текста, который может переходить на другие строки, таким образом образуя многострочный текст."}
    btn1 <- hL4 $+ button def{btnSize = V2 120 120,  btnPicture = ButtonLeftPicture "sync.png"
                , btnTextWrapMode = TextWrap 0 Nothing
                , btnText = "Кнопка с картинкой слева и текстом в несколько строк"  }
    btn2 <- hL4 $+ button def{btnSize = V2 120 120,  btnPicture = ButtonBottomPicture "check.png"
                , btnTextWrapMode = TextWrap 0 Nothing
                , btnText = "Кнопка с картинкой внизу и текстом в несколько строк"  }
    btn3 <- hL4 $+ button def{btnSize = V2 120 120,  btnPicture = ButtonBottomPicture "rss_circle.png"
                , btnTextWrapMode = TextWrap 0 Nothing
                , btnText = "Эту кнопку сделаем недоступной после нажатия первой"  }
    -- Реакции на события
    onClick btn1 $ do -- Переводим 3-ю кнопку в disable
        let widget = getWidget btn3
        widgetFlagsRemove widget WidgetEnable
        markWidgetForRedraw widget
    onClick btn2 $ do -- Переводим 3-ю кнопку в enable
        let widget = getWidget btn3
        widgetFlagsAdd widget WidgetEnable
        markWidgetForRedraw widget
    onClick btn3 $ setValue trBar (500::Int) -- устанавливаем scrollBar на середину
    -- при перетаскивании scrollBar-а соответствующее значение отображается в тексте метки
    onChanged trBar $ \ v -> setText lb1 (T.pack $ show (v:: Int))
    -- При нажатии на кнопки со стрелками цвет текста "Трекбар :" поменяется
    onClick btnL $ setTextColor lb0 $ rgb 255 0 0
    onClick btnR $ setTextColor lb0 $ rgb 0 255 0
    onClick btnU $ setTextColor lb0 $ rgb 0 0 255
    onClick btnD $ setTextColor lb0 $ rgb 0 0 0
4
Антикодер
Эксперт функциональных языков программирования
1889 / 871 / 48
Регистрация: 15.09.2012
Сообщений: 3,092
12.05.2017, 00:49
Может библиотеку для GUI лучше делать поверх reflex на принципах FRP?
Я просто переосмыслил доклад:
Фронтенд на Haskell с reflex-dom. Антон Гуща
1
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
12.05.2017, 03:21  [ТС]
Цитата Сообщение от XRuZzz Посмотреть сообщение
Может библиотеку для GUI лучше делать поверх reflex на принципах FRP?
Скорее уж reflex над базовым слоем GUI. Может я пока не въехал какие в ФРП печеньки, пока обхожусь без них. См. низ последнего моего кода. Я смотрел некоторые FRP библиотеки. Внешне события, поведения. Потом запускаем построение схемы (это сразу все взаимодействия ГУЯ описать? Предпочту динамически достраивать.). Внутри исходников elerea/euphoria видны теже IORef-ы, что и у меня.
Но, повторяю, я пока не въехал в ФРП.
За ссылку спасибо. Посмотрел доклад. Про собственно ФРП нового не узнал (или не заметил). А reflex-dom опять же про Web-интерфейс. Я делаю НЕ web интерфейс приложения. Web-GUI-ёв для Haskell море и они строятся по другому принципиально.
3
 Аватар для Araneo
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
15.05.2017, 19:58
KolodeznyDiver, а вашу библиотеку где-нибудь взять можно? Я понимаю что она сырая, но всё же?
0
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
15.05.2017, 20:20  [ТС]
Цитата Сообщение от Araneo Посмотреть сообщение
а вашу библиотеку где-нибудь взять можно? Я понимаю что она сырая, но всё же?
Всё планирую вскорости выложить, да всё ... ну это должно быть хоть что то. Если вы планируете заменить ею GTK, то пока не получится. У меня даже поля ввода текста ещё нет. Я сейчас делаю то что требует внесения изменений в базовый слой, splitter, дальше popup menu, возможно, дальше всплывающие подсказки. Чем быстрее базовый слой приведу к удовлетворяющему меня виду, тем проще будет независимые виджеты, типа поля ввода текста или списков с чекбоксами делать. Т.е. сейчас это если и выложу, то будет чисто познавательно - обсуждательно - холиварный интерес.
p.s. Там ещё надо хотя бы правильно описания по английски написать, ридми. Вот, планирую, отдельной темой выложить как устанавливать SDL. Будет перекликаться с вашей установкой gtk, т.к. там тоже через pacman. Буду "чистую" машину мучить. Но это не сегодня-завтра. У меня ещё и основная работа есть.
1
 Аватар для Araneo
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
15.05.2017, 20:26
Мне нужен минимум функционала ввод текста не работает? Ну... и ладно, сделаю по нажатию кнопки ввод из файла.
P.S. Заодно может я что-то полезное от себя допилю.
0
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
15.05.2017, 20:35  [ТС]
Цитата Сообщение от Araneo Посмотреть сообщение
P.S. Заодно может я что-то полезное от себя допилю.
Замечательно если допилите, но, как я уже сказал, не в течении ближайших дней. Ну, пардон, я не нарочно. Нужно оформить.
0
 Аватар для Araneo
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
15.05.2017, 20:38
Очень, очень жаль :-( Видимо придётся мне от дипломной программы GUI отпиливать совсем, чтобы она под винду хотя-бы собралась Хотя не хотелось бы. Крайне не хотелось бы.
0
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
15.05.2017, 20:52  [ТС]
Цитата Сообщение от Araneo Посмотреть сообщение
Очень, очень жаль :-(
Не. Правильно. Не нужно к дипломной работе (если не ошибаюсь, МГУ заканчиваете?) пытаться по быстрому что то прилепить что не отлажено и/или не освоено. Надёжность в этом деле лучше "фенечек".
Ну, или, весьма простую, и правда, http://wiki.haskell.org/Threepenny-gui , которую в этом трэде уже упоминали. Только тогда в браузере интерфейс. Ну, почему бы и нет? Я если я делаю desktop-ый gui, то это не значит что браузерные неприемлемы нигде.
1
 Аватар для Araneo
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
15.05.2017, 20:56
А вот это наверно вариант, я уже когда-то об этом думал... что же. Благодарю за совет. Это конечно не идеально, но за неимением гербовой...

Добавлено через 48 секунд
Я заканчиваю не сам МГУ, всего лишь его филиал.
0
15.05.2017, 21:03  [ТС]

Не по теме:

Araneo, у вас ещё кто ни будь диплом на Haskell делает? Или стоит говорить в процентном отношении сколько делают?

0
15.05.2017, 21:07

Не по теме:

В нашей группе один я такой. За предыдущий год тоже никого больше :( печально всё это. Если искать других таких же, то это надо в самом МГУ на кафедру АЯ при ВМК идти. Там есть сколько-то хаскелистов (на третьем курсе весной его учат). Но не могу сказать сколько.

0
16.05.2017, 23:48

Не по теме:

Раньше мечтал о таком GUI на OpenGL - ну чтобы был интерфейс как в хороших играх

0
16.05.2017, 23:58  [ТС]

Не по теме:

Цитата Сообщение от XRuZzz Посмотреть сообщение
Раньше мечтал о таком GUI на OpenGL - ну чтобы был интерфейс как в хороших играх
Типа, ходишь по лабиринту с BFG9000 и одновременно, например, прогу в IDE отлаживаешь? )))

0
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
18.05.2017, 08:03  [ТС]
Выложил. https://github.com/KolodeznyDiver/GUI-SDL2
Многого не ожидайте. Оно в процессе. Нет ещё основных виджетов, типа ввод текста или чекбоксов. Я делаю по плану, как мне удобно делать, а не стараюсь выдать на гора уже что то удобное. В перспективе будет.
Так же практически нет комментариев, уж не говоря про спецкомментарии haddock для автогенерации HTML и прочих справок. Да, сознаю что это плохо, нужно бы сразу с комментариями писать. Всё понимаю, но, если бы я с комментариями писал, да по английски все, вы бы не скоро даже в таком объёме увидели бы хоть что то.

p.s. Я там кратко описал в ридми как ставить, но крайне желательно читать Правильная установка Haskell. Утилита Stack и Установка SDL и её Haskell- обёрток.
2
Модератор
 Аватар для Curry
5164 / 3522 / 536
Регистрация: 01.06.2013
Сообщений: 7,670
Записей в блоге: 9
01.06.2017, 04:13  [ТС]
Снова первое число месяца. И так, что сделано (кроме ловли багов).


Добавлен универсальный декоративный элемент border. В зависимости от настроек, он может быть и линией на форме (опционально с надписью) и прямоугольником и рамкой с вставленным туда другим виджетом (или даже несколькими, перекрывающими друг друга).

Добавлена возможность передавать сообщения из трэдов к GUI.
Ранее был только намёк (задел) на это. Теперь можно создать Pipe (я назвал pipe, как pipes у Gabriel Gonzalez, хотя его пайпы в GUI не используются) указав функцию получающую сообщение, а тред может сообщения к этой функции посылать. Вполне типобезопасно, хотя и не без ограничений. По каждой трубе передаётся один аргумент типа Storable a => V.Vector a . Труб этих может быть любое разумное количество, допустимо с разными типами вместо а. Если захочется передавать что то другое, то придётся написать свой instance к классу GuiPipe, при этом поорудовать с указателями (Ptr) , т.к. данные передаётся через очередь сообщений SDL, т.е. там нужно уметь пользоваться FFI (ничего сложного).
Пример использования трубы.
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
    lb <- win $+ label def{labelAlignment=AlignCenter
                           , labelFormItemDef= FormItemWidgetDef $ Just WidgetMarginNone
                           , labelText= "Через 2 с здесь будут данные из трэда"}
 
    pipe <- newGuiPipe gui $ \ _ v -> do
        let toText ix = T.pack $ show $ v V.! ix
        setText lb $ T.concat ["Разрешение дисплея ", toText 0,"x",toText 1]
 
    void $ forkIO $ do
        threadDelay 2000000
        (V2 xRes yRes) <- (SDL.displayBoundsSize . head) <$> SDL.getDisplays
        void $ sendToGuiPipe pipe $ V.singleton xRes `V.snoc` yRes
Так же, добавлены Action-ы и меню.
Идея Action-ов не нова, многие, наверно знают по другим GUI, хотя бы Delphi взять. Для одного действия задаётся обработчик (функция), текст, картинка, горячая клавиша и пр.
Action-ы используются для назначения горячих клавиш, на них ссылаются пункты меню, в будущем кнопки панелей инструментов. В общем, получаем единообразие действий.
В этом GUI Action-ы с особенностями. Во-первых, ссылаются на них по текстовым ключам: имя группы и имя в группе. Это для упрощения будущей возможной кастомизации. В смысле, что бы приложение можно было настроить без изменения исходного кода, например, сменить горячие клавиши. Расход на поиск в HashMap невелик, да и выполняется только при создании меню и пр. При движениях мыши, конечно, Action-ы по текстовым строкам не перебираются.
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    vL <- win $+ vLayout def{layoutAlignment = AlignCenterTop}
 
    -- Define actions
    addActions gui "File" [
         ("New",def{actionText="Новый", actionHotKey=hkCtrl SDL.KeycodeN, actionPicture="new.ico"})
        ,("Open",def{actionText="Открыть", actionHotKey=hkCtrl SDL.KeycodeO, actionPicture="open.png"})
        ,("Save",def{actionText="Сохранить", actionHotKey=hkCtrl SDL.KeycodeS, actionPicture="save.png"})
        ,("SaveAs",def{actionText="Сохранить как", actionPicture="saveas.png"})]
 
    addActions gui "Edit" [
         ("Cut",def{actionText="Вырезать", actionHotKey=hkCtrl SDL.KeycodeX, actionPicture="cut.png"})
        ,("Copy",def{actionText="Копировать", actionHotKey=hkCtrl SDL.KeycodeC, actionPicture="copy.png"})
        ,("Paste",def{actionText="Вставить", actionHotKey=hkCtrl SDL.KeycodeV, actionPicture="paste.png"})]
 
    addActions gui "Application" [
         ("Exit",def{actionText="Выход", actionHotKey=hkAlt SDL.KeycodeF4, actionPicture="exit.png"
            , actionValue = def{onAction=guiApplicationExitSuccess gui}})]
 
    addActions gui "Find" [
         ("Find",def{actionText="Поиск"})
        ,("Replace",def{actionText="Замена"})
         ]
 
    addActions gui "FileFind" [
         ("Find",def{actionText="Поиск в файлах"})
        ,("Replace",def{actionText="Замена в файлах"})
         ]
 
    addActions gui "doSubmenu" [
         ("SomeSubmenu",def{actionText="Некое подменю"})
         ]
 
    addActions gui "ExamplSub" [
         ("Item 1",def{actionText="Действие 1"})
        ,("Item 2",def{actionText="Действие 2"})
        ,("Item 3",def{actionText="Действие 3"})
         ]
 
    -- Define popup menus
    let popupFile = mkMenu (mItem "File" "New") (mItem "File" "Open") (mItem "File" "Save") (mItem "File" "SaveAs")
                           (mItemSub "doSubmenu" "SomeSubmenu" $ mkMenu (mItem "ExamplSub" "Item 1")
                                                                        (mItem "ExamplSub" "Item 2")
                                                                        (mItem "ExamplSub" "Item 3"))
                           (mItem    "Application" "Exit")
        popupEdit = mkMenu (mItem "Edit" "Cut") (mItem "Edit" "Copy") (mItem "Edit" "Paste")
        popupFind = mkMenu (mItem "Find" "Find") (mItem "Find" "Replace")
                           (mItem "FileFind" "Find") (mItem "FileFind" "Replace")
 
    void $ vL $+ horizontalMenu def{hmenuItems = mkHMenu
        def{hmenuText = "Файл", hmenuPopup = popupFile}
        def{hmenuText = "Правка", hmenuPopup = popupEdit}
        def{hmenuText = "Поиск", hmenuPopup = popupFind}
                                    }
 
    void $ vL $+ border def { borderFormItemDef = FormItemWidgetDef $ Just WidgetMarginNone
                            , borderSize = V2 (-1) 2, borderType = BorderMono
                            , borderBkgrnd = BorderBkColor $ grayColor 255
                            }
 
    let txtHotKeyPrompt = "Попробуйте нажать Alt-F2 или Ctrl-D"
    lb <- vL $+ label def{labelSize=V2 (-1) 20, labelAlignment=AlignCenter, labelText=txtHotKeyPrompt}
 
    hL0 <- vL $+ hLayout def
    btn0 <- hL0 $+ button def{btnSize = V2 200 35, btnText = "Восстановить текст"}
    onClick btn0 $ do
        setText lb txtHotKeyPrompt
        
    addActions gui "Hotkeys" [
         ("hk0",def{actionHotKey= hkAlt SDL.KeycodeF2, actionValue=def{onAction= setText lb "Alt-F2"}})
        ,("hk1",def{actionHotKey= hkCtrl SDL.KeycodeD, actionValue=def{onAction= setText lb "Ctrl-D"}})
        ]
 
    -- Пример задания/замены действия для Action после его создания.
    setAction gui "File" "Save" $ setText lb "Нажат пункт меню File/Save"
Во-вторых, введено понятие состояния программы – число 0..31, одно на весь GUI. У каждого Action-а есть поле задающее его состояние (видим, недоступен, доступен) для каждого состояния программы. Например, в редакторе или IDE состав пунктов меню зависит от того, открыт документ (или проект) или нет. Меню описываются со всеми пунктами, но видны будут те, которые настроены под данное состояние программы. Т.е. меняем код состояния программы и меняются меню, хоткеи и т.д.
Полей ввода текста, чекбоксов, и подобных, наиболее востребованных в GUI, виджетов всё ещё не делал. Не из вредности. Сделаю, когда (и если) почувствую что пакет можно рекомендовать к употреблению. Да ещё и мануал написать надо. Думаю, даже, мануал раньше. С описанием как эти виджеты делать.
4
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.06.2017, 04:13

[ubuntu] Как запустить qt-gui программу без gui-интерфейся из консоли?
Как запустить qt-gui программу без gui-интерфейса из консоли?

Как запустить GUI приложение (например, notepad.exe) без отображения GUI?
Добрый день. Интересует есть ли такая возможность, как запустить GUI приложение (например, notepad.exe) без отображения GUI?

LWJGL+ GUI - Выход из рендерного цикла для работы в GUI без потери окна
Всем привет! Учусь использовать OpenGL в Java. И у меня возникла небольшая проблемка, окно LWJGL запускается с гуи, и если уже...

LWJGL и GUI - Выход из рендерного цикла для роботы в GUI без потери окна
Всем привет! Учусь использовать OpenGL в Java. И у меня возникла небольшая проблемка, окно LWJGL запускается с гуи, и если уже запустился...

Как лучше и быстрее из SQL в QVector и в GUI или сразу из SQL в GUI
Доброе время суток! Ну собственно вопрос в теме, как лучше сделать. Сначала прочитать SQLite в вектор и работать с ним и оставить файл...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru