Issue
I am trying to only show certain columns when pressing one of the buttons on the right side, for that reason I implemented to hide the other columns by reducing their column width to 0. While this works for hiding the columns, it leaves yellow pixels in their place which just doesn't look right, see the following screenshots for reference.
Does anyone know how I can remove these pixels? (marked in yellow)
Screenshots:
Code explanation:
Display Data Sheet Window:
The data sheet window opens when the user clicks a button (e.g., "Show Data Sheet").
It uses pd.read_excel to load an Excel file into a Pandas DataFrame (df).
Window Configuration:
The window is configured to enable an interactive display of the styled DataFrame.
A ttk.Treeview widget is created to represent the columns of the DataFrame.
Column headers and widths are set.
A scrollbar is added to navigate through the Treeview.
Search Functionality:
A search field (search_entry) and a search button are added to search for specific data.
The search_data function is called when the user presses the Enter key or clicks the search button.
Buttons for Different Views:
Various buttons (e.g., "Daily Basis," "Order Basis," "Weekly Basis") are added to activate specific views.
The corresponding functions (show_tagesbasis, show_bestellbasis, show_wochenbasis) are called to hide columns and update the view.
Reset Button:
A "Reset" button is added to reset the view to its initial state.
The reset_view function is called to show all columns again and update the view.
Color Coding (commented out):
Originally, there was color coding for cells, but it has been commented out.
Relevant code:
# Import necessary libraries and modules
import tkinter as tk
from tkinter import ttk # Import themed tk module
from tkcalendar import DateEntry # Calendar functions
from babel import numbers
import datetime # Date conversion
import matplotlib
matplotlib.use("TkAgg") # Use Tkinter backend for plots
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt # Graph functions
import numpy as np # Graph functions
import matplotlib.dates as mdates # Date conversion to weekdays
import locale # X-axis graph labeling in German
from PIL import Image, ImageTk # Image functions
import pandas as pd # Import pandas for reading Excel data
from tkinter.ttk import Separator
import mplcursors # Mouseover over chart points
import warnings # Filter chart mouseover warnings: "missing pick support for PolyCollection and that the Selection.target.index attribute is deprecated."
import time # For startup screen progress bar
import threading # For startup screen progress bar
from functools import partial # To link the progress bar with loading the DataFrame
from tkinter import messagebox # For error message (e.g., empty Excel data entry)
import os
def on_datenblatt_button_click():
print("Function started")
try:
# Load the Excel file
file_path = 'data/Input.xlsx'
df = pd.read_excel(file_path)
# Check if the window is already open
if hasattr(on_datenblatt_button_click, 'styled_window') and on_datenblatt_button_click.styled_window.winfo_exists():
# If yes, close the window
on_datenblatt_button_click.styled_window.destroy()
return # Exit the function to prevent reopening the window
# Round the numbers to 2 decimal places
df = df.round(2)
# Create a new window for the interactive display of the styled DataFrame
styled_window = tk.Toplevel(start_window)
styled_window.title("Data Sheet")
# Save the window as an attribute of the function to access it later
on_datenblatt_button_click.styled_window = styled_window
# Window size configuration (centered on the screen)
window_width = 1000
window_height = 600
styled_window.geometry(f'{window_width}x{window_height}')
# screen_width = styled_window.winfo_screenwidth()
# screen_height = styled_window.winfo_screenheight()
# x_coordinate = int((screen_width - window_width) / 2)
# y_coordinate = int((screen_height - window_height) / 2)
# styled_window.geometry(f'{window_width}x{window_height}+{x_coordinate}+{y_coordinate}')
# Create a ttk.Treeview widget with a style
style = ttk.Style()
style.configure("Treeview", font=('Arial', 12))
tree = ttk.Treeview(styled_window)
tree["columns"] = list(df.columns)
tree["show"] = "headings" # Do not show an empty column on the left
# Add column headers
col_width = 120
# Set the width for all columns
for col in df.columns:
tree.heading(col, text=col)
tree.column(col, width=col_width, stretch=tk.NO) # Set stretch to tk.NO and width to col_width
# Pack the Treeview widget
tree.pack(fill='both', side='left')
# Add scrollbar
scrollbar = ttk.Scrollbar(styled_window, orient='vertical', command=tree.yview)
scrollbar.pack(side='right', fill='y')
tree.configure(yscrollcommand=scrollbar.set)
# Create a frame for the search
search_frame = ttk.Frame(styled_window)
search_frame.pack(side='top', fill='x')
# Entry for the search
search_entry = ttk.Entry(search_frame)
search_entry.grid(row=0, column=0, padx=5, pady=5)
# Bind the Enter key for search
search_entry.bind('<Return>', lambda event: search_data(tree, df, search_entry.get()))
# Button for the search
search_button = ttk.Button(search_frame, text="Search", command=lambda: search_data(tree, df, search_entry.get()))
search_button.grid(row=1, column=0, padx=5, pady=5)
# An empty frame for spacing
ttk.Frame(search_frame, height=10).grid(row=2, column=0)
# Buttons for different views
tagesbasis_button = ttk.Button(search_frame, text="Daily Basis", command=lambda: show_tagesbasis(tree, df, styled_window))
tagesbasis_button.grid(row=3, column=0, padx=5, pady=5)
bestellbasis_button = ttk.Button(search_frame, text="Order Basis", command=lambda: show_bestellbasis(tree, df, styled_window))
bestellbasis_button.grid(row=4, column=0, padx=5, pady=5)
wochenbasis_button = ttk.Button(search_frame, text="Weekly Basis", command=lambda: show_wochenbasis(tree, df, styled_window))
wochenbasis_button.grid(row=5, column=0, padx=5, pady=5)
# An empty frame for spacing
ttk.Frame(search_frame, height=10).grid(row=6, column=0)
reset_button = ttk.Button(search_frame, text="Reset", command=lambda: reset_view(tree, df))
reset_button.grid(row=7, column=0, padx=5, pady=5)
# # Set colors for cells
# for tag in ['green', 'yellow', 'red']:
# tree.tag_configure(tag, background='')
# Add entries without coloring
for index, row in df.iterrows():
values = list(row)
tree.insert("", tk.END, values=values, iid=index)
# Save the selection of the latest date and index
if index == df.index[-1]:
styled_window.selected_date = row['Date']
styled_window.selected_index = index
# Set selection to the latest date
tree.selection_set(styled_window.selected_index)
tree.see(styled_window.selected_index)
except Exception as e:
print(f"Error occurred: {e}")
print("Function ended")
def search_data(tree, df, search_date):
try:
# Convert the date to a string and then search for it
matching_rows = df.index[df['Date'].astype(str).str.contains(search_date, case=False, na=False)].tolist()
if matching_rows:
tree.selection_set(matching_rows[0])
tree.see(matching_rows[0])
except Exception as e:
print(f"Error during search: {e}")
# def color_by_deviation(prognose_value, ist_value):
# color = 'green' if ist_value == 0 or prognose_value == 0 else (
# 'green' if abs(ist_value - prognose_value) / ist_value <= 0.1 else (
# 'yellow' if abs(ist_value - prognose_value) / ist_value <= 0.3 else 'red'
# )
# )
# return color
def show_tagesbasis(tree, df, styled_window):
reset_view(tree, df)
hide_column(tree, df, styled_window, '(Actual) Order', 'Forecast Order', '(Actual) Week', 'Forecast Week')
def show_bestellbasis(tree, df, styled_window):
reset_view(tree, df)
hide_column(tree, df, styled_window, '(Actual) Sales', 'Forecast Sales', '(Actual) Week', 'Forecast Week')
def show_wochenbasis(tree, df, styled_window):
reset_view(tree, df)
hide_column(tree, df, styled_window, '(Actual) Sales', 'Forecast Sales', '(Actual) Order', 'Forecast Order')
def reset_view(tree, df):
show_all_columns(tree, df)
# reset_colors(tree)
update_entries(tree, df)
def hide_column(tree, df, styled_window, *columns_to_hide):
for col in columns_to_hide:
# Hide the column
tree.column(col, width=0, stretch=tk.NO)
# Update the Treeview widget
styled_window.update_idletasks()
def update_entries(tree, df):
for index, row in df.iterrows():
values = list(row)
tree.item(index, values=values)
def show_all_columns(tree, df):
for col in df.columns:
tree.column(col, width=120, stretch=tk.NO)
Solution
There is a displaycolumns
option of Treeview
widget to select which columns to be shown.
Below is an example:
import tkinter as tk
from tkinter import ttk
import pandas as pd
root = tk.Tk()
root.minsize(1000, 300)
style = ttk.Style()
style.theme_use("default")
style.configure("Treeview", font=("Arial", 12))
columns = [f"col#{i}" for i in range(1, 8)]
tree = ttk.Treeview(root, columns=columns, show="headings")
tree.pack(side="left", fill="both", expand=1)
for col in columns:
tree.heading(col, text=col)
tree.column(col, width=120, stretch=0)
frame = tk.Frame(root)
frame.pack(side="right", fill="y")
# checkboxes for selecting columns to be shown
variables = {}
for col in columns:
var = tk.IntVar(value=1)
tk.Checkbutton(frame, text=col, variable=var).pack(fill="x", anchor="w")
variables[col] = var
# function to show selected columns
def update_tree():
show = [col for col,var in variables.items() if var.get()]
tree.configure(displaycolumns=show)
tk.Button(frame, text="Update", command=update_tree).pack()
# sample dataframe
df = pd.DataFrame([[j*10+i for i in range(1, len(columns)+1)] for j in range(1, 10)])
# insert data into treeview
for index, row in df.iterrows():
values = list(row)
tree.insert("", "end", values=values, iid=index)
root.mainloop()
All columns shown:
Some columns hidden:
Answered By - acw1668
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.