这是我的代码示例 - 我使用 tkinter,其中包含选项卡和 pandas 表。 当我尝试将数据插入第一个选项卡中的单元格时,我收到错误
`
import pandas as pd
from pandastable import Table
import tkinter as tk
from tkinter import ttk
class PandasTableApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("PandasTable in Tabs")
self.geometry("800x600")
# Sample DataFrames
data1 = {'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}
df1 = pd.DataFrame(data1)
data2 = {'X': [10, 20, 30], 'Y': [40, 50, 60], 'Z': [70, 80, 90]}
df2 = pd.DataFrame(data2)
# Create Tab Control
tab_control = ttk.Notebook(self)
tab1 = ttk.Frame(tab_control)
tab2 = ttk.Frame(tab_control)
tab_control.add(tab1, text='Tab 1')
tab_control.add(tab2, text='Tab 2')
tab_control.pack(expand=1, fill='both')
# Create PandasTable instances
self.table1 = Table(tab1, dataframe=df1)
self.table2 = Table(tab2, dataframe=df2)
self.table1.show()
self.table2.show()
# Bind events for each table
self.table1.bind("<Return>", self.handle_return_table1)
self.table2.bind("<Return>", self.handle_return_table2)
def handle_return_table1(self, event):
# Custom handler for the Enter key event for table1
self.table1.handle_arrow_keys(event)
return "break"
def handle_return_table2(self, event):
# Custom handler for the Enter key event for table2
self.table2.handle_arrow_keys(event)
return "break"
if __name__ == "__main__":
app = PandasTableApp()
app.mainloop()`
这是我得到的错误:
C:\Users\xxxx\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py:1884: FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version. Call result.infer_objects(copy=False) instead. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`
return self.func(*args)
C:\Users\xxxx\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py:1884: FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version. Call result.infer_objects(copy=False) instead. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`
return self.func(*args)
C:\Users\xxxxx\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py:1884: FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version. Call result.infer_objects(copy=False) instead. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`
return self.func(*args)
C:\Users\xxxxx\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py:1884: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
return self.func(*args)
C:\Users\xxxxx\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py:1884: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '2' has dtype incompatible with int64, please explicitly cast to a compatible dtype first.
return self.func(*args)
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1884, in __call__
return self.func(*args)
File "C:\Users\xxxxx\Desktop\xxxx-xxx\xxx-venv\lib\site-packages\pandastable\core.pyy", line 2350, in handle_arrow_keys
x,y = self.getCanvasPos(self.currentrow, self.currentcol-1)
File "C:\Users\xxxxx\Desktop\xxxx-xxx\xxx-venv\lib\site-packages\pandastable\core.py", line 2151, in getCanvasPos
x1,y1,x2,y2 = self.getCellCoords(row,col)
File "C:\Users\xxxxx\Desktop\xxxx-xxx\xxx-venv\lib\site-packages\pandastable\core.py", line 2140, in getCellCoords
x1=self.col_positions[col]
IndexError: list index out of range
当我写入第二个选项卡时,它可以工作 - 我能够写入那里的单元格。 但写入第一个选项卡会崩溃并发送此错误。
知道为什么会发生吗?
提前致谢。
该错误似乎与每个选项卡中的表的初始化有关。
在
tab1
上启动应用程序后尝试修改单元格时,我可以重现该错误,但如果我转到 tab2
,然后返回到 tab1
,则不会出现错误。
解决方法可能是在启动应用程序后通过每个选项卡手动强制初始化。
将此行添加到
def __init__(self):
:
self.after(100, self.initialize_tabs)
after
方法确保应用程序已加载。我尝试不使用它,但仍然遇到同样的问题。
并将此方法添加到您的类中:
def initialize_tabs(self):
# Switch to each tab to initialize
self.tab_control.select(self.tab2)
self.tab_control.select(self.tab1)
此外,您没有正确处理
return
键。 handle_arrow_keys
方法无法用于 return
键。
pandastable
包使得正确完成绑定变得更加复杂。
首先,我们需要将每个表的引用存储在
__init__
中,并将 return
键绑定到应用程序,而不是表:
self.tables = {self.tab1: self.table1, self.tab2: self.table2}
self.bind("<Return>", self.handle_return)
然后,我们可以定义
handle_return
方法:
def handle_return(self, event):
try:
widget_name = event.widget.rsplit(".!", 1)[0]
widget = self.nametowidget(widget_name)
table = self.tables.get(widget, None)
self.process_enter_key(table)
except AttributeError:
pass
return "break"
如果不在表格中时按下
return
键,则不会追加任何内容,但是当在表格内按下该键时,代码会获取表格父元素的名称,然后使用tables
词典的帮助。
这样,你就可以随心所欲地操纵对象了。
例如:
def process_enter_key(self, table):
row = table.getSelectedRow()
col = table.getSelectedColumn()
if row < len(table.model.df):
row += 1
else:
row = 1
if col < len(table.model.df.columns) - 1:
col += 1
else:
col = 0
table.setSelectedRow(row-1)
table.setSelectedCol(col)
table.redraw()
如果可能的话,这会转到下一行。如果没有,则转到下一列的第一行,如果不可能,则转到第一行第一列。这样,当您按
return
键时,您始终会到达选项卡的某个单元格。
由于我不知道的原因,行从 1 开始索引,列从 0 开始索引。