wxgrid Spaltenauswahl dauert bei vielen Zeilen sehr lange

Plattformunabhängige GUIs mit wxWidgets.
Antworten
tommy_3
User
Beiträge: 6
Registriert: Dienstag 29. Juli 2008, 23:10

Hallo Leute,

ich verwende seit kurzem ein wxGrid um meine ASCII-Meßdaten darzustellen und zu editieren. Mein erster Ansatz war, die Messdaten aus einem ASCII-File zu lesen und mittels ‚SetCellValue’ in ein wxGgrid zu schreiben. Ich habe aber bald festgestellt, dass es wesentlich einfacher und schneller geht die Daten in einer wxGridTableBase zu speichern. Allerdings stehe ich jetzt vor dem folgenden Problem. Nachdem ich große Datenmengen (ca. 300 000 Zeilen) in das Grid eingelesen habe dauert die Auswahl einer Spalte (Linksklick bzw. Rechtsklick) sehr lange. Dieses Problem hatte ich zuvor (ohne wxGridTableBase) nicht.

Hat jemand eine Idee woran das liegen kann?
Bzw. weiß jemand welche Events oder Funktionen bei der Auswahl einer Spalte aufgrufen werden und ob diese eine Iteration über alle Zeilen einer Spalten durchführen?

Danke im Voraus für Eure Antworten!

Schöne Grüße,
Thomas
tommy_3
User
Beiträge: 6
Registriert: Dienstag 29. Juli 2008, 23:10

Hallo Leute,

ich kämpfe nach wie vor mit demselben Problem. Da ich gerade den Post gelesen habe indem geraten wird Codebeispiele zu posten, werde ich das nun tun.

Ich habe zwei kleine Applikationen erstellt in denen jeweils ein wxgrid mit 2 Spalten und 300.000 Zeilen erzeugt wird und mit Zufallszahlen gefüllt wird.

Applikation 1:
verwendet den Befehl wxgrid:CreateGrid um das Grid zu erzeugen. Ihr werdet merken, dass die Befüllung des Grids ganz schön lange dauert, da ich für jede Zelle den Befehl SetCellValue verwende (darum bin ich dazu übergegangen mit einer wxGridTableBase zu arbeiten).

Code: Alles auswählen

import wx
import wx.grid
import random

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.grid = wx.grid.Grid(self, -1, size=(400, 300))
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.grid, 1, wx.EXPAND, 0)
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.Layout()
            
        cols = 2
        rows = 300000
        self.grid.CreateGrid(rows, cols)
            
        # fill with random numbers
        for col in range(cols):
            map(lambda x: self.grid.SetCellValue(x, col, str(random.random())), range(rows))


if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame = MyFrame(None, -1, "")
    app.SetTopWindow(frame)
    frame.Show()
    app.MainLoop()


Applikation 2:

Verwendet eine wxGridTableBase. Das befüllen der Daten geht jetzt sehr rasch aber wenn eine Spalte selektiert wird dauert das viel länger als im Beispiel 1. Es macht übrigens keinen Unterschied ob ich die Spalte über einen Mouse-Event auswähle oder im Programm den Befehl SelectCol(col) verwende.

Code: Alles auswählen

import wx
import wx.grid
import random

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.grid = wx.grid.Grid(self, -1, size=(400, 300))
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.grid, 1, wx.EXPAND, 0)
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.Layout()
            
        table = GridTable()
        self.grid.SetTable(table)


class GridTable(wx.grid.PyGridTableBase):
    
    def __init__(self, *args, **kwds):
        self.cols = 2
        self.rows = 300000
        self.data = []
        map(lambda x: self.data.append(2*[random.random()]), range(300000))
        wx.grid.PyGridTableBase.__init__(self)
        
    def GetValue(self, row, col):
        return self.data[row][col]
        
    def GetNumberRows(self):
        return self.rows

    def GetNumberCols(self):
        return self.cols


if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame = MyFrame(None, -1, "")
    app.SetTopWindow(frame)
    frame.Show()
    app.MainLoop()

Weiß jemand welche Funktionen bei der Selektion einer Spalte (z.b. über SelectCol) aufgerufen werden und wie ich diese bei großen Datenmengen beschleunigen kann?

Ich bedanke mich wieder im Voraus! Habe gesehen es haben schon einige meinen Post gelesen, vielleicht kann mir nun jemand weiterhelfen. Falls ich eine Lösung finde werde ich diese natürlich auch posten.

Schöne Grüße,
Tommy
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Schau Dir mal das Grid_MegaExample in der wxPython-Demo an. Vielleicht hilft das ja weiter.
MfG
HWK
tommy_3
User
Beiträge: 6
Registriert: Dienstag 29. Juli 2008, 23:10

Hallo Leute,

das GridMegaExample hat mir etwas weitergeholfen. Die Beispielsammlung finde ich generell toll und kann sie nur weiterempfehlen.

Aber nun zu meinem Problem. Ich konnte die Spaltenauswahl etwas beschleunigen indem ich die Standard-Spalenattribute explizit angegeben habe. Also für mein grid mit zwei Spalten habe ich in der Initialisierung die folgenden Zeilen eingefügt:

Code: Alles auswählen

attr = wx.grid.GridCellAttr()
self.grid.SetColAttr(0, attr)
self.grid.SetColAttr(1, attr)
Es ist aber nach wie vor so, dass eine Zeitverzögerung auftritt, im Gegensatz zu dem oben gezeigten Beispiel 1 welches ohne PyGridTableBase auskommt. Warum das setzten der Spaltenattribute eine Verbesserung bringt kann ich nicht erklären.

Weiters habe ich versucht, die Spalten anders zu rendern (wie im Beispiel GridMegaExample demonstriert), aber ohne Effekt auf die Zeitverzögerung bei der Spaltenauswahl. Selbst ein Dummy_Renderer (Renderer der keine Zellen verändert) brachte keine Beschleunigung.

Ich bin vorerst mit der Geschwindigkeit zufrieden und werde daher nicht mehr allzu viel Zeit aufwenden um dieses Problem komplett zu lösen. Sollte ich ein Lösung finden werde ich sie natürlich posten.

Vielen Dank and alle, die meinen Beitrag gelesen haben und an HWK für seinen tollen Tipp.

Schöne Grüße,
Tommy
Antworten