Wondering if my approach is good. Code works as intended, just want to know if there is a better approach. Want to be able to add this widget to any future project. Is there a better way to make it compatible with future projects? Or are there any other glaring problems with the code?
My 3 requirements for the table:
- Populate from a Pandas DataFrame.
- Allow for a specified column to have a selection event.
- Change mouse pointer to a PointingHandCursor when hovering a cell that is clickable
Thank you for any suggestions!
import sys
import pandas as pd
import sqlalchemy as sa
from PyQt5.QtWidgets import QApplication, QTableView, QMainWindow
from PyQt5.QtCore import Qt, QItemSelectionModel
from PyQt5.QtGui import QStandardItemModel, QStandardItem
class Database123:
def __init__(self):
self.engine = None
def create_engine(self):
self.engine = sa.create_engine('postgresql://postgres:pass@localhost:5432/db')
def tbl_list(self, table_name):
try:
self.create_engine()
sql = f"SELECT * FROM {table_name};"
df = pd.read_sql_query(sql, self.engine)
return df
except (sa.exc.OperationalError, sa.exc.DatabaseError) as e:
print(f"Error accessing the database: {e}")
return pd.DataFrame()
finally:
if self.engine:
self.engine.dispose()
self.engine = None
class CellTableModel(QStandardItemModel):
def __init__(self, data):
super(CellTableModel, self).__init__()
self._data = data
self.setHorizontalHeaderLabels(data.columns)
for row in range(data.shape[0]):
for col in range(data.shape[1]):
item = QStandardItem(str(data.iloc[row, col]))
self.setItem(row, col, item)
class MainWindow(QMainWindow):
def __init__(self, data):
super().__init__()
self.initUI(data)
def initUI(self, data):
# Create a table view and set it as central widget
tableView = QTableView(self)
self.setCentralWidget(tableView)
# Create a CellTableModel and set it as the model for the table view
model = CellTableModel(data)
tableView.setModel(model)
# Create a selection model and set it for the table view
selectionModel = QItemSelectionModel(model)
tableView.setSelectionModel(selectionModel)
# Connect the selection changed signal to a custom slot
selectionModel.selectionChanged.connect(self.selectionChanged)
# Enable mouse tracking to receive mouse move events
tableView.setMouseTracking(True)
# Connect the custom slot to handle mouse move events
tableView.mouseMoveEvent = self.mouseMoveEvent
# Set up the main window
self.setGeometry(100, 100, 600, 400)
self.setWindowTitle('QTableView with Pandas DataFrame')
self.show()
def selectionChanged(self, selected, deselected):
# Custom slot to handle selection changes
selected_indexes = selected.indexes()
for index in selected_indexes:
# Check if the selected column is 'name'
if index.column() == data.columns.get_loc('name'):
print(f"Selected 'name': {index.data()}")
def mouseMoveEvent(self, event):
# Custom slot to handle mouse move events and change cursor
index = self.centralWidget().indexAt(event.pos())
if index.isValid() and index.column() == data.columns.get_loc('name'):
self.centralWidget().setCursor(Qt.PointingHandCursor)
else:
self.centralWidget().setCursor(Qt.ArrowCursor)
if __name__ == '__main__':
# create a pandas Data Frame
list_cell = Database123()
data = list_cell.tbl_list('cell')
app = QApplication(sys.argv)
ex = MainWindow(data)
app.exec_()
del app
I have tried multiple methods. This is the only one I could get to work.