Fast, GPU-painted spreadsheet grid for tens of thousands of rows (OpenGL; Windows and Linux).
Project description
An OpenGL spreadsheet grid for tens of thousands of rows. Only visible cells are built, so scroll, select, filter and find stay instant. A GUI-free core holds the logic, under a thin Tk or Qt host.
Requirements
| Requirement | Details |
|---|---|
| Platform | The renderer is OpenGL 1.1 (core/glsurface.dll / .so): Windows (WGL + GDI) and Linux (GLX + FreeType). No macOS backend. |
| Python 3.8+ | |
| Tk host | Standard library only (tkinter). |
| Qt host | Needs PySide6 (pip install PySide6), the only dependency, and only for the Qt host. |
| Native libs | The wheel bundles glsurface (OpenGL renderer) and gridcore (C++ data core). Both required; build from source needs CMake + a C++17 compiler (MSVC on Windows; GCC/Clang + GL/X11/FreeType dev headers on Linux). |
Install
pip install fastpygrid # Tk host (stdlib only)
pip install fastpygrid PySide6 # add the Qt host
Example
Tk
from fastpygrid.render.tk import make_sheet # tkinter host (stdlib only)
win = make_sheet(
["Ticker", "Company", "Sector", "Price"],
[["AAPL", "Apple Inc.", "Technology", "189.20"],
["XOM", "Exxon Mobil", "Energy", "104.10"]],
frozen_columns=2, # pin the first 2 columns against horizontal scroll
)
win.mainloop()
Qt
from fastpygrid.render.qt import make_sheet # PySide6 host
win = make_sheet(headers, rows, frozen_columns=2)
win.mainloop() # aliases app.exec()
From a pandas DataFrame
dataframe_to_grid(df) turns a DataFrame into (headers, rows) you splat straight
into make_sheet / make_model. pandas is not a dependency -- it duck-types the
DataFrame, so it only needs pandas if you actually pass one. A MultiIndex columns
frame becomes stacked headers (one row per level); NaN/None render blank.
from fastpygrid import dataframe_to_grid
from fastpygrid.render.tk import make_sheet
win = make_sheet(*dataframe_to_grid(df), frozen_columns=2)
win.mainloop()
Interface
make_sheet() (in both fastpygrid.render.tk and fastpygrid.render.qt) opens a
window and returns a GridModel for styling cells, dropdowns and dividers.
col is 0-based. gr is a grid row where rows 0 .. header_rows-1
are the header and data starts at gr=header_rows (so gr=1 with one header row).
make_sheet(headers, rows, ...)
Builds the model, opens the window, returns it. Raises RuntimeError if a required
native lib (glsurface or gridcore) is missing.
| Argument | Type | Default | What it does |
|---|---|---|---|
headers |
list[str] or list[list[str]] |
required | Column titles. A list of lists gives stacked headers, where adjacent equal labels in the upper rows merge into group bands. |
rows |
list[list] |
required | The data, row by row. Values are stringified. |
frozen_columns |
int |
0 |
Pin this many leading columns against horizontal scroll. |
view_only |
bool |
False |
Read-only sheet: no edit, paste or delete. |
master |
widget | None |
Parent window. Given one, opens as a child instead of a new top-level app. |
col_w |
list[int] |
None |
Per-column pixel widths. None auto-sizes. |
title |
str |
host default | Window title. |
uncap_rows |
bool |
False |
Lift the built-in row-count cap. |
uncap_cols |
bool |
False |
Lift the built-in column-count cap. |
filters |
bool |
True |
Show the per-column header filter/sort ▼ dropdowns. False hides them. |
Returns the host window: a tk.Tk (or Toplevel) for Tk, a QWidget for Qt.
Both carry .mainloop() (Qt aliases app.exec()), .model (the GridModel),
and .grid_view (the grid widget).
from fastpygrid.render.tk import make_sheet
win = make_sheet(
["Ticker", "Company", "Sector", "Price"],
[["AAPL", "Apple Inc.", "Technology", "189.20"],
["XOM", "Exxon Mobil", "Energy", "104.10"]],
frozen_columns=2,
)
win.mainloop()
Reading and writing cells
Reach the model through win.model.
| Call | Returns | What it does |
|---|---|---|
cell(gr, col) |
str |
Text at that grid row/column ("" if out of range). |
nrows() |
int |
Total grid rows: header rows plus data. |
ncols |
int |
Column count (a property, no parens). |
set_cell(gr, col, text) |
bool |
Write a cell. Goes through undo. Returns False if unchanged or read-only. |
set_data(headers, rows) |
None |
Swap in a new sheet, resetting filters, sort and undo. |
m = win.model
m.cell(1, 0) # 'AAPL'
m.set_cell(1, 3, "191.55") # bump Apple's price, returns True
m.ncols # 4
Styling and dropdowns
Styles and choices are keyed to the data, so they follow a row through sort and filter.
| Call | What it does |
|---|---|
set_cell_style(gr, col, fg=None, bg=None, bold=None) |
Style one cell. fg/bg are #rrggbb. None leaves an attribute as-is. |
set_cell_choices(gr, col, choices) |
Turn one cell into a dropdown offering choices. None clears it. |
set_col_choices(col, choices) |
Same for a whole column, one O(1) call. A per-cell choice overrides it. |
m.set_cell_style(1, 3, fg="#c0392b", bold=True) # Apple's price in bold red
m.set_col_choices(2, ["Technology", "Energy", "Healthcare"]) # Sector is a dropdown
Dividers and locked cells
Dividers are positional (keyed by index), so they stay put when data moves. Read-only rows are keyed to the data and follow it.
| Call | What it does |
|---|---|
set_vline(col, on=True, width=None) |
Thick black rule on the right edge of a column. |
set_hline(gr, on=True, width=None) |
Thick black rule on the bottom edge of a grid row. |
set_readonly_col(col, on=True) |
Block edit/paste/delete in a column (still selectable and copyable). |
set_readonly_row(gr, on=True) |
Same, for a row. |
m.set_vline(1) # rule after the 'Company' column
m.set_hline(0, width=4) # rule under the header; width in px (omit for the 2px default)
m.set_readonly_col(0) # Ticker can't be edited
Build
build.bat
Runs python -m build, which drives CMake to compile the DLLs and produce
dist/fastpygrid-*.whl + .tar.gz (same artifacts as CI/PyPI). Needs CMake,
MSVC, and Python's build. Re-run after any .cpp/.py change.
Run demo
After build.bat, launch the OpenGL demo. It copies the built DLLs out of
dist/*.whl on first run, then prompts for the tk or qt host:
demos\demo.bat # prompts for tk or qt
demos\demo.bat tk # tkinter host, 100k rows
demos\demo.bat qt # Qt host, same data
demos\demo.bat tk --rows 500000 # stress it
The tk host needs nothing extra. The qt host needs PySide6: run demos/setup.bat
once to create demos/.venv (PySide6 + the wheel), which demo.bat then uses
automatically.
demos\.venv\Scripts\python -m pytest tests/ # headless self-checks
Layout
Fast-Python-Grid/
|-- fastpygrid/ # the python package
| |-- core/ # model, geometry, selection, rendering, gpu.py (OpenGL engine)
| | # glsurface + gridcore libs compile in here, beside their loaders (not committed)
| |-- render/ # tk.py (tkinter host), qt.py (PySide6 host)
| `-- csrc/ # C++ sources: glsurface.cpp, gridcore.cpp
|-- CMakeLists.txt # compiles the DLLs (scikit-build-core)
|-- build.bat # python -m build -> dist/*.whl + *.tar.gz (same as CI/PyPI)
|-- demos/ # demo_gpu_tk.py, demo_gpu_qt.py, _data.py, benchmark_*.py, setup.bat (wheel into demos/.venv)
`-- tests/ # headless self-checks (pytest; needs fastpygrid installed)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastpygrid-0.1.3.tar.gz.
File metadata
- Download URL: fastpygrid-0.1.3.tar.gz
- Upload date:
- Size: 380.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fdf8c5fa0d8bccedaab2ea34c008a4995c9f07f348291a05245d32a4b0e25d7d
|
|
| MD5 |
83e1efd7ac2a90b07a54af174fe6a45d
|
|
| BLAKE2b-256 |
4f246464f77ee0a3ca4af329a01f5e7711bdfc8002f87bb23711de7b25721b23
|
Provenance
The following attestation bundles were made for fastpygrid-0.1.3.tar.gz:
Publisher:
publish.yml on flynncrochon/Fast-Python-Grid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastpygrid-0.1.3.tar.gz -
Subject digest:
fdf8c5fa0d8bccedaab2ea34c008a4995c9f07f348291a05245d32a4b0e25d7d - Sigstore transparency entry: 2156620361
- Sigstore integration time:
-
Permalink:
flynncrochon/Fast-Python-Grid@fe89114f188e85488dec5f04d084af18eb2ba181 -
Branch / Tag:
refs/tags/v0.01.3 - Owner: https://github.com/flynncrochon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fe89114f188e85488dec5f04d084af18eb2ba181 -
Trigger Event:
release
-
Statement type:
File details
Details for the file fastpygrid-0.1.3-py3-none-win_amd64.whl.
File metadata
- Download URL: fastpygrid-0.1.3-py3-none-win_amd64.whl
- Upload date:
- Size: 130.2 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7997b974ae71e47b391e1c797d5bb56407050ec1e23c7f544e03abe1eb754c6f
|
|
| MD5 |
c23f721b1ba02169176fee62232e1389
|
|
| BLAKE2b-256 |
48d067595ddd479e8ae74463aa1dc2f8ed7cd90bdd3333febb794760a228460c
|
Provenance
The following attestation bundles were made for fastpygrid-0.1.3-py3-none-win_amd64.whl:
Publisher:
publish.yml on flynncrochon/Fast-Python-Grid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastpygrid-0.1.3-py3-none-win_amd64.whl -
Subject digest:
7997b974ae71e47b391e1c797d5bb56407050ec1e23c7f544e03abe1eb754c6f - Sigstore transparency entry: 2156620807
- Sigstore integration time:
-
Permalink:
flynncrochon/Fast-Python-Grid@fe89114f188e85488dec5f04d084af18eb2ba181 -
Branch / Tag:
refs/tags/v0.01.3 - Owner: https://github.com/flynncrochon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fe89114f188e85488dec5f04d084af18eb2ba181 -
Trigger Event:
release
-
Statement type: