Štai kaip aš sukūriau žiniatinklio srauto kaip vartotojo sąsajos kūrimo priemonę, skirtą Python

Štai kaip aš sukūriau žiniatinklio srauto kaip vartotojo sąsajos kūrimo


Pastarąsias kelias savaites dirbau su „Python“ skirtu „Drag and Drop“ kūrimo priemone.

Galite tai patikrinti adresu PyUIBuilder

Šaltinio kodas: https://github.com/PaulleDemon/PyUIBuilder

Ką gali padaryti statybininkas?

Trumpai tariant, tai gali padėti greitai sukurti „Python“ skirtą vartotojo sąsają ir generuoti vartotojo sąsajos kodą keliose bibliotekose / rėmuose, įskaitant „Tkinter“ ir „customtkinter“. galite perskaityti daugiau apie funkcijų skyrius

Tačiau noriu ne tik pradėti projektą, bet ir pasidalinti su jumis savo patirtimi. Šiame tinklaraštyje apžvelgsiu savo mąstymo procesą ir aukšto lygio apžvalgą, kaip sukūriau programą.

Sugalvojus idėją.

Priešingai populiariems įsitikinimams, Python dažnai naudojamas kuriant greitas programas, ypač populiarus tarp kūrėjų, dirbančių duomenų mokslo, automatizavimo, skriptų užduočių ir kt. paprastumas ir tokių konstrukcijų kaip „Tkinter“, „PyQt“ ir kitų prieinamumas.

idėjaidėja

Dabar buvo daug žiniatinkliui skirtų „drag and drop“ kūrimo priemonių, tačiau labai mažai „Python“ GUI, ypač „tkinter“. Mačiau keletą, bet problema buvo ta, kad juose buvo labai ribotas valdiklių skaičius arba jie generuotų kodą XML formatu, o tai nėra idealu, jei kuriate vartotojo sąsają naudodami Python.

Taigi iš pradžių tiesiog norėjau sukurti tinkamą „drag and drop“ vartotojo sąsajos kūrimo priemonę, skirtą „Tkinter“.

Aš nuolat galvojau apie idealaus GUI kūrėjo idėją (jokio kalbėjimo). Mane įkvėpė „Canva“ vartotojo sąsaja ir sugalvojau keletą funkcijų, dėl kurių mano GUI būtų ideali.

  1. Visi valdikliai turėtų būti sukurti kaip papildiniai.
  2. Turėtų palaikyti trečiųjų šalių vartotojo sąsajos valdiklius įskiepių pavidalu.
  3. Turėtų būti galimybė įkelti išteklius, pvz., vaizdus, ​​vaizdo įrašus ir kt.
  4. Jis turėtų sugeneruoti kodą Python.

Taigi maždaug liepos pabaigoje nusprendžiau pradėti dirbti su projektu

Idėjos išplėtimas

Iš pradžių jis buvo vadinamas tkbuilder, nurodant, kad tai GUI kūrimo priemonė, skirta Tkinter UI bibliotekai.

Tačiau, jei pastebėjote, galiu išplėsti tą pačią idėją, kad palaikyčiau kelias Python GUI sistemas ir bibliotekas, nes viskas sukurta kaip įskiepis ir būtent tai planavau padaryti.

Pradinės versijos planavimas.

Pradinėje versijoje nenorėjau pridėti per daug funkcijų, kurios priblokštų vartotojus. Norėjau jį sukurti remdamasis juo besinaudojančių žmonių atsiliepimais. Taip nešvaistau laiko kurdamas dalykus, kurių žmonės nenori.

Nuo pat pradžių nusprendžiau neturėti užpakalinės programos ar jokios registracijos formos. Taip man kurti ir juo besinaudojantiems vartotojams yra daug paprasčiau. Aš tiesiog norėjau paprastos sąsajos, su kuria žmonės galėtų pradėti.

Kalbos pasirinkimas JS, TS arba Python

pasirenkant kalbąpasirenkant kalbą

Taip, tai buvo kažkas, apie ką kartais galvodavau, dauguma „Python“ GUI kūrėjų buvo sukurti naudojant Python. Mano pirmasis pasirinkimas Python buvo PySide.

Sudėtingiausia GUI pagrįsta programa, kurią sukūriau naudodamas PyQt / Pyside, buvo a mazgais pagrįstas redaktorius prieš keletą metų.

