本系统是一个简单图书管理系统,主要目的是使用它来管理图书,比如管理员负责图书日常管理工作,如各种基本信息的录入、修改、删除、查询操作。本系统的主要功能有图书信息的查询、录入、修改、删除及图书统计以及读者借还书功能等。
刚开始老师就说最好不要选择这种比较老套的项目,网上已经有很多人做过的。但我不同意老师的观点,我觉得即使是这种很普通没有新意的项目,想要做好做细致还是很难的。刚开始的时候确实很有干劲努力地去学wxpython,想用CS模式做一个客户端出来。最后因为学习界面而忽视了数据库的部分,导致大部分时间花在了界面上(关键是花了很多时间界面也没做好,失败啊),做为一个作品已经跑题了。一个人的项目,没办法。
数据库设计
系统E-R图:
数据库表的设计:
书籍信息表
图书ID | ID | VARCHAR2(15) |
图书名称 | NAME | VARCHAR2(30) |
图书作者 | AUTHOR | VARCHAR2(30) |
出版社 | PUBLISHER | VARCHAR2(30) |
类别 | TYPE | VARCHAR2(30) |
价格 | PRICE | NUMBER |
是否借阅 | BORROWED | VARCHAR2(2) |
用户表
用户编号 | USERID | VARCHAR2(15) |
用户姓名 | USERNAME | VARCHAR2(30) |
密码 | USERPWD | VARCHAR2(20) |
权限 | PERMISSION | VARCHAR2(10) |
读者表
读者编号 | READERID | VARCHAR2(15) |
读者姓名 | READERNAME | VARCHAR2(30) |
性别 | GENDER | VARCHAR2(2) |
借书数目 | BBN | NUMBER |
借书表
图书编号 | BOOKID | VARCHAR2(15) |
读者编号 | READERID | VARCHAR2(15) |
借书日期 | BORROWDATE | VARCHAR2(20) |
还书表
图书编号 | BOOKID | VARCHAR2(15) |
读者编号 | READERID | VARCHAR2(15) |
还书日期 | RETURNDATE | VARCHAR2(20) |
界面设计
最后贴几张运行的界面(做完这个我再也不想做界面了,以前觉得会做界面多酷啊::>_<:: )
代码被我弄成一坨了,本来是写出多个文件的,后来干脆直接弄一起,DEBUG还方便些。可能还是分模块多个文件逻辑更清晰吧。
#! /usr/bin/env python
# -*- coding: gbk -*-
''' A simple library management system.'''
#--------------------------------------------------------------------------------
import wx
import cx_Oracle
import wx.html
import wx.grid
import string
import cx_Oracle
import sys
#--------------------------------------------------------------------------------
#defining my database class
class LMSDatabase:
def __init__(self, username, userpwd, host, port, dbname):
self.username = username
self.userpwd = userpwd
self.host = host
self.port = port
self.dbname = dbname
self.dsn = cx_Oracle.makedsn(self.host, self.port, self.dbname)
self.connection= cx_Oracle.connect(self.username, self.userpwd, self.dsn)
def execute(self, sql):
''' (LMSDatabase, str) -> Type
Execute a sql statement, if there is a result, return the result,
else return None.
'''
cursor = self.connection.cursor()
cursor.execute(sql)
if sql.startswith('select') or sql.startswith('SELECT'):
result = cursor.fetchall()
if result:
return result
else:
return None
def OnClose(self):
self.connection.close()
#-------------------------------------------------------------------------------
#defining BookTable class for displaying table in the main frame
class BookEntry:
def __init__(self, data, dataTypes, colLabels):
self.data = data
self.dataTypes = dataTypes
self.colLabels = colLabels
class BookTable(wx.grid.PyGridTableBase):
def __init__(self, entries):
wx.grid.PyGridTableBase.__init__(self)
self.entries = entries
def GetNumberRows(self):
return len(self.entries.data) + 1
def GetNumberCols(self):
return len(self.entries.data[0])
def GetColLabelValue(self, col):
return self.entries.colLabels[col]
def IsEmptyCell(self, row, col):
return False
def GetValue(self, row, col):
try:
return self.entries.data[row][col]
except IndexError:
return ''
def SetValue(self, row, col, value):
pass
class BookGrid(wx.grid.Grid):
def __init__(self, parent, database):
wx.grid.Grid.__init__(self, parent, id = -1)
self.dataTypes = [wx.grid.GRID_VALUE_STRING,
wx.grid.GRID_VALUE_STRING,
wx.grid.GRID_VALUE_STRING,
wx.grid.GRID_VALUE_STRING,
wx.grid.GRID_VALUE_FLOAT,
wx.grid.GRID_VALUE_STRING
]
self.colLabels = ['图书编号', '名称', '作者', '出版社', '价格', '分类', '是否借阅']
result = database.execute('SELECT * FROM BOOK ORDER BY BOOKID ASC')
bookData = []
for eachTuple in result:
bookData.append(list(eachTuple))
bookEntry = BookEntry(bookData, self.dataTypes, self.colLabels)
tableBase = BookTable(bookEntry)
self.SetTable(tableBase, True)
self.SetRowLabelSize(0)
self.AutoSizeColumns(False)
self.AutoSizeRows(True)
#-------------------------------------------------------------------------------
#defining the LoginDialog class
class LoginDialog(wx.Dialog):
def __init__(self, parent, id, title,
size = (350, 200),
pos = wx.DefaultPosition,
style = wx.DEFAULT_DIALOG_STYLE, useMetal = False):
try:
self.lmsDatabase = LMSDatabase('scott', 'tiger', 'localhost', 1521, 'system')
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
raise SystemExit
pre = wx.PreDialog()
pre.Create(parent, id, title, pos, size, style)
self.PostCreate(pre)
self.user, self.password = '', ''
self.CreateSizer()
def dataEntries(self):
return (('用户 ', 0, self.OnUser),('密码 ', wx.TE_PASSWORD, self.OnPassword))
def dataButtons(self):
return ((wx.ID_OK, '确定'),(wx.ID_CANCEL, '取消'))
def CreateSizer(self):
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(wx.StaticText(self, -1, '请输入用户名和密码'), 0, wx.ALIGN_CENTER | wx.ALL, 5)
for eachLabel, eachStyle, eachHandler in self.dataEntries():
self.CreateEntry(sizer, eachLabel, eachStyle, eachHandler)
sizer.Add(wx.StaticLine(self, -1, size=(20, -1), style=wx.LI_HORIZONTAL),
0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.TOP, 5)
btnsizer = wx.StdDialogButtonSizer()
for eachId, eachLabel in self.dataButtons():
self.CreateButton(btnsizer, eachId, eachLabel)
btnsizer.Realize()
sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
self.SetSizer(sizer)
sizer.Fit(self)
def CreateEntry(self, sizer, label, style, handler):
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(wx.StaticText(self, -1, label), 0, wx.ALIGN_CENTER | wx.ALL, 5)
text = wx.TextCtrl(self, -1, "", size = (80, -1), style = style)
text.Bind(wx.EVT_TEXT, handler)
box.Add(text, 1, wx.ALIGN_CENTER | wx.ALL, 5)
sizer.Add(box, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
def CreateButton(self, btnsizer, id, label):
button = wx.Button(self, id, label)
if id == wx.ID_OK:
button.SetDefault()
btnsizer.AddButton(button)
def OnUser(self, event):
self.user = event.GetString()
def OnPassword(self, event):
self.password = event.GetString()
def Authentication(self):
'''
Return true if it is successfully authenticated.
'''
sql = 'select * from users where username = \'' + self.user + '\''
try:
result = self.lmsDatabase.execute(sql)
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
if result and self.password == result[0][2]:
return result
else:
return False
#-------------------------------------------------------------------------------
#Main frame class
class LibraryManFrame(wx.Frame):
def __init__(self, parent = None):
self.title = "图书馆管理系统"
wx.Frame.__init__(self, parent, -1, self.title, size = (800, 600),
style = wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
#database connection
try:
self.lmsDatabase = LMSDatabase('scott', 'tiger', 'localhost', 1521, 'system')
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
raise SystemExit
#permision setting
self.userID = ''
self.permission = 'Visitor'
#main ui
self.panel = wx.Panel(self, -1)
self.panel.SetBackgroundColour("White")
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
text = wx.StaticText(self.panel, -1, self.title)
font = wx.Font(18, wx.ROMAN, wx.NORMAL, wx.NORMAL)
text.SetFont(font)
self.search = wx.SearchCtrl(self.panel, value = "请输入您要搜索的图书名或关键字", size = (400, -1), style = wx.TE_PROCESS_ENTER)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(text, 0, wx.ALL | wx.CENTER, 40)
self.sizer.Add(self.search, 0, wx.ALL | wx.CENTER, 15)
#Functions for initialize the App
self.createMenuBar()
#Bindings
self.Bind(wx.EVT_TEXT_ENTER, self.OnDoSearch, self.search)
self.panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
self.SetSizer(self.sizer)
def menuData(self):
return [("&菜单", (
("&登录系统", "Login", self.OnLogin),
("&保存修改", "Save Change", self.OnSave),
("", "", ""),
("&退出系统", "Quit", self.OnCloseWindow))),
("&图书馆", (
("&图书归还", "Book Statistic", self.OnReturn),
("&图书借阅", "Book Statistic", self.OnBorrow),
("&图书统计", "Book Statistic", self.OnStatistics),
("&打印报表", 'Print Report Forms', self.OnReportForms),
("&管理图书", (
("&添加图书", "Add book information", self.OnAdd),
("&修改图书", "Modify book information", self.OnModify),
("&删除图书", "Delete book information", self.OnDelete))),
("&关于程序", "Software information", self.OnAbout)))
]
def createMenuBar(self):
menuBar = wx.MenuBar()
for eachMenuData in self.menuData():
menuLabel = eachMenuData[0]
menuItems = eachMenuData[1]
menuBar.Append(self.createMenu(menuItems), menuLabel)
self.SetMenuBar(menuBar)
def createSubMenu(self, menuData):
menu = wx.Menu()
for eachLabel, eachStatus, eachHandler in menuData:
if not eachLabel:
menu.AppendSeparator()
continue
menuItem = menu.Append(-1, eachLabel, eachStatus)
self.Bind(wx.EVT_MENU, eachHandler, menuItem)
return menu
def createMenu(self, menuData):
menu = wx.Menu()
for eachItem in menuData:
if len(eachItem) == 2:
label = eachItem[0]
subMenu = self.createSubMenu(eachItem[1])
menu.AppendMenu(wx.NewId(), label, subMenu)
else:
self.createMenuItem(menu, *eachItem)
return menu
def createMenuItem(self, menu, label, status, handler, kind = wx.ITEM_NORMAL):
if not label:
menu.AppendSeparator()
return
menuItem = menu.Append(-1, label, status, kind)
self.Bind(wx.EVT_MENU, handler, menuItem)
#-------------------------------------------------------------------------------
#---------------------handlers are here-----------------------------------------
def OnLogin(self, evt):
dialog = LoginDialog(None, -1, "登录")
result = dialog.ShowModal()
if result == wx.ID_OK:
if dialog.Authentication():
login_info = dialog.Authentication()
self.permission = login_info[0][-1]
self.userID = login_info[0][0]
if self.permission == 'Admin':
wx.MessageBox('以管理员身份登陆成功!', 'Bonjour!')
else:
wx.MessageBox('登陆成功!', 'Bonjour!')
else:
wx.MessageBox('用户名或密码错误', 'Error!')
dialog.Destroy()
def OnBorrow(self, evt):
if self.permission == 'Visitor':
wx.MessageBox('您现在的身份为游客,\n请以用户身份登录!', '提示')
if self.permission == 'Admin':
wx.MessageBox('您无法使用此功能。', '提示')
if self.permission == 'User':
dlg = BorrowDialog(self, '请输入您要借阅的图书编号和日期:', '借书')
result = dlg.ShowModal()
if result == wx.ID_OK:
id, borrowtime = dlg.GetValue()[0], dlg.GetValue()[1]
sql = 'SELECT * FROM BOOK WHERE BOOKID = \'' + id + '\''
try:
result = self.lmsDatabase.execute(sql)
borrow_sql = 'SELECT BORROWED FROM BOOK WHERE BOOKID = \'%s\'' % id
borrow_status = self.lmsDatabase.execute(borrow_sql)[0][0]
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
if result and borrow_status == 'N':
#update owner table
sql_owner = 'INSERT INTO OWNER VALUES(\'%s\', \'%s\', \'%s\')' % (id, self.userID, borrowtime)
self.lmsDatabase.execute(sql_owner)
#update reader table
num_result = self.lmsDatabase.execute('SELECT BBN FROM READER WHERE READERID = \'%s\'' % self.userID)
num = num_result[0][0]
sql_reader = 'UPDATE READER SET BBN = %s WHERE READERID = \'%s\'' %(str(num + 1), self.userID)
self.lmsDatabase.execute(sql_reader)
#upadate book table
sql_book = 'UPDATE BOOK SET BORROWED = \'Y\' WHERE BOOKID = \'%s\'' % id
self.lmsDatabase.execute(sql_book)
else:
wx.MessageBox('您要借阅的图书不存在或已被借阅!', '提示')
dlg.Destroy()
def OnReturn(self,evt):
if self.permission == 'Visitor':
wx.MessageBox('您现在的身份为游客,\n请以用户身份登录!', '提示')
if self.permission == 'Admin':
wx.MessageBox('您无法使用此功能。', '提示')
if self.permission == 'User':
dlg = BorrowDialog(self, '请输入您要归还的图书编号和日期:', '还书')
result = dlg.ShowModal()
if result == wx.ID_OK:
id, returntime = dlg.GetValue()[0], dlg.GetValue()[1]
sql = 'SELECT * FROM BOOK WHERE BOOKID = \'' + id + '\''
try:
result = self.lmsDatabase.execute(sql)
borrow_sql = 'SELECT BORROWED FROM BOOK WHERE BOOKID = \'%s\'' % id
borrow_status = self.lmsDatabase.execute(borrow_sql)[0][0]
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
if result and borrow_status == 'Y':
#update returnbook table
sql_owner = 'INSERT INTO returnbook VALUES(\'%s\', \'%s\', \'%s\')' % (id, self.userID, returntime)
self.lmsDatabase.execute(sql_owner)
#update reader table
num_result = self.lmsDatabase.execute('SELECT BBN FROM READER WHERE READERID = \'%s\'' % self.userID)
num = num_result[0][0]
sql_reader = 'UPDATE READER SET BBN = %s WHERE READERID = \'%s\'' %(str(num - 1), self.userID)
self.lmsDatabase.execute(sql_reader)
#upadate book table
sql_book = 'UPDATE BOOK SET BORROWED = \'N\' WHERE BOOKID = \'%s\'' % id
self.lmsDatabase.execute(sql_book)
else:
wx.MessageBox('您要归还的图书不存在或已归还!', '提示')
def OnStatistics(self, evt):
raw_types = self.lmsDatabase.execute('select type from BOOK')
bookTypes = []
for types in raw_types:
for eachType in types[0].split('\\'):
if eachType not in bookTypes:
bookTypes.append(eachType)
bookStatistic = {}
for eachType in bookTypes:
sql = 'select * from Book where Type like \'%' + eachType + '%\''
num = len(self.lmsDatabase.execute(sql))
bookStatistic[eachType] = num
dlg = StatisticDialog(self, bookStatistic)
dlg.ShowModal()
dlg.Destroy()
def OnReportForms(self, evt):
result = self.lmsDatabase.execute('SELECT * FROM BOOK')
if result:
dlg = ReportFormsDialog(self)
dlg.ShowModal()
dlg.Destroy()
else:
wx.MessageBox('表为空!', '信息')
def OnSave(self, evt):
self.lmsDatabase.connection.commit()
def OnAdd(self, evt):
if self.permission == 'Admin':
dlg = BookDialog(self, '请输入需要添加的图书信息')
result = dlg.ShowModal()
if result == wx.ID_OK:
sql = 'insert into Book (BOOKID, BOOKNAME, AUTHOR, PUBLISHER, PRICE, TYPE, BORROWED) VALUES ' + dlg.GetString()
try:
self.lmsDatabase.execute(sql)
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
dlg.Destroy()
else:
wx.MessageBox('权限不够!\n请以管理员身份登录!', '提示')
def OnModify(self, evt):
if self.permission == 'Admin':
dlg = BookDialog(self, '请输入需要修改的图书信息')
result = dlg.ShowModal()
if result == wx.ID_OK:
newBookData = dlg.GetValue()
sql = 'UPDATE BOOK SET BOOKNAME = \'' + newBookData[1] + '\', AUTHOR = \'' + \
newBookData[2] + '\', PUBLISHER = \'' + newBookData[3] + '\', PRICE = ' + \
newBookData[4] + ', TYPE = \'' + newBookData[5] + '\' WHERE BOOKID = \'' + \
newBookData[0] + '\''
try:
self.lmsDatabase.execute(sql)
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
dlg.Destroy()
else:
wx.MessageBox('权限不够!\n请以管理员身份登录!', '提示')
def OnDelete(self, evt):
if self.permission == 'Admin':
dlg = DelDialog(self, '请输入需要删除的图书ID')
result = dlg.ShowModal()
if result == wx.ID_OK:
sql = 'DELETE FROM BOOK WHERE BookID = \'%s\'' % dlg.GetValue()
try:
self.lmsDatabase.execute(sql)
except cx_Oracle.DatabaseError, exc:
error, = exc.args
wx.MessageBox('Oracle-Error-Message: ' + error.message, 'Error')
dlg.Destroy()
else:
wx.MessageBox('权限不够!\n请以管理员身份登录!', '提示')
def OnDoSearch(self, evt):
#To destroy the text used for the last search
pChildren = self.panel.GetChildren()
sChildren = self.sizer.GetChildren()
sWidgets = []
for sChild in sChildren:
sWidgets.append(sChild.GetWindow())
for pChild in pChildren:
if pChild not in sWidgets:
pChild.Destroy()
#-----------------------------------------------
keywords = self.search.GetValue()
if keywords:
sql = 'SELECT * FROM BOOK WHERE BOOKNAME LIKE \'%' + keywords + '%\' ORDER BY BOOKID ASC'
result = self.lmsDatabase.execute(sql)
if result:
resultText = '找到的相关图书信息如下:\n'
for eachTuple in result:
for eachElem in eachTuple:
resultText = resultText + str(eachElem) + ' '
resultText += '\n'
else:
resultText = '未找到相关图书信息。\n'
text = wx.StaticText(self.panel, -1, resultText)
self.sizer.Insert(2, text, flag = wx.ALL | wx.CENTER)
self.sizer.Layout()
self.sizer.Detach(text)
def OnEraseBackground(self, evt):
"""
Add a picture to the background
"""
dc = evt.GetDC()
# Added by me
cliWidth, cliHeight = self.GetClientSize()
if not dc:
dc = wx.ClientDC(self)
rect = self.GetUpdateRegion().GetBox()
dc.SetClippingRect(rect)
dc.Clear()
try:
image_file = 'background.png'
bmp = wx.Bitmap(image_file)
dc.DrawBitmap(bmp, 0, 0)
except wx._core.PyAssertionError:
wx.MessageBox("Image file %s not found" % image_file, 'Error')
raise SystemExit
def OnCloseWindow(self, event):
if wx.OK == wx.MessageBox('是否保存您所做的修改?', '提示', wx.OK | wx.CANCEL):
self.OnSave(self)
self.lmsDatabase.OnClose()
self.Destroy()
def OnAbout(self, evt):
dlg = LibraryManAbout(self)
dlg.ShowModal()
dlg.Destroy()
class LibraryManAbout(wx.Dialog):
text = '''
<html>
<body bgcolor="#9DC678">
<center><table bgcolor="#455481" width="100%" cellspacing="0"
cellpadding="0" border="1">
<tr>
<td align="center"><h1>Library Management System!</h1></td>
</tr>
</table>
</center>
<p><b>Librabry Management System</b> really took me a lot of time
to finish it. But I love the process!
</p>
<p><b>wxPython</b> are brought to you by
<b>Robin Dunn</b> and <b>Total Control Software</b>, Copyright
© 1997-2006.</p>
</body>
</html>
'''
def __init__(self, parent):
wx.Dialog.__init__(self, parent, -1, 'About',
size=(440, 400) )
html = wx.html.HtmlWindow(self)
html.SetPage(self.text)
button = wx.Button(self, wx.ID_OK, "Okay")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(html, 1, wx.EXPAND|wx.ALL, 5)
sizer.Add(button, 0, wx.ALIGN_CENTER|wx.ALL, 5)
self.SetSizer(sizer)
self.Layout()
class BorrowDialog(wx.Dialog):
def __init__(self, parent, aboutText, capital):
wx.Dialog.__init__(self, parent, -1, capital)
self.aboutText = aboutText
self.textCtrl = []
self.CreateSizer()
def CreateSizer(self):
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(wx.StaticText(self, -1, self.aboutText), 0, wx.ALL, 5)
sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
sizer_n = wx.BoxSizer(wx.HORIZONTAL)
sizer_n.Add(wx.StaticText(self, -1, '图书编号: '), 0, wx.ALIGN_RIGHT)
id = wx.TextCtrl(self)
self.textCtrl.append(id)
sizer_n.Add(id, 0, wx.ALL)
sizer_t = wx.BoxSizer(wx.HORIZONTAL)
sizer_t.Add(wx.StaticText(self, -1, '借阅时间: '), 0, wx.ALIGN_RIGHT)
time = wx.TextCtrl(self)
self.textCtrl.append(time)
sizer_t.Add(time, 0, wx.ALL)
sizer.Add(sizer_n, 0, wx.EXPAND|wx.ALL, 5)
sizer.Add(sizer_t, 0, wx.EXPAND|wx.ALL, 5)
self.CreateButton(sizer)
self.SetSizer(sizer)
sizer.Fit(self)
def CreateButton(self, sizer):
# Use standard button IDs
okay = wx.Button(self, wx.ID_OK)
okay.SetDefault()
cancel = wx.Button(self, wx.ID_CANCEL)
btns = wx.StdDialogButtonSizer()
btns.AddButton(okay)
btns.AddButton(cancel)
btns.Realize()
sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
def GetValue(self):
return (self.textCtrl[0].GetValue(), self.textCtrl[1].GetValue())
class ReportFormsDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, -1, '报表打印')
grid = BookGrid(self, parent.lmsDatabase)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 0, wx.ALL, 10)
self.SetSizer(sizer)
sizer.Fit(self)
class StatisticTable(wx.grid.PyGridTableBase):
def __init__(self, data, rowLabels=None, colLabels=None):
wx.grid.PyGridTableBase.__init__(self)
self.data = data
self.rowLabels = rowLabels
self.colLabels = colLabels
def GetNumberRows(self):
return len(self.rowLabels)
def GetNumberCols(self):
return len(self.colLabels)
def GetColLabelValue(self, col):
if self.colLabels:
return self.colLabels[col]
def GetRowLabelValue(self, row):
if self.rowLabels:
return self.rowLabels[row]
def IsEmptyCell(self, row, col):
return False
def GetValue(self, row, col):
return self.data[row][col + 1]
def SetValue(self, row, col, value):
pass
class StatisticGrid(wx.grid.Grid):
def __init__(self, parent, data, rowLabels, colLabels):
wx.grid.Grid.__init__(self, parent, -1)
tableBase = StatisticTable(data, rowLabels, colLabels)
self.SetTable(tableBase)
class StatisticDialog(wx.Dialog):
def __init__(self, parent, bookStatistic):
wx.Dialog.__init__(self, parent, -1, '图书统计')
data = []
for key in bookStatistic:
data.append((key, bookStatistic[key]))
rowLabels = bookStatistic.keys()
colLabels = ['图书数量']
grid = StatisticGrid(self, data, rowLabels, colLabels)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 0, wx.ALL, 10)
self.SetSizer(sizer)
sizer.Fit(self)
class BookInfoValidator(wx.PyValidator):
def __init__(self, flag):
wx.PyValidator.__init__(self)
self.flag = flag
self.Bind(wx.EVT_CHAR, self.OnChar)
def Clone(self):
"""
Note that every validator must implement the Clone() method.
"""
return BookInfoValidator(self.flag)
def Validate(self, win):
textCtrl = self.GetWindow()
text = textCtrl.GetValue()
if len(text) == 0:
wx.MessageBox("This field must contain some text!", "Error")
textCtrl.SetBackgroundColour("pink")
textCtrl.SetFocus()
textCtrl.Refresh()
return False
else:
textCtrl.SetBackgroundColour(
wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
textCtrl.Refresh()
return True
def TransferToWindow(self):
return True
def TransferFromWindow(self):
return True
def OnChar(self, evt):
key = evt.GetKeyCode()
if key <= 255:
char = chr(key)
if self.flag == "no-alpha" and char in string.letters:
return
if self.flag == "no-digit" and char in string.digits:
return
if self.flag != "any" and key > 255:
return
evt.Skip()
class BookDialog(wx.Dialog):
def __init__(self, parent, aboutText):
wx.Dialog.__init__(self, parent, -1, "图书信息")
self.about = wx.StaticText(self, -1, aboutText)
self.bookEntry = []
self.CreateSizer()
def dataText(self):
return (('图书编号:', 'no-alpha'), ('图书名称:', 'any'),
('作者:', 'any'), ('出版社:', 'any'),
('价格:', 'any'), ('类别:', 'any')
)
def CreateSizer(self):
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.about, 0, wx.ALL, 5)
sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
fgs = wx.FlexGridSizer(6, 2, 5, 5)
for eachLabel, eachFlag in self.dataText():
self.CreateEntry(fgs, eachLabel, eachFlag)
sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
self.CreateButton(sizer)
self.SetSizer(sizer)
sizer.Fit(self)
def CreateEntry(self, sizer, label, flag):
sizer.Add(wx.StaticText(self, -1, label), 0, wx.ALIGN_RIGHT)
text = wx.TextCtrl(self, validator=BookInfoValidator(flag))
self.bookEntry.append(text)
sizer.Add(text, 0, wx.EXPAND)
def CreateButton(self, sizer):
# Use standard button IDs
okay = wx.Button(self, wx.ID_OK)
okay.SetDefault()
cancel = wx.Button(self, wx.ID_CANCEL)
btns = wx.StdDialogButtonSizer()
btns.AddButton(okay)
btns.AddButton(cancel)
btns.Realize()
sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
def GetValue(self):
result = []
for eachText in self.bookEntry:
result.append(eachText.GetValue())
return result
def GetString(self):
'''
Return a string in the format like this ('', '', '').
'''
raw_result = self.GetValue()
result = '(' + '\'' + raw_result[0] + '\', ' + '\'' + raw_result[1] + '\', ' + \
'\'' + raw_result[2] + '\', ' + '\'' + raw_result[3] + '\', ' + \
raw_result[4] + ', ' + '\'' + raw_result[-1] + '\', \'N\')'
return result
class DelDialog(wx.Dialog):
def __init__(self, parent, aboutText):
wx.Dialog.__init__(self, parent, -1, "删除")
self.about = wx.StaticText(self, -1, aboutText)
self.text = []
self.CreateSizer()
def CreateSizer(self):
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.about, 0, wx.ALL, 5)
sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
sizer_t = wx.BoxSizer(wx.HORIZONTAL)
sizer_t.Add(wx.StaticText(self, -1, '图书ID: '), 0, wx.ALIGN_RIGHT)
text = wx.TextCtrl(self)
self.text.append(text)
sizer_t.Add(text, 0, wx.ALL)
sizer.Add(sizer_t, 0, wx.EXPAND|wx.ALL, 5)
self.CreateButton(sizer)
self.SetSizer(sizer)
sizer.Fit(self)
def CreateButton(self, sizer):
# Use standard button IDs
okay = wx.Button(self, wx.ID_OK)
okay.SetDefault()
cancel = wx.Button(self, wx.ID_CANCEL)
btns = wx.StdDialogButtonSizer()
btns.AddButton(okay)
btns.AddButton(cancel)
btns.Realize()
sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
def GetValue(self):
return self.text[0].GetValue()
class LibraryManApp(wx.App):
def OnInit(self):
frame = LibraryManFrame(None)
frame.Show(True)
self.SetTopWindow(frame)
return True
if __name__ == '__main__':
app = LibraryManApp(False)
app.MainLoop()