python

Поиски «идеального» GUI. Путь новичка

  • суббота, 30 ноября 2019 г. в 00:36:17
https://habr.com/ru/post/478106/
  • Python
  • Swift
  • Изучение языков


Изучая первый язык я хотел видеть кнопочки, а не только текст в консоли. Я сделал на Python3+tkinter калькулятор. Это заняло 585 строк. Применив к коду магию py2app, я получил bundle размером 45MB. Мне не понравилась работать с py2app. Иногда все переставало работать, если использовались сторонние библиотеки, а иногда я исправлял код py2app. Из-за этого я думал, что standalone-приложения делать очень сложно.



Через год я познакомился с xCode и калькулятор для iOS занял всего 125 строк. Нужно учитывать, что кнопки были сделаны в визуальном редакторе, а из операций я оставил только: «+», «-», «*», «/». Bundle получился меньше 10 MB.



Пару недель назад я нашел способ сделать калькулятор для Mac OS без xCode. У меня получилось уложиться в 57 строк и я перестал бояться Swift.

import AppKit
let winWid: CGFloat = 256
let wihHei: CGFloat = 180
let dispHei: CGFloat = 18
let rows = 4
let rowHei: CGFloat = 32
class AppDelegate: NSObject, NSApplicationDelegate {
    lazy var window = NSWindow(contentRect: NSMakeRect(0, 0, winWid, wihHei),
                               styleMask: [.titled, .closable], backing: .buffered,
                               defer: false, screen: nil)
    let display = NSText(frame: NSMakeRect(0, wihHei - dispHei, winWid, dispHei))
    func applicationDidFinishLaunching(_ notification: Notification) {
        window.title = "Machine"
        window.contentView?.addSubview(display)

        let eq = NSButton(frame: NSMakeRect(0, 0, winWid, rowHei))
        eq.title = "="
        eq.target = self
        eq.action = #selector(eval)
        window.contentView?.addSubview(eq)

        let items = ["C","0",".","/","1","2","3","*",
                     "4","5","6","-","7","8","9","+"]

        let sz = CGSize(width: (winWid/CGFloat(rows)),
                        height: rowHei)
        for i in 0..<items.count {
            let x = i % rows
            let y = i / rows
            let b = NSButton(
                frame: NSMakeRect(sz.width * CGFloat(x),
                                  sz.height * CGFloat(y) + rowHei,
                                  sz.width, sz.height))
            b.title = items[y*rows+x]
            b.target = self
            b.action = i==0 ? #selector(clear) : #selector(input)
            window.contentView?.addSubview(b)
        }
        window.makeKeyAndOrderFront(nil)
    }
    @objc func input(sender: NSButton) {display.string! += sender.title}
    @objc func eval(sender: NSButton) {
        let exp: NSExpression = NSExpression(format: display.string!)
        if let result: Double = exp.expressionValue(with: nil, context: nil) as? Double {
            display.string = String(result)
        }
    }
    @objc func clear(sender: NSButton) {display.string = ""}
    func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
        return true
    }
}
let delegate = AppDelegate()
var appl: NSApplication
#if swift(>=5.1)
    appl = NSApplication.shared
#else
    appl = NSApplication.shared()
#endif
appl.setActivationPolicy(.regular)
appl.delegate = delegate
appl.run()

Если сохранить код в main.swift и запустить в терминале команду:
swiftc main.swift

Мы получим бинарный файл, который можно упаковать в приложение или просто запустить в терминале. Калькулятор считает не совсем привычным образом. Кнопка "=" вычисляет все, что написано на дисплее.



Но больше всего, меня обрадовал язык Red. Калькулятор на нем можно поместить в 13 строчек. А размер standalone приложения для MacOS будет всего 1 MB.

Red [Needs: View]
View [
    title "Red"
    disp: field 330x50 font-size 25 "" return
    style b: button 71x40 [append disp/text face/text]
    b "1" b "2" b "3" b " + " return
    b "4" b "5" b "6" b " - " return
    b "7" b "8" b "9" b " * " return
    b "0" b "." b " / " b " = " [attempt [
        result: form do disp/text
        append clear disp/text result]] return
    button "C" 325x40 [clear disp/text]
]

Сохраняем код в main.red и набираем в консоли:
red -t macOS main.red




На сайте объявлено, что приложения можно собирать под Windows, Linux, MacOS и др платформы.
Жаль, что разработчики языка пока не среагировали на то, что Apple не поддерживает 32-битные приложения после версии macOS 10.15

Буду рад, если кто-нибудь подскажет более простые варианты создания GUI.