Use QTableWidget for a straightforward item-based table: set its dimensions and headers, add a QTableWidgetItem for each populated cell, and read values back through those items. The example below builds a small table, colors a cell, and safely retrieves its text.
Build and populate a QTableWidget
QTableWidget is a convenient item-based table widget with a default model, so you can add cell items directly without creating a separate table model. Install the PyQt6 package with pip install PyQt6, then create the widget and populate it:
As an Amazon Associate I earn from qualifying purchases.
import sys
from PyQt6.QtGui import QColor
from PyQt6.QtWidgets import QApplication, QTableWidget, QTableWidgetItem
app = QApplication(sys.argv)
table = QTableWidget(3, 2)
table.setHorizontalHeaderLabels(["Product", "Quantity"])
rows = [
("Notebook", 12),
("Pen", 30),
("Folder", 8),
]
for row_index, (product, quantity) in enumerate(rows):
table.setItem(row_index, 0, QTableWidgetItem(str(product)))
table.setItem(row_index, 1, QTableWidgetItem(str(quantity)))
table.item(0, 0).setBackground(QColor("#d9edff"))
table.resizeColumnsToContents()
table.show()
sys.exit(app.exec())
The constructor arguments in QTableWidget(3, 2) specify three rows and two columns. setHorizontalHeaderLabels() names the columns. For each cell, create a QTableWidgetItem and pass it to setItem(row, column, item). Convert values to strings deliberately for display; the example converts the numeric quantities too.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11After insertion, the table takes ownership of the item. Create and insert a distinct item for each populated cell rather than trying to reuse one item in multiple cells. The code follows the PyQt6 module layout; Qt for Python’s tutorial uses PySide6 imports, so its examples should not be copied with those imports into a PyQt6 application. See the Riverbank PyQt product page for package information and the Qt for Python QTableWidget reference for widget behavior.
#1 Best Overall
Style cells and control the table’s appearance
For a one-off cell color, set the item background to a QColor, as the example does. You can also set an item’s foreground or text alignment when those properties are useful for the data. The Qt for Python table-widget tutorial demonstrates per-item background coloring; in PyQt6, import QColor from PyQt6.QtGui.
For broader appearance changes, use item-view styling. When you need custom rendering or editor behavior, a delegate is generally the better place to implement it; Qt’s model/view overview describes QStyledItemDelegate for custom delegates and style-sheet work. See the Qt model/view programming overview.
Rank #2
Read a cell safely
Call item(row, column) to get the cell’s item, then read its text. An unset cell has no item, so check for None before calling text():
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →row = 0
column = 0
item = table.item(row, column)
if item is not None:
print(item.text())
else:
print("That cell is empty")
Use rowCount() and columnCount() to inspect the current dimensions and iterate only over valid coordinates:
for row in range(table.rowCount()):
values = []
for column in range(table.columnCount()):
item = table.item(row, column)
values.append(item.text() if item is not None else "")
print(values)
Handle edits and sorting without mismatching rows
To respond to edits, connect to itemChanged(item) when you need the changed item, or cellChanged(row, column) when its coordinates are sufficient. These signals report data changes; a click signal answers a different question and should not be used as a substitute for edit notification. See the QTableWidget signal reference.
When adding multiple cells to each record, populate the table before enabling sorting. If sorting is active on the column being populated, inserting an item can move its row immediately. Later calls that continue using the original row number may then write values into a different record. If sorting must remain enabled, temporarily disable it while filling a row, then restore it after the row is complete. The behavior is documented in the Qt QTableWidget reference.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Choose between QTableWidget and QTableView
Choose based on where the data lives and how much control the application needs over its model:
| Question | QTableWidget | QTableView with a model |
|---|---|---|
| Where are cell values represented? | As widget-managed QTableWidgetItem objects. |
In a separate model supplied to the view. |
| What setup is it suited to? | Directly adding items to a straightforward table. | Applications that need a custom or reusable data model. |
| Which offers more model control? | Less control; the widget uses its default model. | More control over how data is represented and supplied. |
Qt’s guidance is direct: “If you want a table that uses your own data model you should use QTableView rather than this class.” That recommendation appears in the official Qt for Python QTableWidget documentation. The documentation does not give a row-count threshold at which one widget becomes preferable; base the choice on whether direct item management or a separate model fits your application.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




