Próbuję utworzyć aplikację z kategorii pakowanie paczek. Nie dam rady z algorytmami umieszczania paczek ale przydałby mi się programik który wizualnie pokarze rozmieszczenie. Zacząłem pisać kod ale nie bardzo wiem jak przenosić paczki pomiędzy oknami? Jak aktualizować kontenery i paczki w swoich oknach aby metoda drag and drop działała. Trzeba na bieżąco aktualizować na której kanwie dana paczka/kontener jest.
Poniższy program pokarze mniej więcej jak powinien wyglądać efekt końcowy. Aby "zadziałał" trzeba wcisnąć przyciski "Paczki" i "Kontenery" oraz wskazać plik txt z zawartością np. "24x34
34x35"
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import re
import logging
paczki = []
kontenery = []
# Funkcja do obsługi przycisku "Paczki" i "Kontenery"
def open_file(source):
# Otwórz okno wyboru pliku
file_path = filedialog.askopenfilename(
title="Wybierz plik",
filetypes=[("Pliki tekstowe", "*.txt")]
)
# Jeśli użytkownik wybrał plik, odczytaj jego zawartość i wypisz ją w konsoli
if file_path:
try:
with open(file_path, 'r', encoding='utf-8') as file:
licznik = 1
for line in file:
# Dopasowanie dwóch pierwszych liczb (całych liczb całkowitych)
liczby = re.findall(r'-?\d+', line)
if len(liczby) >= 2:
# Dodajemy dwie pierwsze liczby do paczki jako krotkę
if source == "Paczki":
paczki.append((licznik, int(liczby[0]), int(liczby[1])))
licznik += 1
else:
kontenery.append((licznik, int(liczby[0]), int(liczby[1])))
licznik += 1
if len(paczki) > 0 and len(kontenery) > 0:
logging.debug(f'{paczki=},{kontenery=}')
update_canvas()
except Exception as e:
print(f"Nie udało się odczytać pliku: {e}")
# Funkcja do aktualizacji kanw w lewym panelu
def update_canvas():
canvas = lg_canvas
items = paczki
color = "lightblue"
canvas.delete("all") # Wyczyść obecne rysunki
# Rysowanie prostokątów
y_offset = 10 # Odstęp między prostokątami
width_reprezentacji = 120
height_reprezentacji = 30
for item in items:
# Item[1] to szerokość, item[2] to wysokość
width = item[1]
height = item[2]
# Rysowanie prostokąta
canvas.create_rectangle(10, y_offset, 10 + width_reprezentacji, y_offset + height_reprezentacji, fill=color)
canvas.create_text(10 + width_reprezentacji / 2, y_offset + height_reprezentacji / 2, text=f"{width}x{height}", fill="black")
y_offset += height_reprezentacji + 10 # Przesunięcie w dół na następny prostokąt
canvas = ld_canvas
items = kontenery
color = "lightgreen"
canvas.delete("all") # Wyczyść obecne rysunki
# Rysowanie prostokątów
y_offset = 10
for item in items:
# Item[1] to szerokość, item[2] to wysokość
width = item[1]
height = item[2]
# Rysowanie prostokąta
canvas.create_rectangle(10, y_offset, 10 + width_reprezentacji, y_offset + height_reprezentacji, fill=color)
canvas.create_text(10 + width_reprezentacji / 2, y_offset + height_reprezentacji / 2, text=f"{width}x{height}", fill="black")
y_offset += height_reprezentacji + 10 # Przesunięcie w dół na następny prostokąt
# Główna aplikacja
def main():
logging.basicConfig(level=logging.DEBUG, # filename="paczki_log.log",
format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug("-------------Rozpoczęcie programu------------------") # debug,info,warning,critical
global lg_canvas, ld_canvas # Umożliwiamy dostęp do kanw z funkcji update_canvas
root = tk.Tk()
root.title("Paczki v0.1")
root.minsize(900, 500)
# Lewe górne okno
lg_frame = ttk.Frame(root)
lg_frame.place(x=0, y=0, relwidth=0.2, relheight=0.6)
# Przycisk na górze lewego okna
button_paczki = ttk.Button(lg_frame, text="Paczki", command=lambda: open_file("Paczki"))
button_paczki.place(x=10, y=10, relwidth=0.8) # Ustawienie przycisku na górze (10px od góry i 10px od lewej)
lg_canvas = tk.Canvas(lg_frame, width=120, height=300)
lg_scrollbar = ttk.Scrollbar(lg_frame, orient="vertical", command=lg_canvas.yview)
lg_canvas.configure(yscrollcommand=lg_scrollbar.set)
lg_canvas.place(x=0, y=40, relwidth=0.9, relheight=1) # Przesunięcie o 40px w dół, by nie nakładał się na przycisk
lg_scrollbar.place(relx=0.9, y=0, relwidth=0.1, relheight=1)
lg_canvas.config(scrollregion=lg_canvas.bbox("all"))
# Lewe dolne okno
ld_frame = ttk.Frame(root)
ld_frame.place(x=0, rely=0.6, relwidth=0.2, relheight=0.4)
# Przycisk na górze lewego okna
button_kontenery = ttk.Button(ld_frame, text="Kontenery", command=lambda: open_file("Kontenery"))
button_kontenery.place(x=10, y=10, relwidth=0.8) # Ustawienie przycisku na górze (10px od góry i 10px od lewej)
ld_canvas = tk.Canvas(ld_frame, width=120, height=300)
ld_scrollbar = ttk.Scrollbar(ld_frame, orient="vertical", command=ld_canvas.yview)
ld_canvas.configure(yscrollcommand=ld_scrollbar.set)
ld_canvas.place(x=0, y=40, relwidth=0.9, relheight=1)
ld_scrollbar.place(relx=0.9, y=0, relwidth=0.1, relheight=1)
ld_canvas.config(scrollregion=ld_canvas.bbox("all"))
# Prawe okno
right_frame = ttk.Frame(root)
right_frame.place(relx=0.2, y=0, relwidth=0.8, relheight=1)
right_canvas = tk.Canvas(right_frame, width=120, height=300)
right_scrollbar = ttk.Scrollbar(right_frame, orient="horizontal", command=right_canvas.xview)
right_canvas.configure(xscrollcommand=right_scrollbar.set)
right_canvas.place(x=0, y=0, relwidth=1, relheight=1)
right_scrollbar.place(x=0, rely=0.9, relwidth=1, relheight=0.1)
right_canvas.create_rectangle(20,20,100,200,fill = 'lightgreen')
right_canvas.create_rectangle(40, 40, 60, 70, fill='lightblue')
right_canvas.create_rectangle(220,20,400,400,fill = 'lightgreen')
right_canvas.create_rectangle(240, 240, 310, 310, fill='lightblue')
right_canvas.config(scrollregion=right_canvas.bbox("all"))
# Uruchomienie pętli głównej
root.mainloop()
# Sprawdzenie, czy plik jest uruchamiany bezpośrednio
if __name__ == "__main__":
main()
Może lepiej na jednej kanwie tylko podzielić liniami? Tylko wtedy jak zrobić przewijanie jeżeli będzie więcej paczek. Jak proponujecie podejść do tematu aby takiemu laikowi jak ja udało się to stworzyć?