implement table row click callbacks for individual cells
update docs
This commit is contained in:
27
docs/source/examples/screenshot.md
Normal file
27
docs/source/examples/screenshot.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Screenshot & Save
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
from lightweight_charts import Chart
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
chart = Chart()
|
||||||
|
df = pd.read_csv('ohlcv.csv')
|
||||||
|
chart.set(df)
|
||||||
|
chart.show()
|
||||||
|
|
||||||
|
img = chart.screenshot()
|
||||||
|
with open('screenshot.png', 'wb') as f:
|
||||||
|
f.write(img)
|
||||||
|
```
|
||||||
|
|
||||||
|
```{important}
|
||||||
|
The `screenshot` command can only be executed after the chart window is open. Therefore, either `block` must equal `False`, the screenshot should be triggered with a callback, or `async_show` should be used.
|
||||||
|
```
|
||||||
|
|
||||||
|
```{important}
|
||||||
|
This example can only be used with the standard `Chart` object.
|
||||||
|
```
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ examples/toolbox
|
|||||||
examples/subchart
|
examples/subchart
|
||||||
examples/yfinance
|
examples/yfinance
|
||||||
examples/events
|
examples/events
|
||||||
|
examples/screenshot
|
||||||
examples/gui_examples
|
examples/gui_examples
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -364,6 +364,10 @@ Charts are arranged horizontally from left to right. When the available space is
|
|||||||
|
|
||||||
[Subchart examples](../examples/subchart.md)
|
[Subchart examples](../examples/subchart.md)
|
||||||
|
|
||||||
|
```{important}
|
||||||
|
Price axis scales vary depending on the precision of the data used, and there is no way to perfectly 'align' two seperate price scales if they contain differing price data.
|
||||||
|
```
|
||||||
|
|
||||||
````
|
````
|
||||||
`````
|
`````
|
||||||
|
|
||||||
|
|||||||
@ -85,15 +85,17 @@ class Window:
|
|||||||
return
|
return
|
||||||
self.scripts.append(script) if not run_last else self.final_scripts.append(script)
|
self.scripts.append(script) if not run_last else self.final_scripts.append(script)
|
||||||
|
|
||||||
def create_table(self, width: NUM, height: NUM, headings: tuple, widths: tuple = None,
|
def create_table(
|
||||||
alignments: tuple = None, position: FLOAT = 'left', draggable: bool = False,
|
self, width: NUM, height: NUM, headings: tuple, widths: tuple = None,
|
||||||
background_color: str = '#121417', border_color: str = 'rgb(70, 70, 70)',
|
alignments: tuple = None, position: FLOAT = 'left', draggable: bool = False,
|
||||||
border_width: int = 1, heading_text_colors: tuple = None,
|
background_color: str = '#121417', border_color: str = 'rgb(70, 70, 70)',
|
||||||
heading_background_colors: tuple = None, func: callable = None
|
border_width: int = 1, heading_text_colors: tuple = None,
|
||||||
) -> 'Table':
|
heading_background_colors: tuple = None, return_clicked_cells: bool = False,
|
||||||
|
func: callable = None
|
||||||
|
) -> 'Table':
|
||||||
return Table(self, width, height, headings, widths, alignments, position, draggable,
|
return Table(self, width, height, headings, widths, alignments, position, draggable,
|
||||||
background_color, border_color, border_width, heading_text_colors,
|
background_color, border_color, border_width, heading_text_colors,
|
||||||
heading_background_colors, func)
|
heading_background_colors, return_clicked_cells, func)
|
||||||
|
|
||||||
def create_subchart(self, position: FLOAT = 'left', width: float = 0.5, height: float = 0.5,
|
def create_subchart(self, position: FLOAT = 'left', width: float = 0.5, height: float = 0.5,
|
||||||
sync_id: str = None, scale_candles_only: bool = False, toolbox: bool = False
|
sync_id: str = None, scale_candles_only: bool = False, toolbox: bool = False
|
||||||
@ -916,14 +918,16 @@ class AbstractChart(Candlestick, Pane):
|
|||||||
self.win.handlers[f'{modifier_key, keys}'] = func
|
self.win.handlers[f'{modifier_key, keys}'] = func
|
||||||
|
|
||||||
def create_table(
|
def create_table(
|
||||||
self, width: NUM, height: NUM, headings: tuple, widths: tuple = None, alignments: tuple = None,
|
self, width: NUM, height: NUM, headings: tuple, widths: tuple = None,
|
||||||
position: FLOAT = 'left', draggable: bool = False, background_color: str = '#121417',
|
alignments: tuple = None, position: FLOAT = 'left', draggable: bool = False,
|
||||||
border_color: str = 'rgb(70, 70, 70)', border_width: int = 1, heading_text_colors: tuple = None,
|
background_color: str = '#121417', border_color: str = 'rgb(70, 70, 70)',
|
||||||
heading_background_colors: tuple = None, func: callable = None
|
border_width: int = 1, heading_text_colors: tuple = None,
|
||||||
) -> Table:
|
heading_background_colors: tuple = None, return_clicked_cells: bool = False,
|
||||||
|
func: callable = None
|
||||||
|
) -> Table:
|
||||||
return self.win.create_table(width, height, headings, widths, alignments, position, draggable,
|
return self.win.create_table(width, height, headings, widths, alignments, position, draggable,
|
||||||
background_color, border_color, border_width, heading_text_colors,
|
background_color, border_color, border_width, heading_text_colors,
|
||||||
heading_background_colors, func)
|
heading_background_colors, return_clicked_cells, func)
|
||||||
|
|
||||||
def screenshot(self) -> bytes:
|
def screenshot(self) -> bytes:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -91,23 +91,35 @@ if (!window.Table) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newRow(id) {
|
addRowEventListener(row, id, isCell= false) {
|
||||||
let row = this.table.insertRow()
|
if (isCell) {
|
||||||
row.style.cursor = 'default'
|
id = `${id};;;${isCell}`
|
||||||
|
|
||||||
for (let i = 0; i < this.headings.length; i++) {
|
|
||||||
row[this.headings[i]] = row.insertCell()
|
|
||||||
row[this.headings[i]].style.width = this.widths[i];
|
|
||||||
row[this.headings[i]].style.textAlign = this.alignments[i];
|
|
||||||
row[this.headings[i]].style.border = this.borderWidth+'px solid '+this.borderColor
|
|
||||||
}
|
}
|
||||||
row.addEventListener('mouseover', () => row.style.backgroundColor = 'rgba(60, 60, 60, 0.6)')
|
row.addEventListener('mouseover', () => row.style.backgroundColor = 'rgba(60, 60, 60, 0.6)')
|
||||||
row.addEventListener('mouseout', () => row.style.backgroundColor = 'transparent')
|
row.addEventListener('mouseout', () => row.style.backgroundColor = 'transparent')
|
||||||
row.addEventListener('mousedown', () => row.style.backgroundColor = 'rgba(60, 60, 60)')
|
row.addEventListener('mousedown', () => row.style.backgroundColor = 'rgba(60, 60, 60)')
|
||||||
|
|
||||||
row.addEventListener('click', () => window.callbackFunction(`${this.callbackName}_~_${id}`))
|
row.addEventListener('click', () => window.callbackFunction(`${this.callbackName}_~_${id}`))
|
||||||
row.addEventListener('mouseup', () => row.style.backgroundColor = 'rgba(60, 60, 60, 0.6)')
|
row.addEventListener('mouseup', () => row.style.backgroundColor = 'rgba(60, 60, 60, 0.6)')
|
||||||
|
}
|
||||||
|
|
||||||
|
newRow(id, returnClickedCell=false) {
|
||||||
|
let row = this.table.insertRow()
|
||||||
|
row.style.cursor = 'default'
|
||||||
|
|
||||||
|
for (let i = 0; i < this.headings.length; i++) {
|
||||||
|
let cell = row.insertCell()
|
||||||
|
cell.style.width = this.widths[i];
|
||||||
|
cell.style.textAlign = this.alignments[i];
|
||||||
|
cell.style.border = this.borderWidth+'px solid '+this.borderColor
|
||||||
|
|
||||||
|
if (returnClickedCell) {
|
||||||
|
this.addRowEventListener(cell, id, this.headings[i])
|
||||||
|
}
|
||||||
|
row[this.headings[i]] = cell
|
||||||
|
}
|
||||||
|
if (!returnClickedCell) {
|
||||||
|
this.addRowEventListener(row, id, false)
|
||||||
|
}
|
||||||
this.rows[id] = row
|
this.rows[id] = row
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class Row(dict):
|
|||||||
self._table = table
|
self._table = table
|
||||||
self.id = id
|
self.id = id
|
||||||
self.meta = {}
|
self.meta = {}
|
||||||
self.run_script(f'{self._table.id}.newRow("{self.id}")')
|
self.run_script(f'{self._table.id}.newRow("{self.id}", {jbool(table.return_clicked_cells)})')
|
||||||
for key, val in items.items():
|
for key, val in items.items():
|
||||||
self[key] = val
|
self[key] = val
|
||||||
|
|
||||||
@ -56,14 +56,20 @@ class Table(Pane, dict):
|
|||||||
alignments: tuple = None, position='left', draggable: bool = False,
|
alignments: tuple = None, position='left', draggable: bool = False,
|
||||||
background_color: str = '#121417', border_color: str = 'rgb(70, 70, 70)',
|
background_color: str = '#121417', border_color: str = 'rgb(70, 70, 70)',
|
||||||
border_width: int = 1, heading_text_colors: tuple = None,
|
border_width: int = 1, heading_text_colors: tuple = None,
|
||||||
heading_background_colors: tuple = None, func: callable = None
|
heading_background_colors: tuple = None, return_clicked_cells: bool = False,
|
||||||
|
func: callable = None
|
||||||
):
|
):
|
||||||
dict.__init__(self)
|
dict.__init__(self)
|
||||||
Pane.__init__(self, window)
|
Pane.__init__(self, window)
|
||||||
self._formatters = {}
|
self._formatters = {}
|
||||||
self.headings = headings
|
self.headings = headings
|
||||||
self.is_shown = True
|
self.is_shown = True
|
||||||
self.win.handlers[self.id] = lambda rId: func(self[rId])
|
if return_clicked_cells:
|
||||||
|
self.win.handlers[self.id] = lambda rId, cId: func(self[rId], cId)
|
||||||
|
else:
|
||||||
|
self.win.handlers[self.id] = lambda rId: func(self[rId])
|
||||||
|
self.return_clicked_cells = return_clicked_cells
|
||||||
|
|
||||||
headings = list(headings)
|
headings = list(headings)
|
||||||
widths = list(widths) if widths else []
|
widths = list(widths) if widths else []
|
||||||
alignments = list(alignments) if alignments else []
|
alignments = list(alignments) if alignments else []
|
||||||
|
|||||||
Reference in New Issue
Block a user