wxPythonGrid表格控件的使⽤
因⼯作原因使⽤了⼀下 wxPython。总的来说不推荐。我的观点是⼲什么事情,要⽤那个领域最成熟的库,⽐如桌⾯软件,⽤ C#、Qt。不流⾏的的 wx 有 bug,参考⽂档少。下⾯贴出我的代码。这个代码展⽰了 Grid 的使⽤,可以“增删改”,按列排序,隐藏某⼀列的显⽰(就像在 Excel ⾥为了看东西⽅便)。界⾯设计可以先⽤ wxFormBuilder 设计好,把代码 copy 过来。有些问题不好解决,我给⼀些还在探索中的⼈⼀点帮助。整个代码加上数据库是能运⾏的,数据库结构从代码中也能看出来。
import wx
id
import pymysql,re,time
connection = t(host='localhost',
port=3306,
user='root',
password='password',
db='ZuHaoManager',
charset='utf8'
)
# 获取游标
cursor = connection.cursor()xml文件记事本打开不齐整
class mData_id.Grid):
def __init__(self, parent, dbTable, GridLabelToDBLabel):
self.ColsNums = len(GridLabelToDBLabel)
# 这⼀个类的存在会导致最后类计数器⼤于0,有未释放资源,原因不明
self.dbTable=dbTable
self.GridLabelToDBLabel = GridLabelToDBLabel
self.currentlySelectedCell = (0, 0)
# 执⾏查询 SQL
self.data = cursor.fetchall()
# cursor.fetchone()获取单条数据,返回值是元组。cursor.fetchmany(3)获取多条数据。
vpswindows精品# Grid
self.RowsNum = len(self.data)
self.CreateGrid( self.RowsNum, self.ColsNums )
self.ShowSerial=[]
for i in range(self.RowsNum):
self.ShowSerial.append([i,"str"]) # 在页⾯中的显⽰顺序,排序的时候⽤。i表⽰⾏号,"str"字符串占位
self.ShowCols = []
for i in range(self.ColsNums):
self.ShowCols.append(i) # 表⽰数据表中第i列显⽰于表格中的第⼏列,负数表⽰不显⽰。
self.EnableEditing( True )
self.EnableGridLines( True )
self.EnableDragGridSize( False )
self.SetMargins( 0, 0 )
# Columns
self.EnableDragColMove( False )
self.EnableDragColSize( True )
self.SetColLabelSize( 30 )
self.id.EVT_GRID_LABEL_LEFT_CLICK, self.OnLabelLeftClick)
# 设置列名称
for i,m_tuple in enumerate(GridLabelToDBLabel):
番茄todo社区视频免费看self.SetColLabelValue( i, m_tuple[0])
self.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
# Rows
self.EnableDragRowSize( True )
self.SetRowLabelSize( 80 )
self.SetRowLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
# 设置列背景颜⾊
id.GridCellAttr()
oddStyle.SetBackgroundColour(wx.Colour(12578815))
for i in range(self.RowsNum):
if i%2==0:
self.SetRowAttr(i, oddStyle)
# Label Appearance
# Cell Defaults
self.SetDefaultCellAlignment( wx.ALIGN_LEFT, wx.ALIGN_TOP )
self.DisplayGrid( -100 )
self.id.EVT_GRID_CELL_CHANGED, self.CellContentsChanged)
self.id.EVT_GRID_SELECT_CELL, SingleSelect)
def DisplayGrid( self, ColNum ):
# ColNum 指⽰根据哪⼀列进⾏排序。
"""
if self.ShowCols[0] > -1 and ColNum!=-100 :
IDColAttrROF = wx.grid.GridCellAttr() # 设置ID列为可编辑
IDColAttrROF.SetReadOnly(isReadOnly=False)
# 排序完成以后,Grid的值需要重新设置,要先解除 ReadOnly 才能设置。
# (之前程序在运⾏时,重新设置⼀⾏可以,第⼆⾏就不⾏,也很奇怪。)
for row in range(self.RowsNum):
self.SetAttr( row, 0, IDColAttrROF )
# !!接触设置代码有问题!
"""
for row,ele in enumerate(self.data):
l_ShowRow = row
if ColNum!=-100:
l_ShowRow = self.ShowSerial.index([row,ele[ColNum]]) # 排序完以后这⾏代码就起作⽤了
for col,value in enumerate(ele):
l_ShowCol = self.ShowCols[col] # 有些列是不显⽰的,>=0的要显⽰。
if l_ShowCol>=0:
if type(value) is not str:
value = str(value)
二叉树层级遍历self.SetCellValue(l_ShowRow,l_ShowCol,value)
"""
if self.ShowCols[0] > -1:
IDColAttrRO = wx.grid.GridCellAttr() # 设置ID列为不可编辑
IDColAttrRO.SetReadOnly(isReadOnly=True)
for row in range(self.RowsNum):
self.SetAttr( row, 0, IDColAttrRO )
"""
def CellContentsChanged(self, event):
x = event.GetRow()
y = event.GetCol()
val = self.GetCellValue(x, y)
if val == "":
val = "null"
inDataCol = self.ShowCols.index(y)
ColLabel = self.GridLabelToDBLabel[inDataCol][1]
AccountID_new = self.data[x,0]
InsertCell = "UPDATE %s SET %s = \"%s\" WHERE AccountID = \"%s\";"%(self.dbTable, ColLabel ,val, AccountID_new) ute(InsertCell)
connectionmit() # do commit here to ensure data persistence
# also, retrieve formatting for variable and format the output
# self.SetCellValue(x, y, val)
event.Skip()
event.Skip()
def OnLabelLeftClick(self, event):
# print ("OnLabelLeftClick: (%d,%d) %s\n" % (event.GetRow(),
# event.GetCol(),
# event.GetPosition())) # 输出 (-1,1) (196, 9) or OnLabelLeftClick: (0,-1) (51, 45)
ColNum = event.GetCol()
if event.GetRow()==-1 and self.GridLabelToDBLabel[ColNum][2]==1 and ColNum!=-1:
for i in range(self.RowsNum):
self.ShowSerial[i][1] = self.GetCellValue(i,ColNum) # 把表格数据填充进来
self.ShowSerial.sort(key=lambda x:x[1])
self.DisplayGrid( ColNum )
self.ForceRefresh()
event.Skip()
def onSingleSelect(self, event):
self.currentlySelectedCell = (event.GetRow(),
event.GetCol())
event.Skip()
# Define the tab content as classes:
class TabOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
#以下元组:第三位是是否⽀持排序。第四位是在“添加”的弹出对话框中如何显⽰:“-2”不显⽰,“-1”⽂
本框,其他⾃然数是选项在字典中的索引号。 self.GridLabelToDBLabel=[("账号ID","AccountID",1, -2),
("⼿机号","PhoneNum",1, -1),
("名字","Name",1, -1),
("话费","Fee",1, -1),
("位置","Location",1, -1),
("账号","Account",1, -1),
("密码","Password",0, -1),
findb函数的使用方法("什么数量","PropertyNum",1, -1),
("什么数量","CouponNum",1, -1),
("什么时间","Mature",1, -1),
("什么和","PaySum",1, -1),
("什么","Remark",0, -1),
("什么什么","State",1, 0)] # 此处不能⽤字典,因为字典没有顺序
self.ChoiceList = [[ u"空闲", u"出租中", u"次⽇可⽤", wx.EmptyString ]]
self.m_grid = mData_Grid( self, "AccountT", self.GridLabelToDBLabel )
class TabTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
#以下元组:第三位是是否⽀持排序。第四位是在“添加”的弹出对话框中如何显⽰:“-2”不显⽰,“-1”⽂本框,其他⾃然数是选项在字典中的索引号。 self.GridLabelToDBLabel=[("⽤户ID","UserID",1, -2),
("⽤户名","Name",1, -1),
("⼀个字段","VIPGrade",1, 0),
("⼀个字段","CreditGrade",1, 1),
("⼀个字段","RegisterDate",1, -1),
("⼀个字段","State",1, 2),
("⼀个字段","LastDays",1, -1),
("⼀个字段","RentNum",1, -1),
("⼀个字段","Remark ",0, -1)] # 此处不能⽤字典,因为字典没有顺序
self.ChoiceList = [[ u"普通", u"VIP", u"超级VIP", wx.EmptyString ],
[ u"优", u"良", u"中", u"差", wx.EmptyString ],
[ u"在⽤", u"封号", wx.EmptyString ]]
self.m_grid = mData_Grid( self, "UserT", self.GridLabelToDBLabel )
class TabThree(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
#以下元组:第三位是是否⽀持排序。第四位是在“添加”的弹出对话框中如何显⽰:“-2”不显⽰,“-1”⽂本框,其他⾃然数是选项在字典中的索引号。 self.GridLabelToDBLabel=[("流⽔号","LSH",1, -2),
("账号ID","AccountID",1, -1),
("账号ID","AccountID",1, -1),
("⽤户ID","UserID",1, -1),
("⽤户名","name",1, -1),
("⼀个字段","RentDate",1, -1),
("⼀个字段","RentPropertyNum",0, -1),
("⼀个字段数","RentCouponNum",0, -1),
("⼀个字段","RentDeposit",0, -1),
("⼀个字段","Return_ChangedPwd",1, -1),
("⼀个字段","Return_NewPwd",0, -1),
("⼀个字段","ReturnDate",1, -1),
("⼀个字段数","ReturnPropertyNum",0, -1),
("⼀个字段数","ReturnCouponNum",0, -1),
("⼀个字段","ReturnDeposit",0, -1),
("⼀个字段","RentDays",1, -1),
("⼀个字段","HaveBadRecord",1, 0),
("⼀个字段","Active",1, -1),
("⼀个字段","ActReward",0, -1),
("⼀个字段","Remark",0, -1)] # 此处不能⽤字典,因为字典没有顺序
self.ChoiceList = [[ u"有", u"⽆", u"未检查", wx.EmptyString ]]
self.m_grid = mData_Grid( self, "UserT", self.GridLabelToDBLabel )
class TabFour(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the last tab", (20,20))
class AddDialog ( wx.Dialog ):
def __init__( self, parent, GridLabelToDBLabel, dbTable, targetGrid, ChoiceList ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = "添加",
pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
self.GridLabelToDBLabel=GridLabelToDBLabel
self.dbTable=dbTable
self.targetGrid = targetGrid
self.ChoiceList=ChoiceList
fgSizer = wx.FlexGridSizer( 0, 2, 0, 0 )
fgSizer.SetFlexibleDirection( wx.BOTH )
fgSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
for t_label in GridLabelToDBLabel:
if t_label[3]=="-2": # 这⼀位数据库⾃增
continue
m_staticText = wx.StaticText( self, wx.ID_ANY, t_label[0], wx.DefaultPosition, wx.DefaultSize, 0 )
m_staticText.Wrap( -1 )
fgSizer.Add( m_staticText, 0, wx.ALL, 5 )
if t_label[3]>-1:
m_comboBox1Choices = self.ChoiceList[t_label[3]]
self.m_comboBox1 = wx.ComboBox( self, wx.ID_ANY, u"请选择", wx.DefaultPosition, wx.DefaultSize, m_comboBox1Choices, 0 ) fgSizer.Add( self.m_comboBox1, 0, wx.ALL, 5 )
else:
m_textCtrl = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
fgSizer.Add( m_textCtrl, 0, wx.ALL, 5 )
self.m_button1 = wx.Button( self, wx.ID_ANY, u"添加", wx.DefaultPosition, wx.DefaultSize, 0 )
fgSizer.Add( self.m_button1, 0, wx.ALL, 5 )
self.m_button1.Bind( wx.EVT_BUTTON, self.addItem )
self.SetSizer( fgSizer )
self.Layout()
fgSizer.Fit( self )
self.Centre( wx.BOTH )
def addItem(self, event):
NewLinePara=[] # 此处不能⽤字典,字典是⽆顺序的
# re.match("1[2-9]{1}[0-9]{9}", CtrlList[1].GetLineText(0))==None # 判断输⼊是否为⼿机号
for [m_textCtrl,i] CtrlList:
if i==1:position和location的区别
NewLinePara.append(m_textCtrl.GetStringSelection()) # GetTextSelection()返回(0,0),GetSelection()返回选择的索引 else:
NewLinePara.append(m_textCtrl.GetLineText(0))
InsertCell="INSERT INTO "+self.dbTable+" VALUES ( null,"
for para in NewLinePara:
InsertCell=InsertCell+"\""+para+"\""+","
InsertCell=InsertCell[:-1]+");"
connectionmit()
# 刷新显⽰界⾯
self.targetGrid.RowsNum = self.targetGrid.RowsNum + 1
self.targetGrid.AppendRows( numRows=1 )
for col,para in enumerate(NewLinePara):
self.targetGrid.SetCellValue(self.targetGrid.RowsNum-1,col+1,para) # 之所以 +1 是因为前⾯还有个 id。
# 设置第⼀列为不可编辑
IDColAttr = wx.grid.GridCellAttr()
IDColAttr.SetReadOnly(isReadOnly=True)
self.targetGrid.SetAttr( self.targetGrid.RowsNum-1,0, IDColAttr)
self.targetGrid.ForceRefresh()
event.Skip()
self.Destroy()
def __del__( self ):
pass
class DelDialog ( wx.Dialog ):
def __init__( self, parent, dbTable, dbTableIDName, dbTableID, targetGrid, targetRow ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = "删除",
pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
self.dbTable=dbTable
self.dbTableIDName=dbTableIDName
self.dbTableID=dbTableID
self.targetGrid = targetGrid
self.targetRow = targetRow
bSizer = wx.BoxSizer( wx.VERTICAL )
self.m_staticText = wx.StaticText( self, wx.ID_ANY, u"确定删除?", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText.Wrap( -1 )
bSizer.Add( self.m_staticText, 0, wx.ALL, 5 )
self.m_button = wx.Button( self, wx.ID_ANY, u"确定", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer.Add( self.m_button, 0, wx.ALL, 5 )
self.m_button.Bind( wx.EVT_BUTTON, self.delItem )
self.SetSizer( bSizer )
self.Layout()
bSizer.Fit( self )
self.Centre( wx.BOTH )
def delItem(self, event):
DelCell="DELETE FROM "+self.dbTable+" WHERE "+self.dbTableIDName+" = "+"\""+self.dbTableID+"\";"
connectionmit()
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论