Alex Elkman
Alex Elkman

Reputation: 63

wxPython: Refresh a Frame with Updated Table

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):
            ...

Upvotes: 0

Views: 2765

Answers (2)

Alex Elkman
Alex Elkman

Reputation: 63

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.

Upvotes: 1

Gerrat
Gerrat

Reputation: 29680

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)

Upvotes: 0

Related Questions