Tačiau greitai supratau, kad pradinės versijos kūrimas yra ribotas naudojant python.

  • Python UI bibliotekose nėra daug trečiųjų šalių valdiklių, kurie padėtų greitai sukurti pradinę versiją.
  • Nelengva platinti „Python“ programą kaip „exe“ failus, nes naudojant JS galime ją platinti elektroninės programos pavidalu.
  • Daugelis žmonių nori naudoti žiniatinklį, o ne atsisiųsti vykdomąjį failą iš nepažįstamos svetainės.

„Typescript“ taip pat buvo pasirinkimas, tačiau naudodamas „Typescript“ man visada atrodė, kad tai per daug išsami

Tai buvo vieninteliai dalykai, kuriuos iškart pastebėjau, todėl pirmuoju pasirinkimu tapo naudoti JS.

PS: Vėliau gailėjausi, kad nepradėjau nuo TS, bet tai bus istorija kitam kartui.

Karkasas arba jo nėra.

Į sistemą panaši biblioteka, su kuria man labiausiai patinka, yra React.js, tačiau norint sukurti abstrakciją, tektų naudoti klases, o tai nerekomenduojama nuo kabliukų įvedimo.

Karkaso nenaudojimo problema buvo ta, kad turėjau viską susikurti pats ir neturėjau prieigos prie daugybės komponentų bibliotekų, kurias gali pasiūlyti „React“.

Abu turėjo kompromisų, tačiau „React“ klases vis tiek galima naudoti, todėl man tai tapo akivaizdus pasirinkimas.

Nedrąsi pradžia

Rugpjūčio pradžioje pradėjau statyti pačią bazę ir šoninę juostą, o dėl lėšų trūkumo teko sustoti, tad ėmiausi kliento darbo, kuris, deja, nesumokėjo galutinės sumos. Bandžiau sutelkti finansavimą, bet nepasisekė.

Taigi, rugsėjo mėnesį turėdamas nedideles lėšas, kurias turėjau, nusprendžiau visapusiškai dalyvauti šiame projekte. Maždaug rugsėjo 9 d. iš naujo pradėjau darbą.

Planuoti į priekį…

planuoti į priekįplanuoti į priekį

Daug laiko teko galvoti apie bazinę abstrakciją, kurią galima išplėsti, kad atitiktų poreikius.

  1. Norėjosi turėti drobę, kurią būtų galima priartinti ir stumdyti panašiai kaip Figma.

  2. Pagrindinis valdiklis, iš kurio gali tęstis visi kiti valdikliai.

  3. Vilkimo funkcija, skirta UI elementams nuvilkti į drobę.

Jei norite kurti naudodami „React“, turite galvoti ir kurti jį tam tikru būdu, nepaisant ginčų, ar tai biblioteka, ar sistema, ji visada atrodo labiau kaip „Framework“, o ne į biblioteką.

UI dizainas

Man visada patiko, kaip „Canva“ kūrė savo šoninę juostą, norėjau turėti kažką panašaus savo „drag and drop“ kūrėjui.

Tai, kas buvo mano galvoje, nupiešiau ant popieriaus lapo. Ne pats geriausias menininkas 🙄

UI dizainasUI dizainas

planuoti į priekį...planuoti į priekį...

Taigi, kas turėtų būti atsakingas už vilkimą, dydžio keitimą, pasirinkimą. Drobė arba pagrindinis valdiklis. Kaip bus tvarkomi valdiklio viduje esantys valdikliai?

Ar pagrindinis valdiklis pažins jų vaikus, ar jį valdys viena duomenų struktūra pati drobė. Kaip aš perteiksiu vaikus vaikų viduje?

Kaip vilkimas veiks drobėje ir kituose valdikliuose?

Kaip bus tvarkomi maketai?

Tai buvo keletas klausimų, kuriuos pradėjau klausti prieš statydamas visą daiktą.

Nors dabar vartotojo sąsaja atrodo paprastesnė, buvo daug galvojama kuriant bazę, todėl vartotojams ji atrodo daug paprastesnė.

HTML drobės metodas arba ne drobės metodas.

Drobės metodas

Dabar html turi numatytąjį drobės elementą, leidžiantį atlikti daugybę dalykų, pvz., piešti, pridėti paveikslėlį ir kt., Dabar jis atrodė kaip idealus elementas naudoti mano programai.

Taigi, pradėjau tikrinti, ar buvo ir esama nuvilkimo, dydžio keitimo, mastelio keitimo ir stumdymo funkcijos. radau Audiniaitai atrodė kaip puiki biblioteka mano naudojimo atveju.

Pabandžiau eksperimentuoti su Fabric.Js ir bandžiau įgyvendinti visą failą fabric.js, kaip matote įgyvendinimasbet drobėje buvo kažkas, ko aš nenumačiau.

  1. Kurdamas drobę pradėjau eksperimentuoti su kabliukais pagrįstu metodu, tačiau fabric.js dispose funkcija buvo asinchroninė, todėl ji netinkamai veiktų su kabliukais.
  2. Drobėje negali būti antrinių elementų, pvz., Div ar kitų elementų, dėl kurių būtų šiek tiek sunkiau sukurti išdėstymo tvarkykles
  3. Gana sunku derinti bet ką drobėje, nes vidiniai drobės elementai nerodomi kūrėjo įrankių tikrinimo elemente

Ne drobės metodas

Dabar po eksperimento ne drobės metodas atrodė geresnis, nes turiu prieigą prie numatytosios išdėstymo tvarkyklės, be to, buvo daug iš anksto sukurtų vartotojo sąsajos komponentų, dėl kurių šis pasirinkimas būtų idealus keičiant mastelį.

Aš planavau imituoti drobę naudodamas du skirtingus div vieną vidinį div ir išorinį konteinerį.

Dabar sukurti mastelio keitimą ir stumdymą buvo gana lengva įgyvendinti, nes CSS jau turėjo transformavimą, mastelį ir vertimą.

Pirmiausia, kad tai įgyvendinčiau, turėjau turėti konteinerį, kuriame būtų drobė. Dabar ši drobė yra nematomas elementas (be paslėpto perpildymo), čia visi elementai numetami, taikomas mastelis ir vertimas.

KonteinerisKonteineris

Norėdami padidinti mastelį, turėjau padidinti mastelį, o mažinti – sumažinti.

Išbandykite šį paprastą pavyzdį. (+ klavišas priartinti ir - sumažinti)

Panoravimas veikė panašiai

Vilkite ir numeskite

vilkite ir numeskitevilkite ir numeskite

Pradėdamas darbą tyrinėjau keletą bibliotekų, tokių kaip Reaguoti-gražus-Dnd, Reaguoti Dnd-kit ir Reaguoti Swappy.

Ištyręs pamačiau, kad „react-beautiful-dnd“ nebeprižiūrimas ir pradėjau naudoti „React dnd-kit“. Pradėjus kurti, dnd-kit dokumentacija buvo gana ribota tam, ką kuriau, be to, netrukus pasirodys naujas leidimas su dideliais bibliotekos pakeitimais, todėl nusprendžiau atsisakyti react-dnd-kit iki pagrindinio leidimo.

Perrašiau dalis, kuriose naudojau DND rinkinį, naudodamas HTML „Drag and Drop“ API. Vienintelis vietinės „Drag and drop“ API apribojimas buvo tas, kad jos vis dar nepalaiko kai kurie jutikliniai įrenginiai, o tai man nebuvo svarbu, nes kūriau neliečiamiems įrenginiams.

Vienintelis tiesos šaltinis

Susidurk su tiesaSusidurk su tiesa

Kuriant tokią programėlę gali būti lengva pamiršti visus kintamuosius ir pakeitimus. Taigi, aš negaliu turėti kelių kintamųjų, kurie sektų tą pačią informaciją.

Kiekvieno valdiklio informacija / būsena turėtų būti saugoma drobėje arba pačiame valdiklyje, kuris vėliau perduoda informaciją, gavus prašymą.

Arba naudokite valstybės valdymo biblioteką, pvz., Redux

Išbandęs skirtingus metodus, pasirinkau turėti visą informaciją apie valdiklius, kuriuos valdo komponentas „Canvas“.

Duomenų struktūra atrodo maždaug taip.

(
  {
    id: "", // id of the widget
    widgetType: WidgetClass,  // base widget
    children: (), // children will also have the same datastructure as the parent
    parent: "", // id of the parent of the current widget
    initialData: {} // information about the widget's data that's about to be rendered eg: backgroundColor, foregroundColor etc.
  }
)

Reaguoti konteksto tvarkytojai

Dabar norėjau, kad į šoninę juostą įkeltas turtas būtų pasiekiamas naudojant valdiklių įrankių juostą. Tačiau kiekvieną kartą, kai perjungiau šoninius skirtukus, dėl pakartotinio pateikimo įkelti ištekliai išnyko.

Vienas didžiausių „Redux“ apribojimų yra tas, kad galite saugoti tik nuosekliuosius duomenis. Neserializuojami duomenys, tokie kaip vaizdas, vaizdo įrašas ir kiti ištekliai, negali būti saugomi redux sistemoje. Dėl to būtų sunkiau perduoti bendrus duomenis apie skirtingus komponentus.

