Форум сайта python.su
Вопрос не совсем точный в тексте темы. Просто туда много букв не помещается! >:(
Полный вопрос:
Имеется sqlite-база данных. Есть таблица (PyGridTableBase) для сетки (Grid). Есть учебник в котором написано как ими обоими пользоваться. Но там в качестве данных для пигрида (пардон) используется питоновский словарь. Мне же нужно запихать в пигрид результат sql-запроса. Я создаю курсор, делаю запрос, а затем делаю так:
tmp=cu.fetchall()
И эту tmp подставляю в качестве данных для пигрида. Всё путём получается. Грид с пигридом всё это кушают и выдают результат запроса в сетку, НО, выдают-то выдают, а изменить какую-нибудь ячейку невозможно. При попытке пользователя редактировать ячейку, после нажатия enter (принять новое значение ячейки) возвращается старое значение (до редактирования), а wx.Python пишет, что список не поддерживает операцию присваивания. Т.е. после нажатия enter моя программа пытается сделать так: tmp='новое значение', а питон говорит: фигушки тебе, вчера придёшь.
Думается, как-то по-другому нужно передавать данные в пигрид, чтоб имелась возможность изменять эти самые данные. Как?
Офлайн
А можно код? У меня ни на какие изменения в гриде питон не ругается. Может он у тебя ругается не при заполнении грида, а наоборот, когда ты измененные данные в базу пихаешь?
Офлайн
До пихания данных в базу я ещё и не добрался. Хорошо хоть, наконец-то, данные из запроса в сетку запихал. Может лучше ты дашь мне ма-а-а-а-а-аленький примерчик программки работающей с пигридом, гридом, да ещё и результат редактирования ячейки грида в sqlite-базу пихает. Как сделать последнее я, вообще, не соображаю. Как я должен узнавать, какая часть пигрида изменилась, а потом ещё и догадываться какой записи в базе данных она соответствовала? Программируя на фокспро с такими заморочками не сталкиваешься…
Пардон, за наглость. Жажда знаний обуревает. :)
А до моего примерчика нужно лезть на другой жёсткий диск, вырубать комп, подключать другой диск, загружать виндус, брать пример на флешку, отключать комп, подключать снова другой жёсткий диск, загружать виндус и выходить в интербред. Вот такой кошмар. Но я потом, всё ж попытаюсь.
Офлайн
Извини, что не быстро, на работе запарка! Вот тебе полноценный, работающий пример:
# -*- coding: cp1251 -*-
“Пример работы с гридом”
from wxPython.wx import *
from wxPython.grid import *
import wx.grid
import wx
from pysqlite2 import dbapi2 as db
mydb = ‘mydb.db’
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds = wxDEFAULT_FRAME_STYLE
wxFrame.__init__(self, *args, **kwds)
self.SetSize((550, 400))
font_1 = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.window1 = wxSplitterWindow(self, -1, style=wxNO_BORDER)
self.panel1 = wxPanel(self.window1, -1)
self.panel2 = wxPanel(self.window1, -1)
self.exit = wxButton(self.panel2, -1, “Выход”)
self.exit.SetFont(font_1)
self.create = wxButton(self.panel2, -1, “Создать бд”)
self.create.SetFont(font_1)
self.full1 = wxButton(self.panel2, -1, “Выгрузить в бд”)
self.full1.SetFont(font_1)
self.full2 = wxButton(self.panel2, -1, “Загрузить из бд”)
self.full2.SetFont(font_1)
#создание грида
self.grid = wxGrid(self.panel1, -1, size=(1, 1))
self.grid.CreateGrid(100, 3)
self.grid.SetRowLabelSize(40)
self.grid.SetColLabelSize(40)
self.grid.SetMinSize((500,300))
self.grid.SetColLabelValue(0, “Табельный\nномер”)
self.grid.SetColSize(0,80)
self.grid.SetColLabelValue(1, “ФИО”)
self.grid.SetColSize(1,250)
self.grid.SetColLabelValue(2, “Должность”)
self.grid.SetColSize(2,150)
EVT_BUTTON(self, self.create.GetId(), self.on_create)
EVT_BUTTON(self, self.full1.GetId(), self.on_full1)
EVT_BUTTON(self, self.full2.GetId(), self.on_full2)
EVT_BUTTON(self, self.exit.GetId(), self.on_exit) # выход
#EVT_GRID_CELL_CHANGE(self.grid, self.on_change) #событие на изменение данных в таблице на первой вкладке
#EVT_GRID_SELECT_CELL(self.grid, self.on_select) #событие на выбор ячейки
self.panel1.SetMinSize((550, 370))
self.panel2.SetMinSize((550, 30))
self.window1.SetMinSize((550, 400))
sizer = wxBoxSizer(wxVERTICAL) #сайзеры, на которых держатся элементы формы
sizer_1 = wxBoxSizer(wxVERTICAL)
sizer_2 = wxBoxSizer(wxHORIZONTAL)
sizer_1.Add(self.grid, -1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
sizer_2.AddMany([(self.create, -1, wx.EXPAND|wx.ADJUST_MINSIZE, 0),
(self.full1, -1, wx.EXPAND|wx.ADJUST_MINSIZE, 0),
(self.full2, -1, wx.EXPAND|wx.ADJUST_MINSIZE, 0),
(self.exit, -1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)])
self.panel1.SetSizer(sizer_1)
self.panel2.SetSizer(sizer_2)
self.window1.SplitHorizontally(self.panel1, self.panel2)
sizer.Add(self.window1, 1, wxALL|wxEXPAND, 0)
self.SetAutoLayout(True)
self.SetSizer(sizer)
self.Layout()
self.Centre()
def on_create(self, event):
con = db.connect(mydb)
cur = con.cursor()
try:
cur.execute(“”“
create table my (
numb integer,
fio varchar(200),
dolzh varchar(200));
”“”)
except db.DatabaseError, x:
print “Не могу создать базу!”, x
print “База создана!”
con.commit()
con.close()
event.Skip()
def on_full1(self, event):
con = db.connect(mydb)
cur = con.cursor()
var = {}
tb = self.grid.GetTable()
for i in range(tb.GetNumberRows()):
if tb.GetValue(i, 0) != ‘':
try:
cur.execute(“”“insert into my values(”“”+tb.GetValue(i, 0)+“”“,
’”“”+tb.GetValue(i, 1)+“”“',
‘”“”+tb.GetValue(i, 2)+“”“’);”“”)
except db.DatabaseError, x:
print “Не могу занести данные в базу!”, x
else:
break
print “Данные занесены!”
con.commit()
con.close()
event.Skip()
def on_full2(self, event):
con = db.connect(mydb)
cur = con.cursor()
var = {}
try:
cur.execute(“select * from my”)
except db.DatabaseError, x:
print “Не могу считать данные!”, x
rows = cur.fetchall()
cols = cur.description
for row in range(len(rows)):
for col in range(len(cols)):
values = unicode(rows)
self.grid.SetCellValue(row,col,values)
con.commit()
con.close()
self.Update()
print “Данные занесены!”
event.Skip()
def on_exit(self, event):
self.Destroy()
def on_select(self, event):
tb = self.grid.GetTable()
if tb.GetNumberRows() > 0:
r = self.grid.GetGridCursorRow()
print “Номер строки ”+str(r)+“!\n”
event.Skip()
def on_change(self, event):
row = self.grid.GetGridCursorRow()
col = self.grid.GetGridCursorCol()
val = self.grid.GetCellValue(row,col)
print ‘Изменилась ячейка ’+str(row)+','+str(col)+'! Новое значение ‘+str(val)+’!\n'
event.Skip()
class MyApp(wx.App):
def OnInit(self):
wxInitAllImageHandlers()
frame = MyFrame(None, -1, “Пример Грида”)
self.SetTopWindow(frame)
frame.Show()
return 1
if __name__ == “__main__”:
app = MyApp(redirect=True)
app.MainLoop()
Офлайн
Событие на изменение ячейки в примере заремарено.
Офлайн
ПроДива! Я Вас люблю! (не стоит принимать близко к сердцу :) )
С м-а-а-а-аленьким примерчиком я погорячился. В питоне, к сожалению, маленьких примерчиков не бывает. И PyGridTableBase в нём не фигурирует.
А вот и мой неработающий код, вернее не желающий присваивать новое значение ячейке. С использованием пигрида:
# -*- coding: utf-8 -*-
import wx, wx.grid, sqlite3 as db
class MainFrame(wx.Frame):
def __init__(self, parent, title, pos, size):
wx.Frame.__init__(self, parent, -1, title, pos=pos, size=size)
mypanel=self.mypanel=wx.Panel(self, -1)
c=db.connect(database='bigbase.sqlite3')
cu=c.cursor()
cu.execute('SELECT fam, im, ot FROM one')
mygrid=wx.grid.Grid(mypanel, size=(400,400))
cuu=cu.fetchall()
table=MyTable(cuu)
mygrid.SetTable(table, True)
class MyTable(wx.grid.PyGridTableBase):
def __init__(self, dannie):
wx.grid.PyGridTableBase.__init__(self)
self.dannie=dannie
def GetNumberRows(self):
return len(self.dannie)
pass
def GetNumberCols(self):
return len(self.dannie[0])
pass
def IsEmptyCell(self, row, col):
return self.dannie[row] [col] is not None
pass
def GetValue(self, row, col):
value = self.dannie[row] [col]
if value is not None:
return value
else:
return ''
pass
def SetValue(self, row, col, value):
self.dannie[row][col]=value
pass
if __name__==('__main__'):
myapp=wx.App()
MainFrame_=MainFrame(None, title=u'Таблица для сетки', pos=(100,100), size=(500,500))
MainFrame_.Show()
myapp.MainLoop()
Офлайн
ПроДива, ты используешь написанные на питоне программы в своей работе? Имею ввиду официальную работу, ту на которой деньги зарабатываешь.
Зачем в твоём примерчике кнопки-то в размерах увеличиваются при изменении размеров формы? Думается лучше было бы сетку растягивать.
У меня, кстати, не получается текстконтроль заставить растягиваться на всю форму. Пока в него текст не запихаешь, не желает растягиваться вертикально, мерзавец эдакий. Как заставить?
П.С. А чего это мой код нецветной получился?
Отредактировано (Ноя. 13, 2007 17:34:28)
Офлайн
FoxPythonДа, я разрабатываю программки для банка.
ПроДива, ты используешь написанные на питоне программы в своей работе? Имею ввиду официальную работу, ту на которой деньги зарабатываешь.
FoxPythonКнопки “сидят” на сайзерах, размещение на сайзерах элементов пропорциональное. В общем, при увеличении формы, увеличиваются и объекты на ней.
Зачем в твоём примерчике кнопки-то в размерах увеличиваются при изменении размеров формы?
FoxPythonА Вам принципиально? у меня используется GridTableBase, разницы между ними не вижу и не знаю.
И PyGridTableBase в нём не фигурирует.
FoxPythonНужно код вписывать в теги с открывающим “code:python”.
А чего это мой код нецветной получился?
Отредактировано (Ноя. 14, 2007 09:13:36)
Офлайн
proDiva
Ой, что-то то на ты, то на вы… Я прямо смущён, как лучше-то обращаться? Чтоб не обидеть.
>>>А Вам принципиально? у меня используется GridTableBase, разницы между ними не вижу и не знаю.
Ну, да, вобщем, поскольку я решил именно PyGridTableBase использовать. А кто такой GridTableBase без Py я тоже не знаю.
PyGridTableBase - это некая дополнительная таблица (не сама сетка-grid), которая отвечает за хранение данных и подсовывает их гриду. Для неё нужно переопределить пять функций-процедур, они описаны в моём примере в классе MyTable созданном от PyGridTableBase. Эти пять функций отвечают за слежение за размерностью таблица (кол-во строк, кол-во столбцов), за выдачу значения в сетку, за записывание значения в таблицу, а также за значение которое выдаётся сетке, если в ячейке таблицы пусто.
Всё это позволяет к примеру не заботиться об установке размеров грида. Функции GetNumberRows и GetNumberCols высчитают их сами и подсунут гриду в автоматическом порядке. Не нужно заботиться об присвоении значения каждой ячейке грида, это автоматом сделает SetValue, ну и т.д.
Всё дело в том, что я не могу передать в PyGridTableBase результат запроса из базы данных, типа cu.fetchall(). Не получается так. Пришлось скопировать это дело в другую переменную cuu=cu.fetchall() и её уже подсунуть для PyGridTableBase. А cuu получается в виде списка (tuple) и записать в него новые данные не выходит.
Офлайн
FoxPythonможно и на ты ;)
Ну, да, вобщем, поскольку я решил именно PyGridTableBase использовать. А кто такой GridTableBase без Py я тоже не знаю.
Офлайн