Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Building a Random Student Selector with Python tkinter

Tech 1

Data Preparation

A classroom roster typically contains student IDs and names stored in an Excel file. This project uses pandas to read Excel data.

First, install the required dependenceis:

pip install pandas openpyxl

Consider an Excel file roster.xlsx with columns including ID and Name. The following steps demonstrate how to process this data:

import pandas as pd

df = pd.read_excel("roster.xlsx")
print(df.head())

Convert the DataFrame to a simple list format suitable for the selector:

for idx, row in df.iterrows():
    print(f"{row['ID']} - {row['Name']}")

Validation ensures the Excel file contains required columns. Using assertions prevents the program from proceeding with invalid data:

columns = df.columns.values.tolist()
assert "ID" in columns, "Excel must contain an 'ID' column"
assert "Name" in columns, "Excel must contain a 'Name' column"

A complete data processing function:

def load_roster(filepath):
    df = pd.read_excel(filepath)
    columns = df.columns.values.tolist()
    assert "ID" in columns, "Excel must contain an 'ID' column"
    assert "Name" in columns, "Excel must contain a 'Name' column"
    return [f"{row['ID']} {row['Name']}" for idx, row in df.iterrows()]

GUI Implementation

The tkinter library provides the foundation for building the graphical interface.

import tkinter as tk
import random

Basic Window Setup

root = tk.Tk()
root.mainloop()

Display Label

A StringVar holds the currently displayed name, which updates rapidly during the selection animation:

display_var = tk.StringVar(value="READY")
name_label = tk.Label(root, textvariable=display_var, font=("Arial", 24))
name_label.pack(pady=50)

Control Buttons

start_btn = tk.Button(root, text='Start', font=("Arial", 14))
start_btn.pack(side="left", padx=20)

stop_btn = tk.Button(root, text='Stop', font=("Arial", 14))
stop_btn.pack(side="right", padx=20)

Enimation Logic

The rolling effect uses after() to repeatedly update the display at short intervals:

is_running = False

def start_rolling(var, data_list):
    global is_running
    if is_running:
        return
    is_running = True
    roll_animation(var, data_list)

def roll_animation(var, data_list):
    var.set(random.choice(data_list))
    if is_running:
        root.after(50, roll_animation, var, data_list)

def stop_rolling():
    global is_running
    is_running = False

Connect these functions to the buttons:

start_btn.config(command=lambda: start_rolling(display_var, student_data))
stop_btn.config(command=stop_rolling)

Window Centering

Position the window in the screen center for better user expeirence:

def center_window(win, width, height):
    screen_w = win.winfo_screenwidth()
    screen_h = win.winfo_screenheight()
    x = (screen_w - width) // 2
    y = (screen_h - height) // 2
    win.geometry(f"{width}x{height}+{x}+{y}")

Complete Selector Class

Encapsulating the functionality in a class provides clean organization:

class RandomSelector(tk.Tk):
    def __init__(self, data_list):
        super().__init__()
        self.student_data = data_list
        self.is_running = False

        self.title("Random Selector")
        center_window(self, 400, 300)

        self.display_var = tk.StringVar(value="READY")
        self.name_label = tk.Label(
            self,
            textvariable=self.display_var,
            font=("Arial", 28, "bold")
        )
        self.name_label.pack(expand=True)

        btn_frame = tk.Frame(self)
        btn_frame.pack(pady=30)

        self.start_btn = tk.Button(
            btn_frame,
            text='Start',
            width=10,
            command=lambda: self.begin_rolling(self.display_var)
        )
        self.start_btn.grid(row=0, column=0, padx=10)

        self.stop_btn = tk.Button(
            btn_frame,
            text='Stop',
            width=10,
            command=self.halt_rolling
        )
        self.stop_btn.grid(row=0, column=1, padx=10)

    def roll_animation(self, var):
        var.set(random.choice(self.student_data))
        if self.is_running:
            self.after(50, self.roll_animation, var)

    def begin_rolling(self, var):
        if self.is_running:
            return
        self.is_running = True
        self.roll_animation(var)

    def halt_rolling(self):
        self.is_running = False

File Upload Interface

Adding a file selection dialog improves usability by allowing users to browse for Excel files instead of hardcoding paths.

File Browser Dialog

from tkinter import filedialog

def browse_file(entry_widget):
    filename = filedialog.askopenfilename(
        title="Select Roster File",
        filetypes=[("Excel Files", "*.xls *.xlsx")]
    )
    entry_widget.delete(0, tk.END)
    entry_widget.insert(0, filename)

Upload Window Layout

class FileUploader(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Load Roster")
        center_window(self, 400, 120)

        path_label = tk.Label(self, text="File Path:")
        path_label.grid(row=0, column=0, padx=10, pady=15, sticky="e")

        self.path_entry = tk.Entry(self, width=35)
        self.path_entry.grid(row=0, column=1, columnspan=2, padx=(0, 10))

        browse_btn = tk.Button(
            self,
            text="Browse",
            command=self.select_file
        )
        browse_btn.grid(row=1, column=1, pady=10, ipadx=15)

        load_btn = tk.Button(
            self,
            text="Load Data",
            command=self.load_roster_data
        )
        load_btn.grid(row=1, column=2, ipadx=15)

    def select_file(self):
        filename = filedialog.askopenfilename(
            title="Select Roster File",
            filetypes=[("Excel Files", "*.xls *.xlsx")]
        )
        self.path_entry.delete(0, tk.END)
        self.path_entry.insert(0, filename)

    def load_roster_data(self):
        try:
            roster = load_roster(self.path_entry.get())
            self.destroy()
            RandomSelector(roster)
        except AssertionError as e:
            from tkinter.messagebox import showerror
            showerror("Error", str(e))
        except Exception as e:
            from tkinter.messagebox import showerror
            showerror("Error", f"Failed to load data\n{e}")

Application Entry Point

if __name__ == "__main__":
    FileUploader().mainloop()

Summary

This application consists of two main windows: a file upload interface for loading Excel rosters, and a random selector interface for choosing students. The RandomSelector class manages the rolling animation using tkinter's after() method, while the FileUploader class handles file selection and data validation. Both windows use the center_window() function to appear centered on screen.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.