Perhaps you could use a Grid control with a single column? It appears to handle (on linux at least) large numbers of entries. It also has built in support for Ctrl+C to copy the contents of the selected rows to the clipboard as long as there is either a single selected row or a single selected block of contiguous rows. If there are more than one non-contiguous selected rows or blocks, a warning dialog is displayed.
import wx
import wx.grid
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((1900, 300))
self.SetTitle("Grid Control")
self.panel = wx.Panel(self, wx.ID_ANY)
sizer = wx.BoxSizer(wx.VERTICAL)
self.grid = wx.grid.Grid(self.panel, wx.ID_ANY)
self.grid.CreateGrid(0, 1)
self.grid.SetRowLabelSize(0)
self.grid.SetColLabelSize(30)
self.grid.SetDefaultColSize(1900, True)
self.grid.EnableEditing(0)
self.grid.EnableDragRowSize(0)
self.grid.SetSelectionMode(wx.grid.Grid.SelectRows)
self.grid.SetColLabelValue(0, "Log Messages")
sizer.Add(self.grid, 1, wx.EXPAND, 0)
self.panel.SetSizer(sizer)
self.Layout()
long_text = ("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, "
"sed diam nonumy eirmod tempor invidunt ut labore et dolore "
"magna aliquyam erat, sed diam voluptua. At vero eos et "
"accusam et justo duo dolores et ea rebum. Stet clita kasd "
"gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.")
num_rows = 100000
self.grid.AppendRows(num_rows)
for r in range(num_rows):
self.grid.SetCellValue(r, 0, f"{r} {long_text}")
self.grid.GoToCell(num_rows-1, 0)
self.grid.Refresh()
self.grid.Update()
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()
Below is an attempt at overriding the built in Ctrl+C handler to support non-contiguous rows. It appears to work on linux.
import wx
import wx.grid
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((1900, 300))
self.SetTitle("Grid Control")
self.panel = wx.Panel(self, wx.ID_ANY)
sizer = wx.BoxSizer(wx.VERTICAL)
self.grid = wx.grid.Grid(self.panel, wx.ID_ANY)
self.grid.CreateGrid(0, 1)
self.grid.SetRowLabelSize(0)
self.grid.SetColLabelSize(30)
self.grid.SetDefaultColSize(1900, True)
self.grid.EnableEditing(0)
self.grid.EnableDragRowSize(0)
self.grid.SetSelectionMode(wx.grid.Grid.SelectCells)
self.grid.SetColLabelValue(0, "Log Messages")
sizer.Add(self.grid, 1, wx.EXPAND, 0)
self.panel.SetSizer(sizer)
self.Layout()
long_text = ("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, "
"sed diam nonumy eirmod tempor invidunt ut labore et dolore "
"magna aliquyam erat, sed diam voluptua. At vero eos et "
"accusam et justo duo dolores et ea rebum. Stet clita kasd "
"gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.")
num_rows = 100000
self.grid.AppendRows(num_rows)
for r in range(num_rows):
self.grid.SetCellValue(r, 0, f"{r} {long_text}")
self.grid.GoToCell(num_rows-1, 0)
self.grid.Refresh()
self.grid.Update()
self.grid.Bind(wx.EVT_KEY_DOWN, self.OnChar)
def OnChar(self, event):
keycode = event.GetKeyCode()
if event.GetModifiers() == wx.MOD_CONTROL:
if keycode == ord('C'):
rows = self.grid.GetSelectedRows()
text_list = [self.grid.GetCellValue(row, 0) for row in rows]
text = "\n".join(text_list)
clip_data = wx.TextDataObject()
clip_data.SetText(text)
wx.TheClipboard.Open()
wx.TheClipboard.SetData(clip_data)
wx.TheClipboard.Close()
else:
event.Skip()
else:
event.Skip()
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()