Custom Table In Python Tkinter

How to Create Custom Table In Python Tkinter

How to Create Custom Table In Python Tkinter


In this Python tutorial we will create a custom table with a fixed header and scrollable content using the Tkinter library for the graphical user interface. 
The table lists names and ages with alternating row colors.

What We Are Gonna Use In This Project:

- Python Programming Language.
- Tkinter for GUI.
- VS Code Editor.




Project Source Code:



import tkinter as tk
from tkinter import ttk


class CustomTable(tk.Tk):
def __init__(self):
super().__init__()
self.title("Custom Table")
self.geometry("400x300")
self.table_data = [
("John", "Doe", "25"), ("Jane", "Smith", "30"),
("Alice", "Johnson", "22"), ("Bob", "Brown", "35"),
("Eve", "Wilson", "28"), ("John", "Doe", "25"),
("Jane", "Smith", "30"), ("Alice", "Johnson", "22"),
("Bob", "Brown", "35"), ("Eve", "Wilson", "28"),
("John", "Doe", "25"), ("Jane", "Smith", "30"),
("Alice", "Johnson", "22"), ("Bob", "Brown", "35"),
("Eve", "Wilson", "28"), ("John", "Doe", "25"),
("Jane", "Smith", "30"), ("Alice", "Johnson", "22"),
("Bob", "Brown", "35"), ("Eve", "Wilson", "28"),
("John", "Doe", "25"), ("Jane", "Smith", "30"),
("Alice", "Johnson", "22"), ("Bob", "Brown", "35"),
("Eve", "Wilson", "28"), ("John", "Doe", "25"),
("Jane", "Smith", "30"), ("Alice", "Johnson", "22"),
("Bob", "Brown", "35"), ("Eve", "Wilson", "28"),
("John", "Doe", "25"), ("Jane", "Smith", "30"),
("Alice", "Johnson", "22"), ("Bob", "Brown", "35"),
("Eve", "Wilson", "28"), ("John", "Doe", "25"),
("Jane", "Smith", "30"), ("Alice", "Johnson", "22"),
("Bob", "Brown", "35"), ("Eve", "Wilson", "28"),
("John", "Doe", "25"), ("Jane", "Smith", "30"),
("Alice", "Johnson", "22"), ("Bob", "Brown", "35"),
("Eve", "Wilson", "28"), ("John", "Doe", "25"),
("Jane", "Smith", "30"), ("Alice", "Johnson", "22"),
("Bob", "Brown", "35"), ("Eve", "Wilson", "28"),
("John", "Doe", "25"), ("Jane", "Smith", "30"),
("Alice", "Johnson", "22"), ("Bob", "Brown", "35"),
("Eve", "Wilson", "28"),
]
self.table_frame = TablePanel(self, self.table_data)
self.table_frame.pack(fill=tk.BOTH, expand=True)

class TablePanel(tk.Frame):
def __init__(self, parent, table_data):
super().__init__(parent)

# Fixed header frame
self.fixed_frame = tk.Frame(self)
self.fixed_frame.pack(side=tk.TOP, fill=tk.X)

# Fixed header canvas
self.fixed_canvas = tk.Canvas(self.fixed_frame, bg="#4caf50", height=30)
self.fixed_canvas.pack(fill=tk.X)

# Scrollable table canvas
self.table_canvas = tk.Canvas(self, bg="white", height=300)
self.table_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbar
self.scrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL,
        command=self.table_canvas.yview)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

# Configure canvas scrolling
self.table_canvas.configure(yscrollcommand=self.scrollbar.set)
self.table_data = table_data
self.draw_table()


def draw_table(self):
x, y = 0, 0
row_height = 30
table_width = 400

# Draw fixed header
self.fixed_canvas.create_rectangle(x, y, x + table_width, y + row_height,
        fill="#4caf50")
self.fixed_canvas.create_text(x + 70, y + 15, text="First Name",
        font=("Arial", 14, "bold"), fill="white")
self.fixed_canvas.create_text(x + 190, y + 15, text="Last Name",
        font=("Arial", 14, "bold"), fill="white")
self.fixed_canvas.create_text(x + 320, y + 15, text="Age",
        font=("Arial", 14, "bold"), fill="white")

#y += row_height

for i, row_data in enumerate(self.table_data):
# Alternate row colors
fill_color = "#f9f1ee" if i % 2 == 0 else "#b5f2ee"
# Draw table rows
self.table_canvas.create_rectangle(x, y, x + table_width, y + row_height,
            fill=fill_color)
self.table_canvas.create_text(x + 70, y + 20, text=row_data[0],
            font=("Arial", 12), fill="black")
self.table_canvas.create_text(x + 190, y + 20, text=row_data[1],
            font=("Arial", 12), fill="black")
self.table_canvas.create_text(x + 320, y + 20, text=row_data[2],
            font=("Arial", 12), fill="black")

y += row_height

self.table_canvas.configure(scrollregion=self.table_canvas.bbox("all"))




if __name__ == "__main__":
app = CustomTable()
app.mainloop()



The Final Result:

Custom Table In Python Tkinter











JavaScript - Array Navigation Form with JavaScript and HTML

How to Create an Array Navigation Form with JavaScript and HTML 


How to Create an Array Navigation Form with JavaScript and HTML


In this Javascript Tutorial, we will see how to create an interactive form for navigating through an array of data.
Users can click navigation buttons to view the details of different people from the array, the form fields and image are updated accordingly.



Project Source Code:



<!DOCTYPE html>
<html>
<head>
<title>Array Navigation Form</title>

<style>
*{margin: 0; padding: 0; box-sizing: border-box;}

body{ font-family: Arial, sans-serif; background-color: #f2f2f2; }

.container{ background-color: #fff; padding: 20px; margin: 50px auto;
width: 50%; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2)
}

form button{ padding: 10px 20px; background-color: #4caf50; color: #fff;
border: none; border-radius: 5px; margin: 10px; width: 21%;
cursor: pointer; text-transform: uppercase;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease-in-out;
}
form button:hover{ background-color: #3e8e41; }

div label{ display: inline-block; margin: 10px 0; font-weight: bold; color: #444;
text-align: right; width: 22%; font-size: 20px;
}

div input[type="text"]{ display: inline-block; margin: 10px; padding: 10px; border: none;
border-radius: 5px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease-in-out; width: 70%; }

div input[type="text"]:focus{ outline: none; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);}
#image{ display: flex; align-items: flex-start; }
#image label{margin-right: 10px;}

#image img{ margin: 10px; width: 30%; border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
}


</style>

</head>
<body>

<div class="container">
<form>
<button id="first-btn">First</button>
<button id="next-btn">Next</button>
<button id="prev-btn">Previous</button>
<button id="last-btn">Last</button>
</form>
<div class="inputs">
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<br>
<label for="age">Age:</label>
<input type="text" id="age" name="age">
<br>
<label for="dob">Date of Birth:</label>
<input type="text" id="dob" name="dob">
<br>
<div id="image">
<label for="pic">Image:</label>
<img id="pic" src="">
</div>
</div>
</div>


<script>

// Define an array of objects with properties name, age, dob and image
const peoples = [
{name:"Alice", age:25, dob:new Date("1997-03-15"), image:"images/avatar1.png"},
{name: "Bob", age: 32, dob: new Date("1990-09-02"), image: "images/avatar2.png"},
{name: "Charlie",age: 42,dob: new Date("1980-05-20"),image: "images/avatar3.png"},
{name: "David",age: 28,dob: new Date("1994-12-06"),image: "images/avatar4.png"},
{name: "Emma",age: 35,dob: new Date("1987-07-19"),image: "images/avatar5.png"},
{name: "Frank",age: 50,dob: new Date("1972-10-31"),image: "images/avatar6.png"},
{name: "Grace",age: 22,dob: new Date("2000-01-01"),image: "images/avatar7.png"}
];

// Initialize the currentIndex variable to 0
let currentIndex = 0;

// Define a function to navigate through the array
function navigateArray(event){
event.preventDefault();

// Check which button was clicked and update the currentIndex accordingly
switch(event.target.id){
case 'first-btn':
currentIndex = 0;
break;
case 'next-btn':
currentIndex = currentIndex <peoples.length-1 ? currentIndex + 1 : peoples.length - 1;
break;
case 'prev-btn':
currentIndex = currentIndex > 0 ? currentIndex - 1 : 0;
break;
case 'last-btn':
currentIndex = peoples.length - 1;
break;

}

// Update the UI with the current item by setting the value of input elements
// and image source to corresponding properties
document.getElementById('name').value = peoples[currentIndex].name;
document.getElementById('age').value = peoples[currentIndex].age;
// Display date in yyyy-mm-dd format
document.getElementById('dob').value = peoples[currentIndex].dob.toLocaleDateString();
document.getElementById('pic').src = peoples[currentIndex].image;

}


// Add click event listeners to navigation buttons
document.getElementById('first-btn').addEventListener('click', navigateArray);
document.getElementById('next-btn').addEventListener('click', navigateArray);
document.getElementById('prev-btn').addEventListener('click', navigateArray);
document.getElementById('last-btn').addEventListener('click', navigateArray);

// Initialize the UI with the values of the first object in the array
document.getElementById('name').value = peoples[currentIndex].name;
document.getElementById('age').value = peoples[currentIndex].age;
// Display date in yyyy-mm-dd format
document.getElementById('dob').value = peoples[currentIndex].dob.toLocaleDateString();
document.getElementById('pic').src = peoples[currentIndex].image;

</script>
</body>
</html>





Code Explanation:

this JavaScript code, allows users to navigate through an array of data and images by clicking on navigation buttons.

This JavaScript code performs the following actions:

1 - Create an array called 'peoples,' containing objects with properties such as name, age, date of birth (dob), and an image URL for each person.

2 - Create a function called navigateArray(event) that handles button clicks and updates the form based on the clicked button.

3 - Event listeners are added to each of the navigation buttons to trigger the navigateArray function when they are clicked.

4 - The initial values in the input fields and the image source are set to the properties of the first person in the peoples array.




OUTPUT:

Array Navigation Form with JavaScript and HTML










Paginated Table Using Tkinter In Python

How To Create a Paginated Table Using Tkinter In Python

Paginated Table Using Tkinter In Python


In this Python tutorial we will create a paginated table using the Tkinter library for the graphical user interface. 
The table shows a list of data and includes pagination controls with "Previous" and "Next" buttons. 
These buttons allow you to navigate through different pages of data, updating the rows displayed according to the current page.

What We Are Gonna Use In This Project:

- Python Programming Language.
- Tkinter for GUI.
- VS Code Editor.




Project Source Code:




import tkinter as tk
from tkinter import ttk

class TablePaginationFrame(tk.Tk):
def __init__(self):
super().__init__()
self.title("Paginated Table")
self.geometry("400x300")
self.create_ui()

def create_ui(self):
ttk.Style().configure("TButton", padding=5, relief="flat")

# Create a Treeview widget for displaying the table
self.table_model = ttk.Treeview(self, columns=("ID", "Name"),
        show="headings", height=5)
self.table_model.heading("ID", text="ID")
self.table_model.heading("Name", text="Name")
self.table_model.column("ID", width="50")
self.table_model.column("Name", width="50")
self.table_model.tag_configure("oddrow", background="#f0f0f0")

# Create a vertical scrollbar for the table
scroll_y = ttk.Scrollbar(self, orient="vertical",
        command=self.table_model.yview)
self.table_model.configure(yscroll=scroll_y.set)

# Create Previous and Next buttons for pagination
self.prev_button = ttk.Button(self, text="Previous", command=self.prev_page)
self.next_button = ttk.Button(self, text="Next", command=self.next_page)

# Grid layout for widgets
self.table_model.grid(row = 0, column = 0, columnspan = 2, padx = 0,
        pady = 5, sticky = "nsew")
scroll_y.grid(row = 0, column = 2, sticky="nsew")
self.prev_button.grid(row=1, column=0, padx=5, pady=5, sticky="w")
self.next_button.grid(row=1, column=1, padx=5, pady=5, sticky="e")

# Configure grid weights to make the table expandable
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)

# Initialize pagination parameters
self.current_page = 1
self.items_per_page = 10
self.update_table_model()


def prev_page(self):
# Go to the previous page if available
if self.current_page > 1:
self.current_page -= 1
self.update_table_model()

def next_page(self):
# Go to the next page if available
if self.current_page < self.get_total_pages():
self.current_page += 1
self.update_table_model()


def update_table_model(self):
# Clear the current table contents
self.table_model.delete(*self.table_model.get_children())

# Calculate the indices for the start and end of the current page
start_index = (self.current_page - 1) * self.items_per_page
end_index = min(start_index + self.items_per_page, len(self.get_data()))

# Iterate over the data for the current page
for i in range(start_index, end_index):
# Get the values for the current row
values = self.get_data()[i]
# Determine tags for the row to set alternate row background colors
tags = ("oddrow") if i % 2 != 0 else ()
# Insert the row into the table with the calculated values and tags
self.table_model.insert("", "end", values = values, tags=tags)
# Disable/enable pagination buttons based on current page
self.prev_button["state"] = tk.NORMAL if self.current_page > 1
        else tk.DISABLED
self.next_button["state"] = tk.NORMAL
        if self.current_page < self.get_total_pages() else tk.DISABLED

def get_total_pages(self):
# Calculate total pages based on data length and items per page
return -(-len(self.get_data()) / self.items_per_page)


