2013-04-08 54 views
3

创建一个自定义wx.frame以包含内部具有两个网格控件的分离器窗口。它用于比较每个网格中的数据。此时两个网格的滚动条需要支持同步滚动。如何同步wx中两个网格的滚动条

问题:

  1. 如何获得这两个网格的滚动事件?我试图在框架中装入wx.EVT_SCROLL事件,但失败了。我也尝试绑定自定义网格控件中的滚动事件,但它也失败了。
  2. 如何同步滚动两个网格的滚动条?一个相对question的回答使用gridInstance.Scroll(row,col)来滚动网格客户端窗口。但它不包含如何同步滚动条。

非常感谢您的任何建议。

定制帧

def __init__(self, parent): 
     wx.Frame.__init__(self, parent, -1, title='', size=(640,480)) 
     main_panel = wx.Panel(self, -1) 
     self.TBFLAGS = (wx.TB_HORIZONTAL| wx.NO_BORDER| wx.TB_FLAT) 
     self.controller = None 
     self.isSyncScroll = True 

     #hsizer = wx.BoxSizer(wx.VERTICAL) 
     gsizer = wx.FlexGridSizer(rows = 1, 
                cols = 1, 
                vgap = 2, 
                hgap = 2) 
     gsizer.AddGrowableRow(0) 
     gsizer.AddGrowableCol(0) 
     self.tb = self.init_toolbar() 
     (sub_panel0, sub_panel1) = self.init_splitter(main_panel) 
     self.grid0 = self.init_grid(sub_panel0) 
     self.grid1 = self.init_grid(sub_panel1) 
     self.init_status_bar() 

     gsizer.Add(main_panel, 1, wx.EXPAND) 
     self.SetSizer(gsizer) 

     ico = wx.Icon(u'Compare.ico', wx.BITMAP_TYPE_ICO) 
     self.SetIcon(ico) 
     self.Maximize() 

     #can't catch the scroll event at the frame 
     self.Bind(wx.EVT_SCROLL, self.OnScroll, self.grid0) 
     #self.Bind(wx.EVT_SCROLL, self.OnScroll) 
     #self.Bind(wx.EVT_SCROLL, self.OnScroll, id=self.grid0.GetId()) 
+0

为什么不把所有的数据并排放在同一个网格中? – Arthur 2013-04-08 09:16:53

+0

客户是什么......所以,它必须。数据列将会像winmerge一样比较,并添加虚拟列来匹配相等的列。 – Erxin 2013-04-09 01:13:05

+0

除了同步滚动两个网格的滚动条以外,还实现了所有其他功能。这似乎是一个常见问题,已经有人[问](http://stackoverflow.com/questions/11269558/wxgrid-detecting-scroll-event)如何检测滚动事件。我只能找出如何绑定网格窗口中的鼠标滚轮事件。 – Erxin 2013-04-09 01:17:54

回答

4

以下代码的init方法得到2个滚动条时抓住一个或另一个一起移动。

Python版本2.7.3 & wxpython 2.9.4.0 & windows Xp。

import wx 
import wx.grid as grid 


class Frame(wx.Frame): 
    def __init__(self, parent): 
     wx.Frame.__init__(self, parent, -1, "Grid", size=(350, 250)) 
     self.grid = grid.Grid(self) 
     self.grid.CreateGrid(20, 20) 


class ScrollSync(object): 
    def __init__(self, frame1, frame2): 
     self.frame1 = frame1 
     self.frame2 = frame2 
     self.frame1.grid.Bind(wx.EVT_SCROLLWIN, self.onScrollWin1) 
     self.frame2.grid.Bind(wx.EVT_SCROLLWIN, self.onScrollWin2) 

    def onScrollWin1(self, event): 
     if event.Orientation == wx.SB_HORIZONTAL: 
      self.frame2.grid.Scroll(event.Position, -1) 
     else: 
      self.frame2.grid.Scroll(-1, event.Position) 
     event.Skip() 

    def onScrollWin2(self, event): 
     if event.Orientation == wx.SB_HORIZONTAL: 
      self.frame1.grid.Scroll(event.Position, -1) 
     else: 
      self.frame1.grid.Scroll(-1, event.Position) 
     event.Skip() 

if __name__ == '__main__': 
    app = wx.App() 
    frame1 = Frame(None) 
    frame1.Show() 
    frame2 = Frame(None) 
    frame2.Show() 
    ScrollSync(frame1, frame2) 
    app.MainLoop() 

这是另一个使用计时器检查和设置滚动位置的版本,因此它覆盖了任何类型的滚动更改。

import wx 
import wx.grid as grid 


class Frame(wx.Frame): 
    def __init__(self, parent): 
     wx.Frame.__init__(self, parent, -1, "Grid", size=(350, 250)) 
     self.grid = grid.Grid(self) 
     self.grid.CreateGrid(20, 20) 


class ScrollSync(wx.EvtHandler): 
    def __init__(self, frame1, frame2): 
     super(ScrollSync, self).__init__() 
     self.frame1 = frame1 
     self.frame2 = frame2 
     self.frame1ScrollPos = self.getFrame1Pos() 
     self.frame2ScrollPos = self.getFrame2Pos() 
     self.Bind(wx.EVT_TIMER, self.onTimer) 
     self.timer = wx.Timer(self) 
     self.timer.Start(20) 

    def onTimer(self, event): 
     if not self.frame1 or not self.frame2: 
      self.timer.Stop() 
      return 
     if self.frame1ScrollPos != self.getFrame1Pos(): 
      self.frame1ScrollPos = self.getFrame1Pos() 
      self.frame2.grid.Scroll(self.frame1ScrollPos) 
     elif self.frame2ScrollPos != self.getFrame2Pos(): 
      self.frame2ScrollPos = self.getFrame2Pos() 
      self.frame1.grid.Scroll(self.frame2ScrollPos) 

    def getFrame1Pos(self): 
     horizontal = self.frame1.grid.GetScrollPos(wx.SB_HORIZONTAL) 
     vertical = self.frame1.grid.GetScrollPos(wx.SB_VERTICAL) 
     return horizontal, vertical 

    def getFrame2Pos(self): 
     horizontal = self.frame2.grid.GetScrollPos(wx.SB_HORIZONTAL) 
     vertical = self.frame2.grid.GetScrollPos(wx.SB_VERTICAL) 
     return horizontal, vertical 


if __name__ == '__main__': 
    app = wx.App() 
    frame1 = Frame(None) 
    frame1.Show() 
    frame2 = Frame(None) 
    frame2.Show() 
    ScrollSync(frame1, frame2) 
    app.MainLoop() 
+0

谢谢你的工作,但鼠标滚轮,页面上/下和上/下行事件仍然需要单独处理。 – Erxin 2013-04-10 07:52:18

+0

谢谢你的回答,先生。 – alwbtc 2013-12-15 14:56:10