Ich arbeite an einem Programm mit einer Reihe von Eingabetabellen, für die ich wxPython wx.Grid (in erster Linie für Windows) verwenden. Ich bemerkte, dass Strg-C und Strg-V zum Kopieren und Einfügen von Rotz einfach funktionieren und ich suchte nach Lösungen, um zu verhindern, dass alle Zahlen in den Tabellen von Hand eingegeben werden mussten. Ich fand einen alten Beitrag von Ruben Charles hier: http://comments.gmane.org/gmane.comp.python.wxpython/26387Arbeite mit ctrl-c und ctrl-v zum Kopieren und Einfügen in ein wx.Grid in wxPython
, die mehr oder weniger zu tun scheint, was ich wollte, und so begann ich mit, dass die Arbeit und machte einige, was ich hoffe, sind Verbesserungen. (Ich habe Funktionen hinzugefügt, die mit ctrl-Z 'rückgängig gemacht' werden, um mit einzelnen Zellen zu arbeiten und einzufügen, wenn die letzte Zeile oder Spalte außerhalb der Grid-Tabelle liegt.)
Gibt es bessere Möglichkeiten, dies zu tun? Haben Sie Verbesserungsvorschläge? Insbesondere: Wie funktioniert das mit Python 3.5? siehe unten
import wx
import wx.grid
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title, pos=wx.DefaultPosition, size=wx.Size(800, 400), style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, ID, title, pos, size, style)
agrid = MyGrid(self, -1, wx.WANTS_CHARS)
agrid.CreateGrid(7, 7)
for count in range(3):
for count2 in range(3):
agrid.SetCellValue(count, count2, str(count + count2))
class MyGrid(wx.grid.Grid):
""" A Copy&Paste enabled grid class"""
def __init__(self, parent, id, style):
wx.grid.Grid.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, style)
wx.EVT_KEY_DOWN(self, self.OnKey)
self.data4undo = [0, 0, '']
def OnKey(self, event):
# If Ctrl+C is pressed...
if event.ControlDown() and event.GetKeyCode() == 67:
self.copy()
# If Ctrl+V is pressed...
if event.ControlDown() and event.GetKeyCode() == 86:
self.paste('clip')
# If Ctrl+Z is pressed...
if event.ControlDown() and event.GetKeyCode() == 90:
if self.data4undo[2] != '':
self.paste('undo')
# If del is pressed...
if event.GetKeyCode() == 127:
# Call delete method
self.delete()
# Skip other Key events
if event.GetKeyCode():
event.Skip()
return
def copy(self):
# Number of rows and cols
print self.GetSelectionBlockBottomRight()
print self.GetGridCursorRow()
print self.GetGridCursorCol()
if self.GetSelectionBlockTopLeft() == []:
rows = 1
cols = 1
iscell = True
else:
rows = self.GetSelectionBlockBottomRight()[0][0] - self.GetSelectionBlockTopLeft()[0][0] + 1
cols = self.GetSelectionBlockBottomRight()[0][1] - self.GetSelectionBlockTopLeft()[0][1] + 1
iscell = False
# data variable contain text that must be set in the clipboard
data = ''
# For each cell in selected range append the cell value in the data variable
# Tabs '\t' for cols and '\r' for rows
for r in range(rows):
for c in range(cols):
if iscell:
data += str(self.GetCellValue(self.GetGridCursorRow() + r, self.GetGridCursorCol() + c))
else:
data += str(self.GetCellValue(self.GetSelectionBlockTopLeft()[0][0] + r, self.GetSelectionBlockTopLeft()[0][1] + c))
if c < cols - 1:
data += '\t'
data += '\n'
# Create text data object
clipboard = wx.TextDataObject()
# Set data object value
clipboard.SetText(data)
# Put the data in the clipboard
if wx.TheClipboard.Open():
wx.TheClipboard.SetData(clipboard)
wx.TheClipboard.Close()
else:
wx.MessageBox("Can't open the clipboard", "Error")
def paste(self, stage):
if stage == 'clip':
clipboard = wx.TextDataObject()
if wx.TheClipboard.Open():
wx.TheClipboard.GetData(clipboard)
wx.TheClipboard.Close()
else:
wx.MessageBox("Can't open the clipboard", "Error")
data = clipboard.GetText()
if self.GetSelectionBlockTopLeft() == []:
rowstart = self.GetGridCursorRow()
colstart = self.GetGridCursorCol()
else:
rowstart = self.GetSelectionBlockTopLeft()[0][0]
colstart = self.GetSelectionBlockTopLeft()[0][1]
elif stage == 'undo':
data = self.data4undo[2]
rowstart = self.data4undo[0]
colstart = self.data4undo[1]
else:
wx.MessageBox("Paste method "+stage+" does not exist", "Error")
text4undo = ''
# Convert text in a array of lines
for y, r in enumerate(data.splitlines()):
# Convert c in a array of text separated by tab
for x, c in enumerate(r.split('\t')):
if y + rowstart < self.NumberRows and x + colstart < self.NumberCols :
text4undo += str(self.GetCellValue(rowstart + y, colstart + x)) + '\t'
self.SetCellValue(rowstart + y, colstart + x, c)
text4undo = text4undo[:-1] + '\n'
if stage == 'clip':
self.data4undo = [rowstart, colstart, text4undo]
else:
self.data4undo = [0, 0, '']
def delete(self):
# print "Delete method"
# Number of rows and cols
if self.GetSelectionBlockTopLeft() == []:
rows = 1
cols = 1
else:
rows = self.GetSelectionBlockBottomRight()[0][0] - self.GetSelectionBlockTopLeft()[0][0] + 1
cols = self.GetSelectionBlockBottomRight()[0][1] - self.GetSelectionBlockTopLeft()[0][1] + 1
# Clear cells contents
for r in range(rows):
for c in range(cols):
if self.GetSelectionBlockTopLeft() == []:
self.SetCellValue(self.GetGridCursorRow() + r, self.GetGridCursorCol() + c, '')
else:
self.SetCellValue(self.GetSelectionBlockTopLeft()[0][0] + r, self.GetSelectionBlockTopLeft()[0][1] + c, '')
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, "Copy and paste enabled only for a single range")
frame.Show(True)
self.SetTopWindow(frame)
return True
def main():
app = MyApp()
app.MainLoop()
if __name__ == '__main__':
main()
Perfekt für meine Zwecke. Das einzige, was ich getan habe, war, die Multi-'if-Anweisung in 'OnKey' in ein Dictionary zu ändern, das die anderen Funktionen aufruft und die Paste austeilt und in separaten Fällen unter meiner Paste-Definition rückgängig macht. – Kyrubas
Danke für den Tipp Kyrubas! Ich habe nie daran gedacht, ein Wörterbuch so zu benutzen. – ROB
Danke @ROB! Das ist sehr cool und nützlich. Danke für die Hilfe. – Deathkill14