wxPython: When selecting a row on frame1 the same row is selected on frame2

Hi, I’ve already posted on the mail list but I guess everyone migrated here so I copy-paste my question here. Thank you.

I have a code that extracts some minimalist data using API and when double-clicking on a cell it opens a new frame with more detailed data about that row. I also select the complete row when a cell is clicked.

My problem is that when I select a row on the second frame it is also selected on the first frame. Also, when I try to select row #10, for example, on the second frame and the first frame contains less rows, the row won’t select and I receive an error message saying that the row doesn’t exist.

Is there a way to differentiate between the 2 frames? I tried renaming the second frame TestFrame1 but that doesn’t change anything.

Here is the code of the first frame, the second one is based on the same template with the only difference TestFrame1 instead of TestFrame. Thank you,

class SimpleGrid(gridlib.Grid): 
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)


        # test all the events
        self.Bind(gridlib.EVT_GRID_SELECT_CELL, self.OnSelectCell)

    def openPublishers(self, evt):

        from publishers import TestFrame1
        frame = TestFrame1(self, sys.stdout)
        frame.Show()

    #Select complete row
    def OnSelectCell(self, evt): 
         self.log.write("OnSelectCell: (%d,%d) %s\n" % 
                        (evt.GetRow(), evt.GetCol(), evt.GetPosition())) 
         self.SelectRow(evt.GetRow()) 
         evt.Skip() 

    #open TestFrame1
    def openPublishers(self, evt):

        from publishers import TestFrame1
        frame = TestFrame1(self, sys.stdout)
        frame.Show()

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, 0, "Report", size=(1400,800))
        self.grid = SimpleGrid(self, log)

if __name__ == '__main__':
    import sys
    from wx.lib.mixins.inspection import InspectableApp
    app = InspectableApp(False)
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    #import wx.lib.inspection
    #wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()

Thanks again,

Please see HOWTO: Get help with a small runnable sample and edit your example above.

Thanks.

I’m sorry I thought that my problem is located within the few code lines I shared above. I’m not sure though that I can replicate my problem in a small code as I don’t know which part of it I should reproduce and I have a couple thousand lines on the first frame alone.
I don’t want a straight answer, just a guess of what may be the problem. I’m sure that the fact that I used the same template for both the frames has something to do with it, I’m just not able to put a finger on it.Thank you,

This:

makes me think that there is some issue with the event handlers catching events from the wrong source window, or perhaps the events are propagating to the wrong parent windows or something. Removing the evt.Skip() in OnSelectCell may help, but events should not be propagating beyond their top-level parent, so there is likely some other root cause even if that helps.

The point is that going through the exercise of narrowing down your problem in order to make a small runnable example will help you to understand the problem better, and perhaps even solve it for yourself.

Thank you for taking the time to help.

Unfotunately it doesn’t work, It has always worked on the first double click on the row, I can select any row on the second frame, but I get the error after that if I open other 2nd frames.

About narrowing, the frame is the foundation of my script and trying to mess with it may rise some other errors in the future that won’t be able to handle as I’m taking baby steps with this first attempt with wxPython. I’m a newbie with Python in general.

You were right, I’ve removed the Skip from the second Frame and it worked. But I still have the problem about the index column.

I’ve created a minimalist code that is replicating my issue, but I can’t upload files as I’m new to the forum. You can find the files on my thread on the mailing list.

Execute reportWindow.py and double-click on any cell and it will open publishers.py. Now, publishers.py contains more rows than reportWindow.py, so if you click on the 4th row and up, it will generate the error I was talking about.

Thank you.

reportWindow.py:

import wx
import wx.grid as gridlib

class SimpleGrid(gridlib.Grid):
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)

        self.wxFont = "9, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL"

        self.CreateGrid(3, 3)#, gridlib.Grid.SelectRows)
        fontBold = wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD)

        self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDClick)
        self.SetReadOnly(1, 1, True)

        self.log = log

        # test all the events
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnCellLeftClick)
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDClick)
        self.Bind(gridlib.EVT_GRID_SELECT_CELL, self.OnSelectCell)

    ######## Get Left click value ##################
    def OnCellLeftClick(self, evt):
        self.log.write("OnCellLeftClick: (%d,%d,%s) %s\n" %
                       (evt.GetRow(), evt.GetCol(), self.GetCellValue(evt.GetRow(), evt.GetCol()), evt.GetPosition()) )
        evt.Skip()
    ######## Get Left double click value ##################
    def OnCellLeftDClick(self, evt):
        print(self.GetCellValue(evt.GetRow(), 1))
        print(self.GetCellValue(evt.GetRow(), 18))

        font = wx.Font(self.wxFont)
        evt.Skip()

    def OnCellLeftDClick(self, evt):
        print(self.GetCellValue(1, 1))

        font = wx.Font(self.wxFont)

        from publishers import TestFrame
        frame = TestFrame(self, sys.stdout)
        frame.Show()

    #Select complete row
    def OnSelectCell(self, evt):
         self.log.write("OnSelectCell: (%d,%d) %s\n" %
                        (evt.GetRow(), evt.GetCol(), evt.GetPosition()))
         self.SelectRow(evt.GetRow())
         evt.Skip()

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, 0, "Report By Campaigns", size=(400,400))
        self.grid = SimpleGrid(self, log)

        #[...Some code...]

if __name__ == '__main__':
    import sys
    from wx.lib.mixins.inspection import InspectableApp
    app = InspectableApp(False)
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    #import wx.lib.inspection
    #wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()

publishers.py:

import wx
import wx.grid as gridlib

class SimpleGrid(gridlib.Grid):
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)

        self.wxFont = "9, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL"

        self.CreateGrid(7, 8)#, gridlib.Grid.SelectRows)
        fontBold = wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD)

        self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDClick)
        self.SetReadOnly(1, 1, True)

        self.log = log

        # test all the events
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnCellLeftClick)
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDClick)
        self.Bind(gridlib.EVT_GRID_SELECT_CELL, self.OnSelectCell)

    ######## Get Left click value ################## 
    def OnCellLeftClick(self, evt):
        self.log.write("OnCellLeftClick: (%d,%d,%s) %s\n" %
                       (evt.GetRow(), evt.GetCol(), self.GetCellValue(evt.GetRow(), evt.GetCol()), evt.GetPosition()) )
        evt.Skip()
    ######## Get Left double click value ################## 
    def OnCellLeftDClick(self, evt):
        print(self.GetCellValue(evt.GetRow(), 1))
        print(self.GetCellValue(evt.GetRow(), 18))

        font = wx.Font(self.wxFont)

    #Select complete row
    def OnSelectCell(self, evt): 
         self.log.write("OnSelectCell: (%d,%d) %s\n" % 
                        (evt.GetRow(), evt.GetCol(), evt.GetPosition())) 
         self.SelectRow(evt.GetRow()) 
         #evt.Skip() 


class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, 0, "Publishers", size=(400,400))
        self.grid = SimpleGrid(self, log)

        #[...Some code...]


if __name__ == '__main__':
    import sys
    from wx.lib.mixins.inspection import InspectableApp
    app = InspectableApp(False)
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    #import wx.lib.inspection
    #wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()

As mentioned before the issue is that the events are continuing to propagate because the handers are calling evt.Skip, and since you made the parent of the 2nd frame be the grid in the first frame, then the events just kept on going.

2nd grid --> handler, Skip() --> 2nd Frame --> 1st Grid --> handler --> GetCellValue --> exception

There are three ways to fix this.

  1. First, you probably do not want the first grid to be the parent of the 2nd frame. Just pass None for the parent there, then the event propagation will terminate when it gets to the frame.

  2. Don’t call Skip in your event handlers unless you really do want to allow other handlers to catch the event.

  3. Be more specific when calling Bind. The way you are doing it now says that the binding is for that event coming from any source widget. If you pass the designated source widget in the 3rd parameter, or the source’s ID in the id parameter, then the binding will only match events coming from that widget. In other words:

        # instead of this
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDClick)

        # do this
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDClick, self)

Perfect, the third solution worked great. Thank you very much for your help, it’s appreciated…