IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

combobox en cascade


Sujet :

Python

  1. #1
    Membre éclairé
    Inscrit en
    Février 2005
    Messages
    277
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 277
    Par défaut combobox en cascade
    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()

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 577
    Par défaut
    Salut,

    Il faudrait apprendre à poster du code (la balise # dans l'éditeur de message)...
    Ce que j'ai compris c'est une tas de checkbutton où un sert à sélectionner/désélectionner les suivants.

    Vous avez intérêt (pour vous simplifier la vie) a ce que le callback qui met à jour la sélection de tous les suivants soit autre que celui qui traite les suivants.

    Si vous ne vous en sortez toujours pas, ben, il va falloir écrire un petit bout de code qui se focalise sur ce détail de votre programme (quelque lignes...)

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Probleme ComboBox en cascade
    Par YOP33 dans le forum Macros et VBA Excel
    Réponses: 16
    Dernier message: 17/01/2010, 16h08
  2. fonction pour filtrage avec des combobox en cascade
    Par Montor dans le forum Contribuez
    Réponses: 3
    Dernier message: 09/11/2009, 13h05
  3. [E-00] ComboBox en cascade + TextBox
    Par couistelle dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 20/11/2008, 11h32
  4. Combobox en cascade et sans doublons
    Par humbp dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 29/11/2007, 14h54
  5. [VBA-E] ComboBox en cascade avec correspondance dans matrice
    Par ViperSpy dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 21/06/2006, 18h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo