paint-brush
აი, როგორ ავაშენე Webflow Like UI Builder Python-ისთვისმიერ@paulfreeman
350 საკითხავი
350 საკითხავი

აი, როგორ ავაშენე Webflow Like UI Builder Python-ისთვის

მიერ Paul10m2024/10/05
Read on Terminal Reader

Ძალიან გრძელი; Წაკითხვა

ჩემი აზროვნების პროცესისა და გამოცდილების გაზიარება პითონისთვის Drag and Drop UI builder-ის შექმნისას
featured image - აი, როგორ ავაშენე Webflow Like UI Builder Python-ისთვის
Paul HackerNoon profile picture
0-item
1-item


მე ვმუშაობ Drag and Drop builder-ზე Python-ისთვის ბოლო რამდენიმე კვირის განმავლობაში.


შეგიძლიათ შეამოწმოთ იგი მისამართზე PyUIBuilder

წყარო კოდი: https://github.com/PaulleDemon/PyUIBuilder


რისი გაკეთება შეუძლია მშენებელს?

მოკლედ, ის დაგეხმარებათ სწრაფად შექმნათ UI Python-ისთვის და შექმნათ UI კოდი მრავალ ბიბლიოთეკაში/ჩარჩოებში, მათ შორის Tkinter და customtkinter. შეგიძლიათ მეტი წაიკითხოთ მახასიათებლების განყოფილება


მაგრამ მე არ მინდა მხოლოდ პროექტის დაწყება, ასევე მინდა გაგიზიაროთ ჩემი გამოცდილება. ამ ბლოგში მე განვიხილავ ჩემს აზროვნების პროცესს და მაღალი დონის მიმოხილვას, თუ როგორ შევქმენი აპლიკაცია.

მოდის იდეა.

პოპულარული რწმენის საწინააღმდეგოდ, Python ხშირად გამოიყენება სწრაფი აპლიკაციების შესაქმნელად, ის განსაკუთრებით პოპულარულია დეველოპერებში, რომლებიც მუშაობენ მონაცემთა მეცნიერებაში, ავტომატიზაციაში, სკრიპტირების ამოცანები და ა.შ. მრავალი შიდა ინსტრუმენტი და GUI, განსაკუთრებით სამეცნიერო და კვლევით პარამეტრებში, აშენებულია Python-ით მისი გამო. სიმარტივე და ისეთი ჩარჩოების ხელმისაწვდომობა, როგორიცაა Tkinter, PyQt და სხვა.

იდეა

ახლა იყო ბევრი Drag and drop მშენებლები ვებისთვის, მაგრამ ძალიან ცოტა Python GUI-ებისთვის, განსაკუთრებით tkinter-ისთვის. მე ვნახე რამდენიმე, მაგრამ პრობლემა ის იყო, რომ ისინი იყო ვიჯეტების ძალიან შეზღუდული რაოდენობა ან ქმნიდნენ კოდს XML ფორმატში, რაც არ არის იდეალური, თუ თქვენ ავითარებთ ინტერფეისს Python-ში.


ასე რომ, თავიდან მე უბრალოდ მსურდა შეგვექმნა შესაბამისი drag and drop UI builder მხოლოდ Tkinter-ისთვის.


მე განვაგრძობდი ვიფიქრებდი იდეალური GUI შემქმნელის იდეის ირგვლივ (სიტყვა არ იყო განკუთვნილი). მე შთაგონებული ვიყავი Canva's UI-ით და გამოვიტანე რამდენიმე ფუნქცია, რომელიც ჩემს GUI-ს იდეალურს გახდის.


  1. ყველა ვიჯეტი უნდა გაკეთდეს როგორც დანამატები.
  2. უნდა მხარი დაუჭიროს მესამე მხარის UI ვიჯეტებს დანამატების სახით.
  3. უნდა შეეძლოს აქტივების ატვირთვა, როგორიცაა სურათები, ვიდეო და ა.შ.
  4. მან უნდა შექმნას კოდი პითონში.

ამიტომ, დაახლოებით ივლისის ბოლოს გადავწყვიტე პროექტზე მუშაობა დამეწყო

იდეის გაფართოება

თავიდან მას ეძახდნენ tkbuilder, რაც მიუთითებს, რომ ეს არის GUI მშენებელი Tkinter UI ბიბლიოთეკისთვის.


მაგრამ, თუ შენიშნეთ, მე ასევე შემიძლია გავაფართოვო იგივე იდეა მრავალი Python GUI ჩარჩოსა და ბიბლიოთეკის მხარდასაჭერად, რადგან ყველაფერი დამზადებულია როგორც დანამატი და ეს არის ზუსტად ის, რის გაკეთებასაც ვგეგმავდი.

საწყისი ვერსიის დაგეგმვა.

თავდაპირველი ვერსიისთვის არ მინდოდა ძალიან ბევრი ფუნქციის დამატება, რაც მომხმარებლებს გადატვირთავს. მსურდა მისი აგება ხალხის გამოხმაურების საფუძველზე, რომლებიც მას იყენებენ. ამ გზით მე არ ვკარგავ დროს იმ ნივთების აშენებაზე, რაც ხალხს არ სურს.


თავიდანვე გადავწყვიტე არ მქონოდა ბექენდი ან რაიმე ან რეგისტრაციის ფორმა. ამ გზით ბევრად უფრო მარტივია ჩემთვის განვითარება და მომხმარებლებისთვის, რომლებიც იყენებენ მას. მე უბრალოდ მინდოდა უბრალო წინა ნაწილი, რომლითაც ადამიანებს შეეძლოთ დაწყება.

ენის არჩევა JS, TS ან Python

ენის არჩევა

დიახ, ეს იყო ის, რაზეც მე ხშირად ვფიქრობდი, პითონის GUI შემქმნელების უმეტესობა აშენდა პითონის გამოყენებით. ჩემი პირველი არჩევანი Python-ისთვის იყო PySide.


ყველაზე რთული GUI-ზე დაფუძნებული აპლიკაცია, რომელიც მე შევქმენი PyQt/Pyside-ის გამოყენებით, იყო ა კვანძზე დაფუძნებული რედაქტორი რამდენიმე წლის უკან.


მაგრამ მე სწრაფად მივხვდი პითონის გამოყენების შეზღუდვებს საწყისი ვერსიის შესაქმნელად.


  • Python UI ბიბლიოთეკებს არ აქვთ ბევრი მესამე მხარის ვიჯეტი, რომელიც დამეხმარება საწყისი ვერსიის სწრაფად აშენებაში.
  • არ არის ადვილი Python აპლიკაციის exe ფაილების სახით გავრცელება, სადაც JS-ის გამოყენებით შეგვიძლია მისი გავრცელება ელექტრონული აპლიკაციის სახით.
  • ადამიანების უმეტესობას ურჩევნია გამოიყენოს ვებ, ნაცვლად იმისა, რომ ჩამოტვირთოს შესრულებადი ფაილი უცნობი ვებსაიტიდან.


Typescript ასევე იყო ვარიანტი, მაგრამ Typescript-ით ყოველთვის ვგრძნობდი, რომ ის ძალიან მრავლისმეტყველი იყო


ეს იყო ერთადერთი რამ, რაც მაშინვე შევნიშნე, ამიტომ ჩემი პირველი არჩევანი გახდა JS-ის გამოყენება.


PS: მოგვიანებით ვნანობ, რომ არ დავიწყე TS, მაგრამ ეს იქნება ამბავი სხვა დროს.

ჩარჩო ან არა ჩარჩო.

Framework-ის მსგავსი ბიბლიოთეკა, რომელიც მე ყველაზე კომფორტული ვარ, არის React.js, მაგრამ აბსტრაქციის შექმნა მოითხოვს კლასების გამოყენებას, რაც არ არის რეკომენდირებული hook-ების დანერგვის შემდეგ.


ჩარჩოს გამოუყენებლობის პრობლემა ის იყო, რომ მე თვითონ უნდა აეშენებინა ყველაფერი და არ მქონოდა წვდომა იმ უზარმაზარ კომპონენტურ ბიბლიოთეკებზე, რომლებიც რეაგირებას გვთავაზობს.


ორივეს ჰქონდა კომპრომისი, მაგრამ React კლასების გამოყენება მაინც შეიძლება, ასე რომ, ეს ჩემთვის აშკარა არჩევანი გახდა.

მუწუკიანი დაწყება

აგვისტოს დასაწყისში დავიწყე ძალიან ბაზისა და გვერდითი ზოლის აშენებით და უსახსრობის გამო მომიწია გაჩერება, ამიტომ შევასრულე კლიენტის სამუშაო, რომელმაც სამწუხაროდ საბოლოო თანხა არ გადაიხადა. Crowd Funding ვცადე, მაგრამ იქაც არ გამიმართლა.


ასე რომ, სექტემბრის თვეში იმ მცირე თანხით, რაც დამრჩა, გადავწყვიტე ამ პროექტში მონაწილეობა მივიღო. დაახლოებით 9 სექტემბერს დავიწყე მუშაობა.

წინასწარ დაგეგმვა...

წინასწარ დაგეგმვა

ბევრი დრო დადიოდა საბაზისო აბსტრაქციაზე ფიქრზე, რომელიც შეიძლება გაფართოვდეს მასშტაბით, საჭიროებების დასაკმაყოფილებლად.


  1. მინდოდა მქონოდა ტილო, რომლის მასშტაბირება და პანირება შესაძლებელია Figma-ს მსგავსად.

  2. საბაზო ვიჯეტი, საიდანაც შეიძლება გავრცელდეს ყველა სხვა ვიჯეტი.

  3. გადაათრიეთ და ჩამოაგდეთ ფუნქცია UI ელემენტების ტილოში გადასატანად.


React-ით ასაშენებლად, თქვენ უნდა იფიქროთ და შექმნათ იგი გარკვეული გზით, მიუხედავად იმისა, რომ ეს ბიბლიოთეკაა თუ ფრეიმვორკი, ის ყოველთვის უფრო ჰგავს Framework-ს, ვიდრე ბიბლიოთეკას.

UI დიზაინი

მე ყოველთვის მომწონდა, როგორ ააშენა Canva-მ თავისი გვერდითი ზოლი, მინდოდა მქონოდა მსგავსი რამ ჩემი drag and drop builder-ისთვის.

ფურცელზე დავხატე ის, რაც გონებაში მქონდა. არ არის საუკეთესო არტისტი იქ 🙄

UI დიზაინი

ჩემი აზროვნების პროცესი ტილოსა და ვიჯეტის ურთიერთქმედების შესახებ.

წინასწარ დაგეგმე...

მაშ, ვინ უნდა იყოს პასუხისმგებელი გადატანის, ზომის შეცვლაზე, შერჩევაზე. ტილო ან საბაზისო ვიჯეტი. როგორ დამუშავდება ვიჯეტის შიგნით არსებული ვიჯეტები?


იცნობს თუ არა საბაზისო ვიჯეტი მათ შვილებს, თუ მისი მართვა მოხდება მონაცემთა ერთი სტრუქტურით თავად ტილოზე. როგორ გავაჩინო ბავშვები ბავშვების შიგნით?


როგორ იმუშავებს გადათრევა და ჩამოშვება ტილოში და სხვა ვიჯეტებში?


როგორ იქნება განლაგების მართვა?


ეს იყო რამდენიმე კითხვა, რომლის დასმა დავიწყე მთელი ნივთის აშენებამდე.


მიუხედავად იმისა, რომ ახლა ინტერფეისი უფრო მარტივი ჩანს, ბევრი ფიქრი იქნა ჩადებული ბაზის აშენებაზე, ასე რომ მომხმარებლებისთვის ის ბევრად უფრო მარტივი ჩანს.

