📄 sheet.py
字号:
self.RegisterDataType(wx.grid.GRID_VALUE_STRING,
wx.grid.GridCellStringRenderer(),
CCellEditor(self))
self.CreateGrid(4, 3) # By default start with a 4 x 3 grid
self.SetColLabelSize(18) # Default sizes and alignment
self.SetRowLabelSize(50)
self.SetRowLabelAlignment(wx.ALIGN_RIGHT, wx.ALIGN_BOTTOM)
self.SetColSize(0, 75) # Default column sizes
self.SetColSize(1, 75)
self.SetColSize(2, 75)
# Sink events
self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnLeftClick)
self.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.OnRightClick)
self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.OnLeftDoubleClick)
self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self.OnRangeSelect)
self.Bind(wx.grid.EVT_GRID_ROW_SIZE, self.OnRowSize)
self.Bind(wx.grid.EVT_GRID_COL_SIZE, self.OnColSize)
self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnCellChange)
self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnGridSelectCell)
def OnGridSelectCell(self, event):
""" Track cell selections """
# Save the last cell coordinates
self._lastRow, self._lastCol = event.GetRow(), event.GetCol()
event.Skip()
def OnRowSize(self, event):
event.Skip()
def OnColSize(self, event):
event.Skip()
def OnCellChange(self, event):
event.Skip()
def OnLeftClick(self, event):
""" Override left-click behavior to prevent left-click edit initiation """
# Save the cell clicked
currCell = (event.GetRow(), event.GetCol())
# Suppress event if same cell clicked twice in a row.
# This prevents a single-click from initiating an edit.
if currCell != (self._lastRow, self._lastCol): event.Skip()
def OnRightClick(self, event):
""" Move grid cursor when a cell is right-clicked """
self.SetGridCursor( event.GetRow(), event.GetCol() )
event.Skip()
def OnLeftDoubleClick(self, event):
""" Initiate the cell editor on a double-click """
# Move grid cursor to double-clicked cell
if self.CanEnableCellControl():
self.SetGridCursor( event.GetRow(), event.GetCol() )
self.EnableCellEditControl(True) # Show the cell editor
event.Skip()
def OnRangeSelect(self, event):
""" Track which cells are selected so that copy/paste behavior can be implemented """
# If a single cell is selected, then Selecting() returns False (0)
# and range coords are entire grid. In this case cancel previous selection.
# If more than one cell is selected, then Selecting() is True (1)
# and range accurately reflects selected cells. Save them.
# If more cells are added to a selection, selecting remains True (1)
self._selected = None
if event.Selecting():
self._selected = ((event.GetTopRow(), event.GetLeftCol()),
(event.GetBottomRow(), event.GetRightCol()))
event.Skip()
def Copy(self):
""" Copy the currently selected cells to the clipboard """
# TODO: raise an error when there are no cells selected?
if self._selected == None: return
((r1, c1), (r2, c2)) = self._selected
# Build a string to put on the clipboard
# (Is there a faster way to do this in Python?)
crlf = chr(13) + chr(10)
tab = chr(9)
s = ""
for row in range(r1, r2+1):
for col in range(c1, c2):
s += self.GetCellValue(row,col)
s += tab
s += self.GetCellValue(row, c2)
s += crlf
# Put the string on the clipboard
if wx.TheClipboard.Open():
wx.TheClipboard.Clear()
wx.TheClipboard.SetData(wx.TextDataObject(s))
wx.TheClipboard.Close()
def Paste(self):
""" Paste the contents of the clipboard into the currently selected cells """
# (Is there a better way to do this?)
if wx.TheClipboard.Open():
td = wx.TextDataObject()
success = wx.TheClipboard.GetData(td)
wx.TheClipboard.Close()
if not success: return # Exit on failure
s = td.GetText() # Get the text
crlf = chr(13) + chr(10) # CrLf characters
tab = chr(9) # Tab character
rows = s.split(crlf) # split into rows
rows = rows[0:-1] # leave out last element, which is always empty
for i in range(0, len(rows)): # split rows into elements
rows[i] = rows[i].split(tab)
# Get the starting and ending cell range to paste into
if self._selected == None: # If no cells selected...
r1 = self.GetGridCursorRow() # Start the paste at the current location
c1 = self.GetGridCursorCol()
r2 = self.GetNumberRows()-1 # Go to maximum row and col extents
c2 = self.GetNumberCols()-1
else: # If cells selected, only paste there
((r1, c1), (r2, c2)) = self._selected
# Enter data into spreadsheet cells one at a time
r = r1 # Init row and column counters
c = c1
for row in rows: # Loop over all rows
for element in row: # Loop over all row elements
self.SetCellValue(r, c, str(element)) # Set cell value
c += 1 # Increment the column counter
if c > c2: break # Do not exceed maximum column
r += 1
if r > r2: break # Do not exceed maximum row
c = c1
def Clear(self):
""" Clear the currently selected cells """
if self._selected == None: # If no selection...
r = self.GetGridCursorRow() # clear only current cell
c = self.GetGridCursorCol()
self.SetCellValue(r, c, "")
else: # Otherwise clear selected cells
((r1, c1), (r2, c2)) = self._selected
for r in range(r1, r2+1):
for c in range(c1, c2+1):
self.SetCellValue(r, c, "")
def SetNumberRows(self, numRows=1):
""" Set the number of rows in the sheet """
# Check for non-negative number
if numRows < 0: return False
# Adjust number of rows
curRows = self.GetNumberRows()
if curRows < numRows:
self.AppendRows(numRows - curRows)
elif curRows > numRows:
self.DeleteRows(numRows, curRows - numRows)
return True
def SetNumberCols(self, numCols=1):
""" Set the number of columns in the sheet """
# Check for non-negative number
if numCols < 0: return False
# Adjust number of rows
curCols = self.GetNumberCols()
if curCols < numCols:
self.AppendCols(numCols - curCols)
elif curCols > numCols:
self.DeleteCols(numCols, curCols - numCols)
return True
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -