bonsoir, je suis un peu bloquer sur mes combobox en cascades.
en premier je veux que quand je selectionne "toutes annees" cela selectionne toutes les annees, mais que quand je de-selectionne "toutes annees" alors toutes les annees de la liste deroulante se de-selectionne et egalement cela pour les autres combobox "AAAAMM", "marque", "type" et "machine". de plus j'aimerais bien que mes listes deroulantes soient en cascades, la selection de 1 ou 2 annees selectionnent les anneesmois correspondante dans "AAAAMM" et ainsi de suite.
Je vous recmercie par avance pour l'aide que vous pourrez me fournir.
import tkinter as tk
from tkinter import ttk, messagebox
import pandas as pd
import os
class CheckboxDropdown(ttk.Frame):
def __init__(self, parent, values, label, callback=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.values = values
self.selected_values = []
self.label = label
self.callback = callback
# Bouton pour ouvrir la liste déroulante
self.button = ttk.Button(self, text=f"Sélectionner {self.label}", command=self.toggle_dropdown)
self.button.pack()
# Fenêtre popup pour la liste déroulante
self.popup = tk.Toplevel(self)
self.popup.withdraw()
self.popup.overrideredirect(True)
# Cadre pour contenir les cases à cocher
self.checkbox_frame = ttk.Frame(self.popup)
self.checkbox_frame.pack(padx=10, pady=10)
# Cases à cocher pour chaque valeur
self.checkbox_vars = {}
for value in self.values:
var = tk.BooleanVar(value=False)
self.checkbox_vars[value] = var
checkbox = ttk.Checkbutton(self.checkbox_frame, text=value, variable=var, command=self.update_selection)
checkbox.pack(anchor="w")
# Bouton pour valider la sélection
ttk.Button(self.popup, text="Valider", command=self.toggle_dropdown).pack(pady=5)
def toggle_dropdown(self):
"""Affiche ou masque la liste déroulante."""
if self.popup.winfo_viewable():
self.popup.withdraw()
else:
# Positionne la fenêtre popup juste en dessous du bouton
self.popup.deiconify()
self.popup.geometry(f"+{self.button.winfo_rootx()}+{self.button.winfo_rooty() + self.button.winfo_height()}")
def update_selection(self):
"""Met à jour les valeurs sélectionnées."""
self.selected_values = [value for value, var in self.checkbox_vars.items() if var.get()]
# Identifier l'option "Toutes les ..." ou "Tous les ..." dynamiquement
if self.label.lower() == "types":
all_option = "Tous les types"
else:
all_option = f"Toutes les {self.label.lower()}"
# Si "Toutes les ..." ou "Tous les ..." est sélectionné, sélectionner toutes les autres cases
if all_option in self.selected_values:
self.selected_values = self.values[1:] # Sélectionner toutes les options sauf "Toutes les ..."
for value, var in self.checkbox_vars.items():
var.set(True)
elif all_option not in self.selected_values and all(var.get() for var in self.checkbox_vars.values()):
# Si toutes les cases sont cochées manuellement, décocher "Toutes les ..."
self.checkbox_vars[all_option].set(False)
if self.callback:
self.callback(self.selected_values)
def get_selected_values(self):
"""Retourne les valeurs sélectionnées."""
return self.selected_values
def update_values(self, new_values):
"""Met à jour les valeurs disponibles dans la liste déroulante."""
self.values = new_values
for widget in self.checkbox_frame.winfo_children():
widget.destroy()
self.checkbox_vars = {}
for value in self.values:
var = tk.BooleanVar(value=False)
self.checkbox_vars[value] = var
checkbox = ttk.Checkbutton(self.checkbox_frame, text=value, variable=var, command=self.update_selection)
checkbox.pack(anchor="w")
class Page1(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.df = None
self.create_widgets()
def create_widgets(self):
"""Crée les widgets de la page."""
self.configure(style="Page1.TFrame")
dropdown_frame = ttk.Frame(self)
dropdown_frame.pack(pady=20)
self.load_dropdown_data(dropdown_frame)
def load_dropdown_data(self, dropdown_frame):
"""Charge les données dans les listes déroulantes."""
file_path = r"C:\Users\user\Desktop\MesScripts\donnees\data.xlsx"
if not os.path.exists(file_path):
messagebox.showerror("Erreur", f"Le fichier {file_path} n'existe pas.")
return
try:
self.df = pd.read_excel(file_path, sheet_name="analyses")
# Traitement des colonnes si elles existent
if "Date" in self.df.columns:
self.df["Date"] = pd.to_datetime(self.df["Date"], errors="coerce")
self.df = self.df.dropna(subset=["Date"])
self.df["AAAAMM"] = self.df["Date"].dt.strftime("%Y%m")
years = sorted(self.df["Date"].dt.year.unique().astype(str).tolist())
years.insert(0, "Toutes les années")
self.year_dropdown = CheckboxDropdown(
dropdown_frame, values=years, label="Années", callback=self.on_selection_change
)
self.year_dropdown.pack(side="left", padx=10)
aaaamm_values = sorted(self.df["AAAAMM"].unique().tolist())
aaaamm_values.insert(0, "Toutes les AAAAMM")
self.aaaamm_dropdown = CheckboxDropdown(
dropdown_frame, values=aaaamm_values, label="AAAAMM", callback=self.on_selection_change
)
self.aaaamm_dropdown.pack(side="left", padx=10)
if "Marque" in self.df.columns:
marques = sorted(self.df["Marque"].dropna().unique().tolist())
marques.insert(0, "Toutes les marques")
self.marque_dropdown = CheckboxDropdown(
dropdown_frame, values=marques, label="Marques", callback=self.on_selection_change
)
self.marque_dropdown.pack(side="left", padx=10)
if "Type" in self.df.columns:
types = sorted(self.df["Type"].dropna().unique().tolist())
types.insert(0, "Tous les types")
self.type_dropdown = CheckboxDropdown(
dropdown_frame, values=types, label="Types", callback=self.on_selection_change
)
self.type_dropdown.pack(side="left", padx=10)
if "Machine" in self.df.columns:
machines = sorted(self.df["Machine"].dropna().unique().tolist())
machines.insert(0, "Toutes les machines")
self.machine_dropdown = CheckboxDropdown(
dropdown_frame, values=machines, label="Machines", callback=self.on_selection_change
)
self.machine_dropdown.pack(side="left", padx=10)
except Exception as e:
messagebox.showerror("Erreur", f"Erreur lors de la lecture du fichier Excel : {e}")
def filter_data(self):
"""Filtre les données en fonction des sélections."""
filtered_df = self.df
if not self.df.empty:
selected_years = self.year_dropdown.get_selected_values()
if selected_years and "Toutes les années" not in selected_years:
filtered_df = filtered_df[filtered_df["Date"].dt.year.astype(str).isin(selected_years)]
selected_aaaamm = self.aaaamm_dropdown.get_selected_values()
if selected_aaaamm and "Toutes les AAAAMM" not in selected_aaaamm:
filtered_df = filtered_df[filtered_df["AAAAMM"].isin(selected_aaaamm)]
selected_marques = self.marque_dropdown.get_selected_values()
if selected_marques and "Toutes les marques" not in selected_marques:
filtered_df = filtered_df[filtered_df["Marque"].isin(selected_marques)]
selected_types = self.type_dropdown.get_selected_values()
if selected_types and "Tous les types" not in selected_types:
filtered_df = filtered_df[filtered_df["Type"].isin(selected_types)]
selected_machines = self.machine_dropdown.get_selected_values()
if selected_machines and "Toutes les machines" not in selected_machines:
filtered_df = filtered_df[filtered_df["Machine"].isin(selected_machines)]
return filtered_df
def on_selection_change(self, _):
"""Callback pour gérer les changements dans les Dropdowns."""
# Si "Toutes les années" est sélectionné, sélectionnez toutes les années et réinitialisez les autres combobox
selected_years = self.year_dropdown.get_selected_values()
if "Toutes les années" in selected_years:
self.year_dropdown.selected_values = self.df["Date"].dt.year.astype(str).unique().tolist() # Sélectionne toutes les années
self.aaaamm_dropdown.update_values(sorted(self.df["AAAAMM"].unique().tolist()))
self.marque_dropdown.update_values(sorted(self.df["Marque"].dropna().unique().tolist()))
self.type_dropdown.update_values(sorted(self.df["Type"].dropna().unique().tolist()))
self.machine_dropdown.update_values(sorted(self.df["Machine"].dropna().unique().tolist()))
else:
# Filtrer les autres combobox en fonction de l'année sélectionnée
filtered_aaaamm = self.df[self.df["Date"].dt.year.astype(str).isin(selected_years)]
aaaamm_values = sorted(filtered_aaaamm["AAAAMM"].unique().tolist())
aaaamm_values.insert(0, "Toutes les AAAAMM")
self.aaaamm_dropdown.update_values(aaaamm_values)
selected_aaaamm = self.aaaamm_dropdown.get_selected_values()
if "Toutes les AAAAMM" not in selected_aaaamm:
filtered_marques = self.df[self.df["AAAAMM"].isin(selected_aaaamm)]
marques_values = sorted(filtered_marques["Marque"].dropna().unique().tolist())
marques_values.insert(0, "Toutes les marques")
self.marque_dropdown.update_values(marques_values)
selected_marques = self.marque_dropdown.get_selected_values()
if "Toutes les marques" not in selected_marques:
filtered_types = self.df[self.df["Marque"].isin(selected_marques)]
types_values = sorted(filtered_types["Type"].dropna().unique().tolist())
types_values.insert(0, "Tous les types")
self.type_dropdown.update_values(types_values)
selected_types = self.type_dropdown.get_selected_values()
if "Tous les types" not in selected_types:
filtered_machines = self.df[self.df["Type"].isin(selected_types)]
machines_values = sorted(filtered_machines["Machine"].dropna().unique().tolist())
machines_values.insert(0, "Toutes les machines")
self.machine_dropdown.update_values(machines_values)
filtered_df = self.filter_data()
print(filtered_df) # Débogage : Affiche les données filtrées
if __name__ == "__main__":
root = tk.Tk()
root.title("Sélection multiple avec Tkinter")
app = Page1(root)
app.pack(fill="both", expand=True)
root.mainloop()
Partager