Seite 1 von 1
Langsamer FlexGridSizer
Verfasst: Dienstag 19. September 2006, 12:51
von HWK
In einem Script verwenden ich einen FlexGridSizer zur Darstellung von Daten in Tabellenform. Bei wenigen Daten klappt die Darstellung recht zügig. Sobald die Datenmenge aber anwächst, wird insbesondere das Löschen des Fensters extrem langsam. Da die Datenmenge in meinem Script aber kontinuierlich anwächst, suche ich nach einer schnelleren Möglichkeit. Zum Testen habe ich ein kurzes Script, das das Wesentliche enthält, geschrieben:
Code: Alles auswählen
from random import randrange
import wx
import wx.lib.scrolledpanel as scrolled
class SlowGrid(scrolled.ScrolledPanel):
def __init__(self, parent, row=10, col=10):
scrolled.ScrolledPanel.__init__(self, parent, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
grid = wx.FlexGridSizer(cols=col, vgap=4, hgap=4)
for i in range(row):
for j in range(col):
label = wx.StaticText(self, -1, str(randrange(100000000)))
grid.Add(label, flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
sizer.Add(grid, 0, wx.ALIGN_LEFT | wx.ALL, 5)
self.SetSizer(sizer)
self.SetAutoLayout(1)
self.SetupScrolling(rate_x=1, rate_y=1)
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, 'SlowGrid', size=(500, 500))
SlowGrid(frame, 20, 100) # <- Hier andere Groessen eingeben
frame.Show()
app.MainLoop()
MfG
HWK
Verfasst: Dienstag 19. September 2006, 13:31
von rayo
Hi
Zum Anzeigen von tabellarischen Daten ist doch das ListCtrl bestens geeignet.
In der Demo von wxPython hat es 3 Einträge unter "Core Windows/Controls" mit ListCtrl.
Da sollte eigentlich alles enthalten sein was du so brauchst.
Gruss
Verfasst: Dienstag 19. September 2006, 21:12
von HWK
Danke für den Vorschlag!
Ich weiß zwar nicht warum, aber es scheint wirklich schneller zu sein. Das zeigt zumindest ein Test von ca. 100 Spalten.
ListCtrl erfüllt aber nicht ganz meine Wünsche. Ich kann z.B. nur die Farbe einer ganzen Zeile ändern und nicht eines einzelnen Eintrags.
Andererseits besitzt es Funktionalität, die überflüssig ist oder sogar stört, z.B. eine Zeile auszuwählen.
Gibt es evtl. Alternativen?
MfG
HWK
Verfasst: Dienstag 19. September 2006, 21:49
von DatenMetzgerX
wx.grid.Grid
Verfasst: Mittwoch 20. September 2006, 12:18
von HWK
Wx.grid.Grid liefert ja noch mehr Funktionalität, die ich nicht brauche. Ich will lediglich möglichst einfach und schnell Daten in Tabellenform darstellen.
Gerold schrieb in einem anderen Thread (
http://www.python-forum.de/topic-6468.h ... 553399a0eb), daß er zur Darstellung einer Tabelle das HtmlWindow benutzt. Ich kenne mich in Html aber nur wenig aus. Auf den ersten Blick wirkt mir das sehr kompliziert. Auch frage ich mich, ob dabei eine automatische Anpassung der Spaltenbreite möglich ist.
Also
Gerold, falls Du dies liest, könntest du einmal ein Beipiel zeigen, wie man am geschicktesten eine Html-Tabelle mit Python erstellt?
MfG
HWK
Verfasst: Mittwoch 20. September 2006, 12:29
von DatenMetzgerX
ja das grid kann mehr, wurde allerdings auch für grosse Datenmengen ausgelegt. Und findest du ein TextCtrl besser? da hast du viel mehr aufwand... Du kannst auch ein virtuelles Grid machen, dann bist du allerdings für das data handling zuständig. Allerdings hättest du sicherlich die gewünschte performance...
Verfasst: Mittwoch 20. September 2006, 14:46
von HWK
Das geht ja rasant schnell. Das Aussehen ist natürlich jetzt etwas anders. Das Störendste für mich ist aber, daß der Benutzer die Möglichkeit hat, eine Auswahl zu treffen und mit den Cursortasten zu arbeiten. Kann man das irgendwie "disablen"?
Vielen Dank schon mal
HWK
Verfasst: Mittwoch 20. September 2006, 16:49
von DatenMetzgerX
du bindest diesen Event an das grid (Example aus meinem Programm)
Danach machst du eine Methode OnEdit
Verfasst: Mittwoch 20. September 2006, 19:16
von HWK
So funktioniert es nicht. Das Editieren verhindere ich bereits mit
Das Benutzen der Cursortasten und das Selektieren mit der Maus verhindert es nicht. Das erste kann man durch Veto für das Event EVT_GRID_SELECT_CELL verhindern:
Code: Alles auswählen
self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnSelectCell)
def OnSelectCell(self, evt):
evt.Veto()
Für das zweite habe ich noch keine Lösung gefunden. Man kann zwar die Auswahl mit
Code: Alles auswählen
self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self.OnRangeSelect)
def OnRangeSelect(self, evt):
self.ClearSelection()
wieder löschen, das Auswählen ist aber weiterhin möglich. Auch der Rahmen um die aktuelle Zelle bleibt bestehen.
MfG
HWK
Verfasst: Mittwoch 20. September 2006, 19:20
von DatenMetzgerX
So kann er zumindest nur ganze Reihen auswählen
Verfasst: Mittwoch 20. September 2006, 21:27
von HWK
Ich glaube, das ist nicht wirklich eine Verbesserung.
Danke trotzdem
HWK
Verfasst: Samstag 23. September 2006, 12:42
von HWK
Mit wx.Grid bin ich noch nicht so ganz glücklich. Es funktioniert zwar (auch sehr schnell), es gibt dem Anwender aber unnötige Möglichkeiten (Cursor bewegen, Auswählen), obwohl ich nur eine Tabelle anzeigen möchten. Wenn der Benutzer eine Auswahl macht, sieht das schon etwas komisch aus. Ich möchte deshalb nochmal auf Gerolds Hinweis im Thread
http://www.python-forum.de/topic-6468.h ... 553399a0eb zurückkommen. Wäre eine Umwandlung in eine HTML-Tabelle und deren Anzeige mit
HtmlWindow eine Alternative? Ist diese schneller im Grafikaufbau als FlexGridSizer? Wie wandelt man die Daten am einfachsten mit Python in HTML um? Ich besitze keine größeren Erfahrungen mit HTML, habe lediglich etwas in SELFHTML gestöbert und winzige HTML-Dateien geschrieben. Kennt sich jemand damit aus und kann mir ein paar Tips geben oder am besten ein Beispiel zeigen?
Danke im voraus
HWK
Verfasst: Samstag 23. September 2006, 14:05
von gerold
HWK hat geschrieben:HtmlWindow
Hi HWK!
Hier ein Beispiel:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import wx
import wx.html
from simpletal import simpleTAL, simpleTALES
from StringIO import StringIO
class MyFrame(wx.Frame):
def __init__(self, parent = None, id = -1, title = "Einfache HTML-Tabelle"):
wx.Frame.__init__(self, parent, id, title)
html_window = wx.html.HtmlWindow(self, -1)
daten = (
{"vorname": u"ööö ööö", "nachname": u"äää äää"},
{"vorname": u"aaa aaa", "nachname": u"fff"},
{"vorname": u"bbb", "nachname": u"ggg ggg"},
{"vorname": u"ccc ccc", "nachname": u"hhh"},
{"vorname": u"ddd", "nachname": u"iii iii"},
{"vorname": u"eee eee", "nachname": u"jjj"},
)
template_string = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFF2">
<table border="0" cellspacing="3" cellpadding="2">
<tr>
<th bgcolor="#D8D8D8"><strong>Vorname</strong></th>
<th bgcolor="#D8D8D8"><strong>Nachname</strong></th>
</tr>
<tr tal:repeat="datensatz daten">
<td bgcolor="#E9E9E9" tal:content="datensatz/vorname">
[Vorname]
</td>
<td bgcolor="#E9E9E9" tal:content="datensatz/nachname">
[Nachname]
</td>
</tr>
</table>
</body>
</html>
"""
context = simpleTALES.Context(allowPythonPath = True)
context.addGlobal("daten", daten)
template = simpleTAL.compileHTMLTemplate(template_string, "iso-8859-1")
html_output = StringIO()
template.expand(context, html_output, "iso-8859-1")
html_window.SetPage(html_output.getvalue())
self.Center()
self.Show()
def main():
app = wx.PySimpleApp()
f = MyFrame()
app.MainLoop()
if __name__ == "__main__":
main()
lg
Gerold

Verfasst: Samstag 23. September 2006, 14:37
von HWK
Danke für die prompte Antwort, Gerold!
Ich werde es mal ausprobieren.
MfG
HWK
Verfasst: Sonntag 24. September 2006, 14:07
von HWK
So, ich hab's ausprobiert. Dies ist mein Beispielscript:
Code: Alles auswählen
from random import randrange
import wx
import wx.html
class HTMLGrid:
def __init__(self, parent, row=10, col=10):
text = '''
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=iso-8859-1'>
</head>
<body>
<table border='0' cellspacing='0' cellpadding='2'>
'''
text += ' <tr>\n <th></th>\n'
for i in range(col):
text += ' <th nowrap><strong>Spalte %i</strong></th>\n' % i
text += ' </tr>\n'
for i in range(row):
text += (' <tr>\n'
' <th align="LEFT" nowrap><strong>Reihe %i'
'</strong></th>\n' % i)
for j in range(col - 1):
text += (' <td align="RIGHT" nowrap>%i</td>\n' %
randrange(100000000))
text += (' <td align="RIGHT" nowrap><font color="#FF0000">%i'
'</font></td>\n </tr>\n' %randrange(100000000))
text += ' </table>\n </body>\n</html>\n'
#print text
html_window = wx.html.HtmlWindow(parent, -1)
html_window.SetPage(text)
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, 'HTMLGrid', size=(500, 500))
HTMLGrid(frame, 20, 100) # <- Hier andere Groessen eingeben
frame.Show()
app.MainLoop()
Ich habe auf simpletal, was ich im übrigen gar nicht kannte, verzichtet, um beim Datenformat nicht auf die etwas seltsame Form einer Liste von Dictionaries fixiert zu sein. Die Ausgabe ist schnell und qualitativ vergleichbar zu den anderen Varianten. Wie beim wx.grid.Grid kann der Anwender aber wieder eine Auswahl treffen. Anders als beim FlexGridSizer und wx.grid.Grid kann ich auch nicht automatisch ans Tabellenende scrollen. Da die Erstellung des HTML-Codes für einen HTML-Laien etwas verwirrend wirkt, werde ich wohl doch wx.grid.Grid verwenden. Ein Beispiel hierzu habe ich in einem anderen Thread gezeigt (
http://www.python-forum.de/viewtopic.php?p=45638#45638).
MfG
HWK
Verfasst: Sonntag 24. September 2006, 16:04
von gerold
HWK hat geschrieben:Wie beim wx.grid.Grid kann der Anwender aber wieder eine Auswahl treffen. Anders als beim FlexGridSizer und wx.grid.Grid kann ich auch nicht automatisch ans Tabellenende scrollen.
Hi HWK!
Ich formuliere mal die Fragen dazu:

1.) Gibt es eine Einstellung, die beim ``wx.grid.Grid()`` den Benutzer daran hindert, den angezeigten Text mit der Maus zu markieren?
2.) Wie scrollt man beim ``wx.grid.Grid()`` an eine bestimmte Position?
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import wx
import wx.html
from simpletal import simpleTAL, simpleTALES
from StringIO import StringIO
class MyFrame(wx.Frame):
def __init__(self, parent = None, id = -1, title = "Einfache HTML-Tabelle"):
wx.Frame.__init__(self, parent, id, title)
html_window = wx.html.HtmlWindow(self, -1, style = wx.html.HW_NO_SELECTION)
daten = [[ str(i) for i in range(888888, 888900) ]] * 20
template_string = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFF2">
<table border="0" cellspacing="3" cellpadding="2">
<tr tal:repeat="zeile daten">
<td bgcolor="#E9E9E9" nowrap
tal:repeat="zelle zeile"
tal:content="zelle"
>
[Wert]
</td>
</tr>
</table>
</body>
</html>
"""
context = simpleTALES.Context(allowPythonPath = True)
context.addGlobal("daten", daten)
template = simpleTAL.compileHTMLTemplate(template_string, "iso-8859-1")
html_output = StringIO()
template.expand(context, html_output, "iso-8859-1")
html_window.SetPage(html_output.getvalue())
self.Center()
self.Show()
html_window.Scroll(*html_window.GetVirtualSizeTuple())
def main():
app = wx.PySimpleApp()
f = MyFrame()
app.MainLoop()
if __name__ == "__main__":
main()
Man achte auf Zeile 15 und Zeile 52.
lg
Gerold

Verfasst: Sonntag 24. September 2006, 19:13
von HWK
Wirklich beeindruckend!
Wenn man sich damit auskennt, kann man ja allerhand mit HTML und Co. machen. Ich glaube, ich könnte mich auch mit dieser Form der Tabellendarstellung gut anfreunden.
Danke, Gerold!
HWK