მე ვმუშაობ Drag and Drop builder-ზე Python-ისთვის ბოლო რამდენიმე კვირის განმავლობაში.
შეგიძლიათ შეამოწმოთ იგი მისამართზე
წყარო კოდი:
რისი გაკეთება შეუძლია მშენებელს?
მოკლედ, ის დაგეხმარებათ სწრაფად შექმნათ 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-ს იდეალურს გახდის.
ამიტომ, დაახლოებით ივლისის ბოლოს გადავწყვიტე პროექტზე მუშაობა დამეწყო
თავიდან მას ეძახდნენ tkbuilder, რაც მიუთითებს, რომ ეს არის GUI მშენებელი Tkinter UI ბიბლიოთეკისთვის.
მაგრამ, თუ შენიშნეთ, მე ასევე შემიძლია გავაფართოვო იგივე იდეა მრავალი Python GUI ჩარჩოსა და ბიბლიოთეკის მხარდასაჭერად, რადგან ყველაფერი დამზადებულია როგორც დანამატი და ეს არის ზუსტად ის, რის გაკეთებასაც ვგეგმავდი.
თავდაპირველი ვერსიისთვის არ მინდოდა ძალიან ბევრი ფუნქციის დამატება, რაც მომხმარებლებს გადატვირთავს. მსურდა მისი აგება ხალხის გამოხმაურების საფუძველზე, რომლებიც მას იყენებენ. ამ გზით მე არ ვკარგავ დროს იმ ნივთების აშენებაზე, რაც ხალხს არ სურს.
თავიდანვე გადავწყვიტე არ მქონოდა ბექენდი ან რაიმე ან რეგისტრაციის ფორმა. ამ გზით ბევრად უფრო მარტივია ჩემთვის განვითარება და მომხმარებლებისთვის, რომლებიც იყენებენ მას. მე უბრალოდ მინდოდა უბრალო წინა ნაწილი, რომლითაც ადამიანებს შეეძლოთ დაწყება.
დიახ, ეს იყო ის, რაზეც მე ხშირად ვფიქრობდი, პითონის GUI შემქმნელების უმეტესობა აშენდა პითონის გამოყენებით. ჩემი პირველი არჩევანი Python-ისთვის იყო PySide.
ყველაზე რთული GUI-ზე დაფუძნებული აპლიკაცია, რომელიც მე შევქმენი PyQt/Pyside-ის გამოყენებით, იყო ა
მაგრამ მე სწრაფად მივხვდი პითონის გამოყენების შეზღუდვებს საწყისი ვერსიის შესაქმნელად.
Typescript ასევე იყო ვარიანტი, მაგრამ Typescript-ით ყოველთვის ვგრძნობდი, რომ ის ძალიან მრავლისმეტყველი იყო
ეს იყო ერთადერთი რამ, რაც მაშინვე შევნიშნე, ამიტომ ჩემი პირველი არჩევანი გახდა JS-ის გამოყენება.
PS: მოგვიანებით ვნანობ, რომ არ დავიწყე TS, მაგრამ ეს იქნება ამბავი სხვა დროს.
Framework-ის მსგავსი ბიბლიოთეკა, რომელიც მე ყველაზე კომფორტული ვარ, არის React.js, მაგრამ აბსტრაქციის შექმნა მოითხოვს კლასების გამოყენებას, რაც არ არის რეკომენდირებული hook-ების დანერგვის შემდეგ.
ჩარჩოს გამოუყენებლობის პრობლემა ის იყო, რომ მე თვითონ უნდა აეშენებინა ყველაფერი და არ მქონოდა წვდომა იმ უზარმაზარ კომპონენტურ ბიბლიოთეკებზე, რომლებიც რეაგირებას გვთავაზობს.
ორივეს ჰქონდა კომპრომისი, მაგრამ React კლასების გამოყენება მაინც შეიძლება, ასე რომ, ეს ჩემთვის აშკარა არჩევანი გახდა.
აგვისტოს დასაწყისში დავიწყე ძალიან ბაზისა და გვერდითი ზოლის აშენებით და უსახსრობის გამო მომიწია გაჩერება, ამიტომ შევასრულე კლიენტის სამუშაო, რომელმაც სამწუხაროდ საბოლოო თანხა არ გადაიხადა. Crowd Funding ვცადე, მაგრამ იქაც არ გამიმართლა.
ასე რომ, სექტემბრის თვეში იმ მცირე თანხით, რაც დამრჩა, გადავწყვიტე ამ პროექტში მონაწილეობა მივიღო. დაახლოებით 9 სექტემბერს დავიწყე მუშაობა.
ბევრი დრო დადიოდა საბაზისო აბსტრაქციაზე ფიქრზე, რომელიც შეიძლება გაფართოვდეს მასშტაბით, საჭიროებების დასაკმაყოფილებლად.
მინდოდა მქონოდა ტილო, რომლის მასშტაბირება და პანირება შესაძლებელია Figma-ს მსგავსად.
საბაზო ვიჯეტი, საიდანაც შეიძლება გავრცელდეს ყველა სხვა ვიჯეტი.
გადაათრიეთ და ჩამოაგდეთ ფუნქცია UI ელემენტების ტილოში გადასატანად.
React-ით ასაშენებლად, თქვენ უნდა იფიქროთ და შექმნათ იგი გარკვეული გზით, მიუხედავად იმისა, რომ ეს ბიბლიოთეკაა თუ ფრეიმვორკი, ის ყოველთვის უფრო ჰგავს Framework-ს, ვიდრე ბიბლიოთეკას.
მე ყოველთვის მომწონდა, როგორ ააშენა Canva-მ თავისი გვერდითი ზოლი, მინდოდა მქონოდა მსგავსი რამ ჩემი drag and drop builder-ისთვის.
ფურცელზე დავხატე ის, რაც გონებაში მქონდა. არ არის საუკეთესო არტისტი იქ 🙄
მაშ, ვინ უნდა იყოს პასუხისმგებელი გადატანის, ზომის შეცვლაზე, შერჩევაზე. ტილო ან საბაზისო ვიჯეტი. როგორ დამუშავდება ვიჯეტის შიგნით არსებული ვიჯეტები?
იცნობს თუ არა საბაზისო ვიჯეტი მათ შვილებს, თუ მისი მართვა მოხდება მონაცემთა ერთი სტრუქტურით თავად ტილოზე. როგორ გავაჩინო ბავშვები ბავშვების შიგნით?
როგორ იმუშავებს გადათრევა და ჩამოშვება ტილოში და სხვა ვიჯეტებში?
როგორ იქნება განლაგების მართვა?
ეს იყო რამდენიმე კითხვა, რომლის დასმა დავიწყე მთელი ნივთის აშენებამდე.
მიუხედავად იმისა, რომ ახლა ინტერფეისი უფრო მარტივი ჩანს, ბევრი ფიქრი იქნა ჩადებული ბაზის აშენებაზე, ასე რომ მომხმარებლებისთვის ის ბევრად უფრო მარტივი ჩანს.
ტილოზე დაფუძნებული მიდგომა
ახლა html-ს აქვს ნაგულისხმევი Canvas ელემენტი, რომელიც საშუალებას გაძლევთ გააკეთოთ ბევრი რამ, როგორიცაა ხატვა, სურათის დამატება და სხვა, ახლა ის იდეალურ ელემენტად გამოიყურებოდა ჩემი პროგრამისთვის.
ასე რომ, დავიწყე შემოწმება, იყო თუ არა და ჩამოაგდეს, ზომის შეცვლა, მასშტაბირება და გადატანა. ვიპოვე
მე ვცადე ექსპერიმენტები Fabric.Js-თან და ვცადე მთლიანი ნივთის დანერგვა ქსოვილში. როგორც ხედავთ ამას
ტილოზე დაფუძნებული მიდგომა
ახლა ექსპერიმენტების შემდეგ, ტილოზე უკეთესი მიდგომა ჩანდა, რადგან მე მაქვს წვდომა ნაგულისხმევი განლაგების მენეჯერზე, ასევე, იყო მრავალი UI წინასწარ ჩაშენებული კომპონენტი, რომელიც გახდის ამ იდეალურ არჩევანს სკალირებისას.
მე ვგეგმავდი ტილოს სიმულაციას ორი განსხვავებული div-ის ერთი შიდა და გარე კონტეინერის გამოყენებით.
ახლა მასშტაბირების და პანელის შექმნა საკმაოდ მარტივი იყო განსახორციელებელი, რადგან CSS-ს უკვე ჰქონდა ტრანსფორმაცია, მასშტაბირება და თარგმნა.
პირველ რიგში, ამის განსახორციელებლად, მე უნდა მქონოდა კონტეინერი, რომელსაც ტილო უჭირავს. ახლა ეს ტილო არის უხილავი ელემენტი (დაფარვის გარეშე), აქ ყველა ელემენტი იშლება და გამოიყენება მასშტაბირება და თარგმანი.
მასშტაბის გასადიდებლად მომიწია მასშტაბის გაზრდა და გასადიდებლად მისი შემცირება.
სცადეთ ეს მარტივი მაგალითი. ( +
გასადიდებლად და -
გასადიდებლად)
პანინგი მუშაობდა ანალოგიურად
დაწყებისას მე გამოვიკვლიე რამდენიმე ბიბლიოთეკა, როგორიცაა
კვლევის შემდეგ დავინახე, რომ 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. } ]
ახლა მინდოდა აქტივები ატვირთული გვერდითა ზოლში, რომელიც ხელმისაწვდომი იყო ვიჯეტების ხელსაწყოთა ზოლით. მაგრამ ყოველთვის, როცა გვერდითა ჩანართებს ვცვლი, ხელახალი რენდერი იწვევს ატვირთული აქტივების გაქრობას.
Redux-ის ერთ-ერთი ყველაზე დიდი შეზღუდვა არის ის, რომ მხოლოდ სერიული მონაცემების შენახვა შეგიძლიათ. არასერიული მონაცემები, როგორიცაა სურათი, ვიდეო, სხვა აქტივები, ვერ შეინახება redux-ზე. ეს გაართულებს საერთო მონაცემების გადაცემას სხვადასხვა კომპონენტის გარშემო.
ამის დაძლევის ერთ-ერთი გზაა React Context-ის გამოყენება. მოკლედ, React Context უზრუნველყოფს მონაცემთა გადაცემის გზას კომპონენტის ხეზე, ყოველ დონეზე ხელნაკეთი რეკვიზიტების გადაცემის გარეშე.
ყველაფერი, რაც მე უნდა გამეკეთებინა, რომ მონაცემები სხვადასხვა კომპონენტში მქონოდა, იყო მისი გადატანა React კონტექსტური პროვაიდერის გარშემო.
მე შევქმენი ჩემი საკუთარი კონტექსტის პროვაიდერები ორი რამისთვის:
აქ არის მარტივი მაგალითი იმისა, თუ როგორ გამოვიყენე 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 დანამატების მხარდასაჭერად.
მე არ მქონდა ბექენდი ან დარეგისტრირება და იყო უამრავი კომპანია, რომელიც უზრუნველყოფდა უფასო ჰოსტინგს სტატიკური გვერდებისთვის. ჯერ გადავწყვიტე ვერსელთან წავსულიყავი, მაგრამ ხშირად მინახავს ვერსელის უფასო საბურავის დაცემა, თუ ძალიან ბევრი მოთხოვნა იყო.
სწორედ მაშინ გავიგე ამის შესახებ
ერთადერთი მინუსი იყო აშენების დრო საკმაოდ ნელი და აკლდა საკმაოდ ცოტა დოკუმენტაცია.
build ნაბიჯის ყველაზე გამაღიზიანებელი ნაწილი იყო build მარცხი, Vercel-ზე მუშაობდა, cloudflare გვერდებზე არა??? ჟურნალები ასევე არ იყო ნათელი. და გვაქვს უფასო საბურავები, თვეში მხოლოდ 500 აწყობა გვაქვს, ამიტომ ბევრის დაკარგვა არ მინდოდა
საათობით ვცდილობდი, შემდეგ გადავწყვიტე უწყვეტი ინტეგრაცია დამეყენებინა ცარიელ სტრიქონზე
CI='' npm install
და ბოლოს პირდაპირ ეთერში გავიდა.
ამ ყველაფერს საჯაროდ ვაშენებდი. გაინტერესებთ, რომ ის გადაიზარდა მარტივი გვერდითი ზოლიდან სრულად აფეთქებულ Drag n drop Builder-მდე, შეგიძლიათ შეამოწმოთ მთელი
#საჯაროში აშენება
ოჰ! არ დაგავიწყდეთ თვალი ადევნოთ განახლებებს
თუ მოგეწონათ ამ ტიპის კონტენტი, მე დავწერ უფრო მეტ ბლოგს, რომელიც უფრო დეტალურად იქნება განხილული, თუ როგორ ვგეგმავ და ავაშენებ პროდუქტებს, შემდეგ კი შეგიძლიათ გამოიწეროთ ჩემი საინფორმაციო ბიულეტენი :)