import sys
import pandas as pd
from PySide6.QtWidgets import (QTableView, QApplication, QVBoxLayout, QPushButton, QWidget, QLineEdit)
from PySide6.QtCore import QAbstractTableModel, Qt, QModelIndex
# 自定義的 Qt 模型,用於顯示 Pandas DataFrame 的數據
class PandasModel(QAbstractTableModel):
def __init__(self, dataframe: pd.DataFrame, parent=None):
QAbstractTableModel.__init__(self, parent)
self._dataframe = dataframe
def rowCount(self, parent=QModelIndex()) -> int:
if parent == QModelIndex():
return len(self._dataframe)
return 0
def columnCount(self, parent=QModelIndex()) -> int:
if parent == QModelIndex():
return self._dataframe.columns.size
return 0
def data(self, index: QModelIndex, role=Qt.ItemDataRole):
if not index.isValid():
return None
if role == Qt.DisplayRole:
return str(self._dataframe.iloc[index.row(), index.column()])
return None
def headerData(self, section: int, orientation: Qt.Orientation, role: Qt.ItemDataRole):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self._dataframe.columns[section])
if orientation == Qt.Vertical:
return str(self._dataframe.index[section])
return None
def addRow(self, row_data):
self.beginInsertRows(QModelIndex(), len(self._dataframe), len(self._dataframe))
self._dataframe.loc[len(self._dataframe)] = row_data
self.endInsertRows()
def deleteRow(self, row):
self.beginRemoveRows(QModelIndex(), row, row)
self._dataframe.drop(self._dataframe.index[row], inplace=True)
self._dataframe.reset_index(drop=True, inplace=True)
self.endRemoveRows()
def changeRow(self, row, row_data):
self._dataframe.loc[row] = row_data
self.dataChanged.emit(self.index(row, 0), self.index(row, self.columnCount()-1))
def searchRows(self, query):
return self._dataframe[self._dataframe.apply(lambda row: row.astype(str).str.contains(query).any(), axis=1)].index.tolist()
# 主要演示函數
def demo_functionality():
app = QApplication(sys.argv)
# 用於演示的示例 DataFrame
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [28, 34, 45],
'Occupation': ['Engineer', 'Doctor', 'Artist']
})
view = QTableView()
model = PandasModel(df)
view.setModel(model)
# GUI 設置
add_button = QPushButton("Add Row")
delete_button = QPushButton("Delete Row")
change_button = QPushButton("Change Row")
search_button = QPushButton("Search")
search_box = QLineEdit("Enter Search Query")
def add_row():
model.addRow(['New', 20, 'Unknown'])
def delete_row():
model.deleteRow(0)
def change_row():
model.changeRow(0, ['Changed', 50, 'Changed'])
def search_row():
results = model.searchRows(search_box.text())
print(f'Search results: {results}')
add_button.clicked.connect(add_row)
delete_button.clicked.connect(delete_row)
change_button.clicked.connect(change_row)
search_button.clicked.connect(search_row)
layout = QVBoxLayout()
layout.addWidget(view)
layout.addWidget(add_button)
layout.addWidget(delete_button)
layout.addWidget(change_button)
layout.addWidget(search_box)
layout.addWidget(search_button)
container = QWidget()
container.setLayout(layout)
container.show()
sys.exit(app.exec())
if __name__ == "__main__":
demo_functionality()
以下是程式碼的主要說明:
匯入必要的模組:
sys:用於與系統進行交互的模組。
pandas as pd:用於處理數據的 Pandas 模組。
from PySide6.QtWidgets:用於建立 Qt 應用程式界面的模組。
from PySide6.QtCore:提供 Qt 核心功能的模組。
創建自定義的 Qt 模型 PandasModel,它是 QAbstractTableModel 的子類,用於將 Pandas DataFrame 的數據顯示在 Qt 表格視圖中。
PandasModel 類有以下方法:
init:初始化方法,接受一個 Pandas DataFrame 作為參數。
rowCount:返回行數。
columnCount:返回列數。
data:返回特定單元格的數據。
headerData:返回表頭數據。
addRow:添加一行數據。
deleteRow:刪除一行數據。
changeRow:更改一行數據。
searchRows:搜索包含特定查詢的行。
demo_functionality 函數創建了一個示例 Qt 應用程式,並在其中進行以下操作:
創建一個 Pandas DataFrame 用於顯示。
創建一個 Qt 表格視圖(QTableView)和與其關聯的 PandasModel 模型。
創建按鈕和搜索框,以便用戶可以添加、刪除、更改和搜索數據。
定義按鈕點擊事件的處理程序,以執行相應的操作。
最後,應用程式進入主函數,並呼叫 demo_functionality 函數以啟動應用程式。當使用者運行這個程式時,將顯示一個包含表格視圖和按鈕的窗口,允許用戶對 DataFrame 進行不同的操作。