how to...wxgrid.

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

how to...wxgrid.

Shizuo Takasu
Ok, I know that title is bit confusing, but I will explain.

First, hi all, I am new to this group. I learning Python for 4+ mounts now, version 2.7. I wanted to do some challenging, because you learn by doing it. I start making program that will connect to MySQL database, collect data from table, show it in wxGrid where user can then edit cell content, and add new row and fill it whit data. And on top of that change data will bee save in database / table. I create grid and insert data, but have problems whit adding new row and editing cell and saving it to table. As for adding new row, i made that when user is in the last cell in last row and hit ENTER key, program add new row, which is do, but not as intended, its only gray space whit no separate columns. AS for other problem, editing and saving, I have now clue where to start. Is it whit EVENT CELL CHANGE or something different. Can someone help me. I look on various  forums and groups, could not find answer. And pleas, pleas do not tell me to cheek  wxPython demo and read wiki and manual, I try that and got confuse even more. I think that is not made for someone how are new to programing.

Thank you.

 Унесите кôд овде...
import wx
import wx.grid as gridlib
import MySQLdb
import datetime



# Class main grid
class MyGrid(gridlib.Grid):
    def __init__(self, parent):
        gridlib.Grid.__init__(self, parent, )


        # Connecting to database
        def getData():
            db = MySQLdb.connect("127.0.0.1", "user", "pass", "database")
            cursor = db.cursor()
            query = "SELECT * FROM setup"
            cursor.execute(query)
            data = []
            res = cursor.fetchall()
            for i in res:
                data.append(i)
            return data

        #Colum names
        colnames = ["idSetup", "idKomitent", "Drzava", "Prg", "Provajder", "ServerName", "DataBaseName", "Sifarnici",
                    "Promena"]

        #Setup
        data = getData()
        plugins = None
        self.data = data
        self.colnames = colnames
        self.plugins = plugins or {}

        #Number of rows
        def GetNumberRed(self):
            return int(len(self.data))

       
#Number of rows
 def GetNumberRows(self):
            return len(self.data)

        #Number of columns
        def GetNumberCols(self):
            return int(len(self.colnames))

        #Creating grid
        col = GetNumberCols(self)
        row = GetNumberRed(self)
        self.CreateGrid(row, col)
        self.ChangedValue = False
        self.EnableEditing(True)
        self.EnableGridLines(True)
        self.EnableDragGridSize(False)
        self.SetMargins(0, 0)
        self.inner_sizer = wx.BoxSizer(wx.VERTICAL)
        self._rows = self.GetNumberRows()
        self._cols = self.GetNumberCols()

        #Setup names of columns
        self.SetColLabelValue(0, "idSetup")
        self.SetColLabelValue(1, "idKomitent")
        self.SetColLabelValue(2, "Drzava")
        self.SetColLabelValue(3, "Prg")
        self.SetColLabelValue(4, "Provajder")
        self.SetColLabelValue(5, "ServerName")
        self.SetColLabelValue(6, "DataBaseName")
        self.SetColLabelValue(7, "Sifarnici")
        self.SetColLabelValue(8, "Promena")

        # Columns
        self.EnableDragColMove(False)
        self.EnableDragColSize(True)
        self.SetColLabelSize(30)
        self.SetColLabelAlignment(wx.ALIGN_CENTER, wx.ALIGN_CENTER)

        # Cell Defaults
        self.SetDefaultCellAlignment(wx.ALIGN_LEFT, wx.ALIGN_TOP)
        self.inner_sizer.Add(self, 1, wx.ALL | wx.EXPAND, 5)

        #Table streching
        self.SetSizer(self.inner_sizer)
        self.Layout()
        self.inner_sizer.Fit(self)
        self.Bind(wx.EVT_SIZE, self.OnSize)

        #Inserting data into table
        for i, seq in enumerate(data):
            for j, v in enumerate(seq):
                if isinstance(v, (int, long,)):
                    v = str(v)
                elif isinstance(v, datetime.datetime):
                    v = v.strftime('%d-%m-%Y')
                try:
                    self.SetCellValue(i, j, v)

                except TypeError:

                    raise RuntimeError(('SetCellValue failed with TypeError', i, j, v))

        #Some function that should help me
        def GetValue(self, row, col):
            return str(self.data[row][1].get(self.GetColLabelValue(col), ""))

        def GetRawValue(self, row, col):
            return self.data[row][1].get(self.GetColLabelValue(col), "")

        def SetValue(self, row, col, value):
            self.data[row][1][self.GetColLabelValue(col)] = value

        #Events
        self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
        self.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.OnCellChange)

#This is function for editing cell
    def OnCellChange(self, evt):
        pass


    #Enter key press
    def onKeyDown(self, evt):
        if evt.GetKeyCode() != wx.WXK_RETURN:
            evt.Skip()
            return

        if evt.ControlDown():  # the edit control needs this key
            evt.Skip()
            return

        self.DisableCellEditControl()
        success = self.MoveCursorRight(evt.ShiftDown())

        if not success:
            newRow = self.GetGridCursorRow() + 1

            if newRow < self.GetTable().GetNumberRows():
                self.SetGridCursor(newRow, 0)
                self.MakeCellVisible(newRow, 0)
            else:
                newRow = self.GetGridCursorRow() + 1
                self.appendRow()
                self.SetGridCursor(newRow, 0)
                self.MakeCellVisible(newRow, 0)
                self.ChangedValue = False
   
#Adding new row
    def Reset(self):
        """reset the view based on the data in the table.  Call
        this when rows are added or destroyed"""
        self.ResetView(self)
        self.ro_attr = gridlib.GridCellAttr()
        self.ro_attr.SetReadOnly(True)
        self.SetRowAttr(self.GetNumberRows() - 1,self.ro_attr)
        self.ro_attr = gridlib.GridCellAttr()
        self.ro_attr.SetReadOnly(False)
        self.SetRowAttr(self.GetNumberRows() - 2,self.ro_attr)

    def ResetView(self, grid):
        """
        (Grid) -> Reset the grid view.   Call this to
        update the grid if rows and columns have been added or deleted
        """
        grid.BeginBatch()

        for current, new, delmsg, addmsg in [
            (self._rows, self.GetNumberRows(), gridlib.GRIDTABLE_NOTIFY_ROWS_DELETED,
             gridlib.GRIDTABLE_NOTIFY_ROWS_APPENDED),
            (self._cols, self.GetNumberCols(), gridlib.GRIDTABLE_NOTIFY_COLS_DELETED,
             gridlib.GRIDTABLE_NOTIFY_COLS_APPENDED),
        ]:

            if new < current:
                msg = gridlib.GridTableMessage(self, delmsg, new, current - new)
                grid.ProcessTableMessage(msg)
            elif new > current:
                msg = gridlib.GridTableMessage(self, addmsg, new - current)
                grid.ProcessTableMessage(msg)
                self.UpdateValues(grid)

        grid.EndBatch()

        self._rows = self.GetNumberRows()
        self._cols = self.GetNumberCols()

        # update the column rendering plugins
        self._updateColAttrs(grid)

        # update the scrollbars and the displayed part of the grid
        grid.AdjustScrollbars()
        grid.ForceRefresh()

    def UpdateValues(self, grid):
        """Update all displayed values"""
        # This sends an event to the grid table to update all of the values
        msg = gridlib.GridTableMessage(self, gridlib.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
        grid.ProcessTableMessage(msg)

    def _updateColAttrs(self, grid):
        """
        wx.Grid -> update the column attributes to add the
        appropriate renderer given the column name.  (renderers
        are stored in the self.plugins dictionary)

        Otherwise default to the default renderer.
        """
        col = 0

        for colname in self.colnames:
            attr = gridlib.GridCellAttr()
            if colname in self.plugins:
                renderer = self.plugins[colname](self)

                if renderer.colSize:
                    grid.SetColSize(col, renderer.colSize)

                if renderer.rowSize:
                    grid.SetDefaultRowSize(renderer.rowSize)

                # attr.SetReadOnly(True)
                attr.SetRenderer(renderer)

            grid.SetColAttr(col, attr)
            col += 1
        grid.SetSize((340, 200))

    def appendRow(self):
        self.AppendRow(self.GetNumberRows())
        self.Reset()

    def AppendRow(self, row):
        self.data[self.GetNumberRows() -1]
        entry = {}
        self.data.insert(int(row), (str(row), entry))


    def OnSize(self, event):
        width, height = self.GetClientSizeTuple()
        for col in range (9):
                self.SetColSize(col, width/(9 + 1))
#-----------------------------------------------------------------------------------------------------------------------
#Class main window
class GlavniProzor(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title = "Editor", size = (500, 1000))
        self.Show()
        self.CenterOnScreen()

        #Panel
        panel = wx.Panel(self)
        mygrid = MyGrid(panel)

        #Box
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(mygrid, 1, wx.EXPAND|wx.ALL)
        panel.SetSizer(sizer)
        sizer.Fit(self)

#Run
if __name__ == "__main__":
    app = wx.App()
    frame = GlavniProzor()
    app.MainLoop()


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: how to...wxgrid.

Tim Roberts
Shizuo Takasu wrote:

>
> First, hi all, I am new to this group. I learning Python for 4+ mounts
> now, version 2.7. I wanted to do some challenging, because you learn
> by doing it. I start making program that will connect to MySQL
> database, collect data from table, show it in wxGrid where user can
> then edit cell content, and add new row and fill it whit data. And on
> top of that change data will bee save in database / table. I create
> grid and insert data, but have problems whit adding new row and
> editing cell and saving it to table. As for adding new row, i made
> that when user is in the last cell in last row and hit ENTER key,
> program add new row, which is do, but not as intended, its only gray
> space whit no separate columns.

You have a couple of problems here.  At the end of _updateColAttrs, you have

            grid.SetColAttr(col, attr)
            col += 1
        grid.SetSize((340, 200))

You certainly do not want the "SetSize" in there.  You don't know how
large the grid needs to be; the whole point here is for the grid to
automatically determine its new size.  The second issue is that in your
"appendRow" processing, you never actually append a row to the grid. 
You append some stuff to your data array (incorrectly), but you don't
change the grid.  You have this:

    def appendRow(self):
        self.AppendRow(self.GetNumberRows())
        self.Reset()

    def AppendRow(self, row):
        self.data[self.GetNumberRows() -1]
        entry = {}
        self.data.insert(int(row), (str(row), entry))

The first line in AppendRow does nothing at all.  I'm not sure what you
were expecting.  The third line here is going to append a tuple
consisting of a string and a dictionary, which is not the same as what
you fetched from the database.  You're going to want to simulate the
format of the database row here.

More important, nothing here actually appends the row, which is done by
calling AppendRows.  I suggest you replace all of that with:

    def appendRow(self):
        self.AppendRows( 1 )
        self.data.append((str(row), '', '', '', '', '', '', '', ''))
        self.Reset()

> AS for other problem, editing and saving, I have now clue where to
> start. Is it whit EVENT CELL CHANGE or something different.

Close -- gridlib.EVT_GRID_CELL_CHANGE.


> Can someone help me. I look on various  forums and groups, could not
> find answer. And pleas, pleas do not tell me to cheek  wxPython demo
> and read wiki and manual, I try that and got confuse even more. I
> think that is not made for someone how are new to programing.

Whether that's true or not, the demo is BY FAR the best way to learn
wxPython.  The grid is a very large and very complicated component --
one of the most complicated in the whole project.  The GridSimple.py
sample shows how to capture all of the events the grid can generate,
including EVT_GRID_CELL_CHANGE.  It is going to be your best source of
information.

--
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: how to...wxgrid.

Tim Roberts
Shizuo Takasu wrote:
First, thank you for answering my question.
Second, sorry for late replay i was on vacation.

I try code that you suggested.  Its working now, adding new row is ok, except that in line: "self.data.append((str(row), '', '', '', '', '', '', '', ''))", PyCharm notified me that i have, Unresolved reference 'row', and when i run program, despite its add new row i got error message:

self.data.append((str(row), '', '', '', '', '', '', '', ''))
NameError: global name 'row' is not defined

Is there any way to correct this by making row global variable?

You aren't thinking about what this code is actually doing.    The question is, what do you want the first column of the new row to be?  In the existing code, you have that as the row number.  Thus, you just need to generate that number:
        row = self.GetNumberRows()
-- 
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.