def get_data(self):
# Mock data for the table
return [
(1, "Apple"), (2, "Banana"), (3, "Orange"), (4, "Grapes"),
                (5, "Strawberry"),
(6, "Watermelon"), (7, "Pineapple"), (8, "Mango"), (9, "Peach"),
                (10, "Kiwi"),
(11, "Blueberry"), (12, "Cherry"), (13, "Raspberry"), (14, "Pear"),
                (15, "Plum"),
(16, "Avocado"), (17, "Coconut"), (18, "Lemon"), (19, "Pomegranate"),
                (20, "Papaya"),
(21, "Apricot"), (22, "Blackberry"), (23, "Cantaloupe"),
                (24, "Cranberry"), (25, "Fig"),
(26, "Guava"), (27, "Lychee"), (28, "Mango"), (29, "Passion Fruit"),
                (30, "Tangerine"),
(31, "Dragon Fruit"), (32, "Kumquat"), (33, "Lime"),
                (34, "Nectarine"), (35, "Persimmon"),
(36, "Rambutan"), (37, "Starfruit"), (38, "Ugli Fruit"),
                (39, "Honeydew Melon"), (40, "Jackfruit"),
(41, "Lingonberry"), (42, "Mangosteen"), (43, "Olive"),
                (44, "Quince"), (45, "Soursop"),
(46, "Tamarillo"), (47, "Ugni"), (48, "Yangmei"), (49, "Zucchini"),
                (50, "Elderberry")
]



if __name__ == "__main__":
app = TablePaginationFrame()
app.mainloop()



The Final Result:

How to Create a Table with Pagination Buttons in Python Tkinter









Python Drawing Project Using Tkinter

How to Create a Drawing App In Python Tkinter



In this Python tutorial, we will see how to create a drawing application using the Tkinter library for the graphical user interface. 
This application provides a graphical user interface (GUI) where users can draw various shapes on a canvas, choose colors, and save their drawings.
The "Choose Color" button opens a color chooser dialog, allowing the user to select a drawing color.
The application supports three types of shapes: Freehand, Rectangle, and Oval, which users can select using dedicated buttons.
Mouse listeners capture user interactions for drawing shapes on the canvas, with the PaintPanel and the ControlPanel classes handling mouse events for drawing shapes.
The "Clear Canvas" button clears all drawn shapes from the canvas.
The "Save as Image" button allows users to save the current drawing as a PNG image file, using a file chooser dialog to select the destination for saving the image.

What We Are Gonna Use In This Project:

- Python Programming Language.
- Tkinter for GUI.
- VS Code Editor.




Project Source Code:




import tkinter as tk
from tkinter import colorchooser, filedialog, messagebox
from enum import Enum
from io import BytesIO
# pip install Pillow
from PIL import Image, ImageDraw, ImageTk, ImageGrab

# Enum to represent different types of shapes
class ShapeType(Enum):
FREEHAND = 1
RECTANGLE = 2
OVAL = 3
LINE = 4


# Main application class
class DrawingApp:
def __init__(self, root):
# Initialize the DrawingApp.
self.root = root
self.root.title("Drawing App")
self.root.geometry("800x600")

# Create a PaintPanel and ControlPanel
self.paint_panel = PaintPanel(root)
self.paint_panel.pack(fill=tk.BOTH, expand=True)

self.controle_panel = ControlPanel(root, self.paint_panel)
self.controle_panel.pack(fill=tk.X)


# Canvas for drawing
class PaintPanel(tk.Canvas):
def __init__(self, master, *args, **kwargs):
# Initialize the PaintPanel.
super().__init__(master, *args, **kwargs)
# Initialize variables
self.image = Image.new("RGB", (800, 600), "white")
self.shapes = []
self.current_color = "black"
self.current_shape_type = ShapeType.FREEHAND
self.background_color = "white"

# Bind events to methods
self.bind("<Button-1>", self.start_drawing)
self.bind("<B1-Motion>", self.draw)


# Start drawing a shape
def start_drawing(self, event):
start_point = (event.x, event.y)
shape = self.create_shape(self.current_shape_type, self.current_color,
        start_point)
self.shapes.append(shape)


# Continue drawing a shape
def draw(self, event):
if self.shapes:
current_shape = self.shapes[-1]
current_shape.add_point((event.x, event.y))
self.update_canvas()


# Create a shape based on shape type
def create_shape(self, shape_type, color, start_point):
if shape_type == ShapeType.FREEHAND:
return FreehandShape(color, start_point)
elif shape_type == ShapeType.RECTANGLE:
return RectangleShape(color, start_point)

elif shape_type == ShapeType.OVAL:
return OvalShape(color, start_point)

elif shape_type == ShapeType.LINE:
return LineShape(color, start_point)


# Update the canvas with shapes
def update_canvas(self):
self.delete("all")
self.create_rectangle(0, 0, self.winfo_width(), self.winfo_height(),
        fill=self.background_color)