Vienas iš būdų tai įveikti yra naudoti React Context. Trumpai tariant, „React Context“ suteikia galimybę perduoti duomenis per komponentų medį, nereikia rankiniu būdu perduoti rekvizitų kiekviename lygyje.

Viskas, ką turėčiau padaryti, kad duomenis turėčiau skirtinguose komponentuose, tai apvynioti juos aplink React konteksto teikėją.

Sukūriau savo konteksto teikėjus dviem dalykams:

  1. Vilkimas – įgalinamas vilkimas ir nuleidimas iš šoninės juostos + vilkimas ir nuleidimas su antriniais elementais.
  2. Failų įkėlimas – kad įkeltus failus būtų galima pasiekti kiekvieno valdiklio įrankių juostoje.

Čia yra paprastas pavyzdys, kaip aš naudoju „React“ kontekstą „Drag and drop“.

import React, { createContext, useContext, useState } from 'react'

const DragWidgetContext = createContext()

export const useDragWidgetContext = () => useContext(DragWidgetContext)

// Provider component to wrap around parts that need drag-and-drop functionality
export const DragWidgetProvider = ({ children }) => {
    const (draggedElement, setDraggedElement) = useState(null)

    const onDragStart = (element) => {
        setDraggedElement(element)
    }

    const onDragEnd = () => {
        setDraggedElement(null)
    }

    return (
        <DragWidgetContext.Provider value={{ draggedElement, onDragStart, onDragEnd }}>
            {children}
        </DragWidgetContext.Provider>
    )
}

Taip! tai viskas. Viskas, ką dabar turėjau padaryti, tai apvynioti jį aplink komponentą, kur man reikėjo konteksto, o tai, mano atveju, buvo virš drobės ir šoninės juostos.

Kodo generavimas

AtsakomybėAtsakomybė

Kadangi kiekvienas valdiklis elgiasi skirtingai ir turi savo atributus, nusprendžiau, kad valdikliai turi būti atsakingi už savo kodo generavimą, o kodo variklis tvarkys tik kintamųjų pavadinimų konfliktus ir kodo sujungimą.

Tokiu būdu galėjau lengvai išplėsti, kad palaikyčiau daugybę iš anksto sukurtų valdiklių ir kai kurių trečiosios šalies vartotojo sąsajos papildinių.

Tiesiogiai

Neturėjau užpakalinės sistemos ar prisiregistravimo ir buvo daug įmonių, teikiančių nemokamą statinių puslapių prieglobą. Iš pradžių nusprendžiau rinktis „Vercel“, bet dažnai matydavau, kaip „Vercel“ padanga nukrenta, jei buvo per daug prašymų.

Tada aš sužinojau apie Cloudflares puslapiai siūlymas. Jų laisvoje padangoje buvo beveik viskas neribota. Taigi, „Cloudflare“ naudojimas tapo mano pirminiu pasirinkimu.

Vieninteliai trūkumai buvo tai, kad kūrimo laikas buvo gana lėtas ir trūko nemažai dokumentų.

Labiausiai erzinanti kūrimo žingsnio dalis buvo kūrimo gedimas. Jis veikė „Vercel“, bet ne „Cloudflare“ puslapiuose??? Rąstai taip pat nebuvo tokie aiškūs. ir mes turime nemokamų padangų, kurių per mėnesį pagaminama tik 500, todėl nenorėjau per daug švaistyti

Bandžiau valandas, tada nusprendžiau nenutrūkstamą integraciją nustatyti į tuščią eilutę

CI='' npm install

Ir pagaliau jis pasirodė tiesiogiai.
TiesiogiaiTiesiogiai

Norite pamatyti, kaip ji progresavo per visus mėnesius?

Visą tai statau viešai. Noriu pamatyti, kaip ji pereina nuo paprastos šoninės juostos iki visiškai išpūstos „Drag n drop“ kūrimo priemonės, kurioje galite patikrinti visą laiko juosta čia.

#buildinpublic

O! nepamirškite sekti naujienų

Žvaigždžių repo ⭐️


Jei jums patiko tokio tipo turinys, rašysiu daugiau tinklaraščių, kuriuose išsamiau aprašysiu, kaip planuoju ir kuriu medžiagas. Jei norite sekti, galite užsiprenumeruoti mano informacinį biuletenį 🙂



Source link

Draugai: - Marketingo agentūra - Teisinės konsultacijos - Skaidrių skenavimas - Fotofilmų kūrimas - Miesto naujienos - Šeimos gydytojai - Saulius Narbutas - Įvaizdžio kūrimas - Veidoskaita - Nuotekų valymo įrenginiai - Teniso treniruotės - Pranešimai spaudai -