0

I'm using pyodbc to make a GUI for viewing table info from my SQL database, currently my code kills the frame and regenerates it with the updated info. Here's an example of what it does when performing a search:

def nctDialog(self):
    global nct, frame, table
    dlg = wx.TextEntryDialog(
            self, 'Enter NCT # here:',
            'NCT Search', 'NCT #')

    if dlg.ShowModal() == wx.ID_OK:
        nct = ""
        if(str(dlg.GetValue()) != ""):
            nct =  int(dlg.GetValue())
        frame.Destroy()
        frame = TestFrame(None, sys.stdout)
        frame.Show(True)

    dlg.Destroy()

It works but it's mildly annoying to me to see the window reappear in a new place on the screen. What I really want to achieve is an update of the table info without killing the frame.

Is there a way to update a table in a frame without killing and remaking the frame in wxPython?

TestFrame is mostly uninsteresting ,it sets up the frame and calls CustTableGrid() which I will show after...

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
    ....
        grid = CustTableGrid(p, log)
    ....

CustTableGrid() creates a grid and calls:

class CustTableGrid(gridlib.Grid):
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)
    table = CustomDataTable(log)
    ....

CustomDataTable:

class CustomDataTable(gridlib.PyGridTableBase):


    def __init__(self, log):
        global nct, toDate, fromDate, isn
        gridlib.PyGridTableBase.__init__(self)
        self.log = log

        self.colLabels = [ 'Model', 'ISN', 'NCT', 'FW', 'Date', 'WWN']

        self.dataTypes = [ gridlib.GRID_VALUE_STRING,gridlib.GRID_VALUE_STRING,gridlib.GRID_VALUE_STRING,gridlib.GRID_VALUE_STRING,gridlib.GRID_VALUE_STRING,gridlib.GRID_VALUE_STRING,gridlib.GRID_VALUE_STRING,gridlib.GRID_VALUE_STRING]



        self.data = []


        cursor.execute("select ISN, WWN, Date, FW, Model, NCT, isCurrent, Date from [General Drive Info] order by [General Drive Info].Date desc")
        rows = cursor.fetchall()

        count = 0


        if(fromDate != None and toDate != None):
            ...
Alex Elkman
  • 63
  • 1
  • 8

2 Answers2

1

In the place of:

frame.Destroy()
frame = TestFrame(None, sys.stdout)
frame.Show(True)

I put:

    table.data[:] = []            #clear all prior data in the table
    table.nctCall()               #puts in the new data/performs nct query
    grid.ForceRefresh()           #forces refresh of the grid with new table

nctCall() is a def of class object CustomDataTable that modifes the data within the object to the desired values, and then ForceRefresh() the grid object to force it to show the changes.

Alex Elkman
  • 63
  • 1
  • 8
0

First off, I have to say that using globals is generally frowned upon.

That being said, without completely reorganizing your program, I'm going to have to make a number of assumptions about your global variables.

Instead of the:

frame.Destroy()
frame = TestFrame(None, sys.stdout)
frame.Show(True)

Assuming that both the table in your CustTableGrid class, and the grid in TestFrame is global (or you make them instance members and get references to them from somewhere higher up), you should be able to do something like:

first, update the data in CustomDataTable

next, use these lines in place of the Frame replacing ones:

msg = wx.grid.GridTableMessage(table, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
grid.ProcessTableMessage(msg)
Community
  • 1
  • 1
Gerrat
  • 28,863
  • 9
  • 73
  • 101
  • When you say update the data in CustomDataTable, do you mean simply calling 'grid.Update()'? I have tried this and it compiles, but the table remains the same when I call a search. – Alex Elkman Jun 17 '16 at 04:39
  • Additionally, I tried 'grid.ForceRefresh()' instead of 'Update()' with the same result. The way I set up my CustomDataTable, it will need to essentially recall it's class constructor again to redefine it's objects, this is what these defs should be doing to my knowledge. – Alex Elkman Jun 17 '16 at 05:00
  • I played around with other msg calls like 'GRIDTABLE_NOTIFY_ROWS_DELETED, 5, 3' instead of the one you suggested, and on search it does in fact delete 3 rows from the table and show the updated table. So your suggestion is on the right track, I just think there's something wrong with that specific message 'REQUEST_VIEW_GET_VALUES' or we are using it wrong. – Alex Elkman Jun 17 '16 at 05:06
  • I think the issue is the way I set my code up, I need to redefine my CustomDataTable object completely and have my grid update the change. – Alex Elkman Jun 17 '16 at 05:12
  • Instead of having to redefine the entire class object, what I need to do is simply change the data within it... I will post results soon. – Alex Elkman Jun 17 '16 at 05:23
  • Ok now it's working but not removing blank rows in the table, which is annoying. But I'm 90% there. Will post results in answer when it is complete. – Alex Elkman Jun 17 '16 at 05:29
  • @AlexElkman: When I said "update the data in CustomDataTable", I was only referring to updating it with the values from the database. (what you said your `nctCall` does). – Gerrat Jun 17 '16 at 13:04