HTML ტილოზე დაფუძნებული მიდგომა ან ტილოზე დაფუძნებული მიდგომა.

ტილოზე დაფუძნებული მიდგომა

ახლა html-ს აქვს ნაგულისხმევი Canvas ელემენტი, რომელიც საშუალებას გაძლევთ გააკეთოთ ბევრი რამ, როგორიცაა ხატვა, სურათის დამატება და სხვა, ახლა ის იდეალურ ელემენტად გამოიყურებოდა ჩემი პროგრამისთვის.


ასე რომ, დავიწყე შემოწმება, იყო თუ არა და ჩამოაგდეს, ზომის შეცვლა, მასშტაბირება და გადატანა. ვიპოვე FabricJs , ეს ფანტასტიკური ბიბლიოთეკა იყო ჩემი გამოყენების შემთხვევაში.


მე ვცადე ექსპერიმენტები Fabric.Js-თან და ვცადე მთლიანი ნივთის დანერგვა ქსოვილში. როგორც ხედავთ ამას განხორციელება , მაგრამ იყო რაღაც ტილოზე, რასაც ვერ ვხვდებოდი.


  1. მე დავიწყე ექსპერიმენტები კაკვებზე დაფუძნებული მიდგომით ტილოს აგებისას, მაგრამ fabric.js dispose ფუნქცია იყო ასინქრონული, ასე რომ, ის კარგად არ ითამაშებდა Hooks-თან.
  2. ტილო არ შეიძლება ჰქონდეს შვილობილი ელემენტები, როგორიცაა Div ან სხვა ელემენტები, რაც უფრო გაართულებს განლაგების მენეჯერების შექმნას
  3. ტილოზე რაიმეს გამართვა საკმაოდ რთულია, რადგან ტილოს შიდა ელემენტები არ ჩანს დეველოპერის ხელსაწყოების შემოწმების ელემენტში


ტილოზე დაფუძნებული მიდგომა


ახლა ექსპერიმენტების შემდეგ, ტილოზე უკეთესი მიდგომა ჩანდა, რადგან მე მაქვს წვდომა ნაგულისხმევი განლაგების მენეჯერზე, ასევე, იყო მრავალი UI წინასწარ ჩაშენებული კომპონენტი, რომელიც გახდის ამ იდეალურ არჩევანს სკალირებისას.


მე ვგეგმავდი ტილოს სიმულაციას ორი განსხვავებული div-ის ერთი შიდა და გარე კონტეინერის გამოყენებით.


ახლა მასშტაბირების და პანელის შექმნა საკმაოდ მარტივი იყო განსახორციელებელი, რადგან CSS-ს უკვე ჰქონდა ტრანსფორმაცია, მასშტაბირება და თარგმნა.


პირველ რიგში, ამის განსახორციელებლად, მე უნდა მქონოდა კონტეინერი, რომელსაც ტილო უჭირავს. ახლა ეს ტილო არის უხილავი ელემენტი (დაფარვის გარეშე), აქ ყველა ელემენტი იშლება და გამოიყენება მასშტაბირება და თარგმანი.

კონტეინერი

მასშტაბის გასადიდებლად მომიწია მასშტაბის გაზრდა და გასადიდებლად მისი შემცირება.

სცადეთ ეს მარტივი მაგალითი. ( + გასადიდებლად და - გასადიდებლად)


პანინგი მუშაობდა ანალოგიურად

გადაათრიეთ და ჩამოაგდეთ

გადაათრიეთ და ჩამოაგდეთ

დაწყებისას მე გამოვიკვლიე რამდენიმე ბიბლიოთეკა, როგორიცაა რეაგირება-ლამაზი-დნდ , React Dnd-kit და React Swappy .


კვლევის შემდეგ დავინახე, რომ react-beautiful-dnd აღარ იყო შენარჩუნებული და დავიწყე React dnd-kit. როგორც დაწყებული შენობა, მე აღმოვაჩინე, რომ dnd-kit-ის დოკუმენტაცია საკმაოდ შეზღუდული იყო იმისთვის, რასაც ვაშენებდი, გარდა ამისა, მალე გამოვა ახალი გამოცემა ძირითადი ცვლილებებით ბიბლიოთეკაში, ამიტომ გადავწყვიტე გამომეტოვებინა react-dnd-kit მთავარ გამოშვებამდე.


მე გადავიწერე ნაწილები, სადაც გამოვიყენე DND-კიტი HTML-ის Drag and Drop API-ით. მშობლიური Drag and drop API-ის შეზღუდვა მხოლოდ ის იყო, რომ ის ჯერ კიდევ არ არის მხარდაჭერილი ზოგიერთი სენსორული მოწყობილობის მიერ, რასაც ჩემთვის მნიშვნელობა არ ჰქონდა, რადგან მე ვაშენებდი არა სენსორული მოწყობილობებისთვის.

სიმართლის ერთადერთი წყარო

შეხედე სიმართლეს

მსგავსი აპლიკაციის შექმნისას ადვილია ყველა ცვლადისა და ცვლილების თვალის დაკარგვა. ასე რომ, მე არ შემიძლია რამდენიმე ცვლადი, რომელიც აკონტროლებს იმავე ინფორმაციას.


ყველა ვიჯეტის ინფორმაცია/მდგომარეობა უნდა იყოს დაცული ტილოში ან თავად ვიჯეტის მიერ, რომელიც შემდეგ გადასცემს ინფორმაციას მოთხოვნისთანავე.


ან იქნებ გამოიყენოთ სახელმწიფო მართვის ბიბლიოთეკა, როგორიცაა redux


მე გადავწყვიტე მქონოდა ყველა ინფორმაცია ვიჯეტების შესახებ, რომელსაც მართავს Canvas კომპონენტი, სხვადასხვა მიდგომების ექსპერიმენტის შემდეგ.


მონაცემთა სტრუქტურა ასე გამოიყურება.

 [ { 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. } ]

React კონტექსტური მენეჯერები

ახლა მინდოდა აქტივები ატვირთული გვერდითა ზოლში, რომელიც ხელმისაწვდომი იყო ვიჯეტების ხელსაწყოთა ზოლით. მაგრამ ყოველთვის, როცა გვერდითა ჩანართებს ვცვლი, ხელახალი რენდერი იწვევს ატვირთული აქტივების გაქრობას.


Redux-ის ერთ-ერთი ყველაზე დიდი შეზღუდვა არის ის, რომ მხოლოდ სერიული მონაცემების შენახვა შეგიძლიათ. არასერიული მონაცემები, როგორიცაა სურათი, ვიდეო, სხვა აქტივები, ვერ შეინახება redux-ზე. ეს გაართულებს საერთო მონაცემების გადაცემას სხვადასხვა კომპონენტის გარშემო.


ამის დაძლევის ერთ-ერთი გზაა React Context-ის გამოყენება. მოკლედ, React Context უზრუნველყოფს მონაცემთა გადაცემის გზას კომპონენტის ხეზე, ყოველ დონეზე ხელნაკეთი რეკვიზიტების გადაცემის გარეშე.


ყველაფერი, რაც მე უნდა გამეკეთებინა, რომ მონაცემები სხვადასხვა კომპონენტში მქონოდა, იყო მისი გადატანა React კონტექსტური პროვაიდერის გარშემო.


მე შევქმენი ჩემი საკუთარი კონტექსტის პროვაიდერები ორი რამისთვის:

  1. გადაათრიეთ და ჩამოაგდეთ - გვერდითი ზოლიდან გადმოწევის ჩართვა + ბავშვის ელემენტების შიგნით გადათრევა და ჩამოშვება.
  2. ფაილის ატვირთვა - იმისათვის, რომ ატვირთული ფაილები ხელმისაწვდომი გახდეს ხელსაწყოთა პანელზე თითოეული ვიჯეტისთვის.


აქ არის მარტივი მაგალითი იმისა, თუ როგორ გამოვიყენე React კონტექსტი 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> ) }


დიახ! ესე იგი. ყველაფერი რაც მე უნდა გამეკეთებინა ახლა იყო მისი გადატანა იმ კომპონენტზე, სადაც მჭირდებოდა კონტექსტი, რომელიც ჩემს შემთხვევაში იყო ტილოზე და გვერდითა ზოლზე.

კოდის გენერირება

პასუხისმგებლობა

ვინაიდან თითოეული ვიჯეტი განსხვავებულად იქცევა და აქვს საკუთარი ატრიბუტები, მე გადავწყვიტე, რომ ვიჯეტები პასუხისმგებელნი უნდა იყვნენ საკუთარი კოდის გენერირებაზე და კოდის ძრავა გაუმკლავდება მხოლოდ ცვლადის სახელების კონფლიქტებს და კოდის შეთავსებას.


ამ გზით, მე ადვილად შევძელი გაფართოება მრავალი წინასწარ აშენებული ვიჯეტის მხარდასაჭერად, ისევე როგორც მესამე მხარის UI დანამატების მხარდასაჭერად.

პირდაპირ ეთერში გადის

მე არ მქონდა ბექენდი ან დარეგისტრირება და იყო უამრავი კომპანია, რომელიც უზრუნველყოფდა უფასო ჰოსტინგს სტატიკური გვერდებისთვის. ჯერ გადავწყვიტე ვერსელთან წავსულიყავი, მაგრამ ხშირად მინახავს ვერსელის უფასო საბურავის დაცემა, თუ ძალიან ბევრი მოთხოვნა იყო.


სწორედ მაშინ გავიგე ამის შესახებ Cloudflares გვერდები შეთავაზება. მათ უფასო საბურავებს თითქმის ყველაფერი შეუზღუდავი ჰქონდა. ასე რომ, cloudflare-ის გამოყენება ჩემი მთავარი არჩევანი გახდა.


ერთადერთი მინუსი იყო აშენების დრო საკმაოდ ნელი და აკლდა საკმაოდ ცოტა დოკუმენტაცია.


build ნაბიჯის ყველაზე გამაღიზიანებელი ნაწილი იყო build მარცხი, Vercel-ზე მუშაობდა, cloudflare გვერდებზე არა??? ჟურნალები ასევე არ იყო ნათელი. და გვაქვს უფასო საბურავები, თვეში მხოლოდ 500 აწყობა გვაქვს, ამიტომ ბევრის დაკარგვა არ მინდოდა


საათობით ვცდილობდი, შემდეგ გადავწყვიტე უწყვეტი ინტეგრაცია დამეყენებინა ცარიელ სტრიქონზე

 CI='' npm install


და ბოლოს პირდაპირ ეთერში გავიდა.
ცოცხალი

გსურთ ნახოთ, როგორ განვითარდა ის თვეების განმავლობაში?

ამ ყველაფერს საჯაროდ ვაშენებდი. გაინტერესებთ, რომ ის გადაიზარდა მარტივი გვერდითი ზოლიდან სრულად აფეთქებულ Drag n drop Builder-მდე, შეგიძლიათ შეამოწმოთ მთელი ვადები აქ .


#საჯაროში აშენება


ოჰ! არ დაგავიწყდეთ თვალი ადევნოთ განახლებებს

ვარსკვლავური რეპო ⭐️


თუ მოგეწონათ ამ ტიპის კონტენტი, მე დავწერ უფრო მეტ ბლოგს, რომელიც უფრო დეტალურად იქნება განხილული, თუ როგორ ვგეგმავ და ავაშენებ პროდუქტებს, შემდეგ კი შეგიძლიათ გამოიწეროთ ჩემი საინფორმაციო ბიულეტენი :)