for shape in self.shapes:
shape.draw(self)

self.photo = ImageTk.PhotoImage(self.image)

# Change the background color
def change_background_color(self, color):
self.background_color = color
self.update_canvas()
# Save the drawing as an image
def save_drawing(self):
# problem caused by the video recorder
file_path = filedialog.asksaveasfilename(defaultextension=".png",
        filetypes=[("PNG Files", "*.png")])
x = self.master.winfo_rootx() + self.winfo_x()
y = self.master.winfo_rooty() + self.winfo_y()

x1 = x + self.winfo_width()
y1 = y + self.winfo_height()

ImageGrab.grab(bbox=(x, y, x1, y1)).save(file_path)
print(f"Drawing saved as {file_path}")






# Control panel with buttons for various actions
class ControlPanel(tk.Frame):
def __init__(self, master, paint_panel, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.paint_panel = paint_panel

# Create buttons and pack them
self.clear_button = self.create_button("Clear Canvas", "red",
        self.clear_canvas)

self.color_button = self.create_button("Choose Color", "#3f51b5",
        self.choose_color)

self.freehand_button = self.create_button("Freehand", "#D35300",
        lambda : self.set_shape_type(ShapeType.FREEHAND))

self.rectangle_button = self.create_button("Rectangle", "#8e44ad",
        lambda : self.set_shape_type(ShapeType.RECTANGLE))

self.oval_button = self.create_button("Oval", "#27ae60",
        lambda : self.set_shape_type(ShapeType.OVAL))

self.line_button = self.create_button("Line", "#FFC107",
        lambda : self.set_shape_type(ShapeType.LINE))

self.bg_color_button = self.create_button("Change BG Color", "#604d8b",
        self.change_bg_color)

self.save_button = self.create_button("Save as image", "green",
        self.paint_panel.save_drawing)

self.pack_buttons()

# Create a button with specified properties
def create_button(self, text, bg_color, command):
button = tk.Button(self, text=text, bg=bg_color, fg="white", command=command)
button.configure(font = ("Arial", 10, "bold"))
button.pack(side = tk.LEFT, padx = 5)
return button

# Pack all buttons
def pack_buttons(self):
buttons = [
self.clear_button,
self.color_button,
self.freehand_button,
self.rectangle_button,
self.oval_button,
self.line_button,
self.bg_color_button,
self.save_button
]

for button in buttons:
button.pack(side = tk.LEFT, padx = 5)


# Change the background color
def change_bg_color(self):
color = colorchooser.askcolor(title="Choose Background Color")[1]
if color:
self.paint_panel.change_background_color(color)


# Choose a drawing color
def choose_color(self):
color = colorchooser.askcolor(title = "Choose Color")[1]
if color:
self.paint_panel.current_color = color


# Set the current shape type
def set_shape_type(self, shape_type):
self.paint_panel.current_shape_type = shape_type


# Clear the canvas
def clear_canvas(self):
self.paint_panel.shapes = []
self.paint_panel.update_canvas()



# Base class for different shapes
class Shape:
def __init__(self, color, start_point):
"""
Initialize a shape.

Args:
color: The color of the shape.
start_point: The starting point of the shape.
"""
self.color = color
self.points = [start_point]

def add_point(self, point):
"""
Add a point to the shape.

Args:
point: The point to add.
"""
self.points.append(point)

def draw(self, canvas):
# Draw the shape on the canvas
# Abstract method for drawing a shape
pass


# Freehand shape class
class FreehandShape(Shape):
def draw(self, canvas):
try:
canvas.create_line(self.points, fill = self.color, width = 2)
except tk.TclError as e:
print(f"Failed to draw freehand shape: {e}")



# Rectangle shape class
class RectangleShape(Shape):
def draw(self, canvas):
start_x, start_y = self.points[0]
end_x, end_y = self.points[-1]
canvas.create_rectangle(start_x, start_y, end_x, end_y,
        outline = self.color, width = 2)


# Oval shape class
class OvalShape(Shape):
def draw(self, canvas):
start_x, start_y = self.points[0]
end_x, end_y = self.points[-1]
canvas.create_oval(start_x, start_y, end_x, end_y, outline = self.color,
        width = 2)

# Line class
class LineShape(Shape):
def draw(self, canvas):
start_x, start_y = self.points[0]
end_x, end_y = self.points[-1]
canvas.create_line(start_x, start_y, end_x, end_y, fill = self.color,
        width = 2)




if __name__ == "__main__":
root = tk.Tk()
app = DrawingApp(root)
root.mainloop()




The Final Result: