Skip to content

Commit e5eab11

Browse files
Jovan MitrevskiJovan Mitrevski
authored andcommitted
add an example
1 parent 1cbd70c commit e5eab11

File tree

5 files changed

+201
-4
lines changed

5 files changed

+201
-4
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ In order to use matplotlib plots with QtQuick, do the following:
99
1. In your QML files, instantiate an object with the QML type defined above. Its `objectName` property specifies the name of the object that can be found in the QML engine. It can be retrieved in python with `win.findChild(QtCore.QObject, "spectFigure")`, for example, where `"spectFigure"` is the `objectName` in this case.
1010
1. One can then pass this object as needed. This is the FigureCanvasQtQuickAgg object. The figure can be found in its `figure` property.
1111

12-
The test in the `tests` directory gives a simple example of how to use this backend.
13-
1412
For interactive plots, if you want to use the toolbar, to the `Bridge` class add slots like:
1513

1614
```python
@@ -65,5 +63,8 @@ and provide the callbacks, for example:
6563
self.setSlice()
6664
```
6765

68-
6966
Please let me know if you have any suggestions or better ways I should do this.
67+
68+
## Examples
69+
70+
The example in the `examples` directory gives a simple example of how to use this backend, including interactions.

examples/__init__.py

Whitespace-only changes.

examples/main.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env python
2+
"""
3+
An example of using the backend
4+
"""
5+
import sys
6+
from pathlib import Path
7+
8+
import numpy as np
9+
from matplotlib_backend_qtquick.backend_qtquick import (
10+
NavigationToolbar2QtQuick)
11+
from matplotlib_backend_qtquick.backend_qtquickagg import (
12+
FigureCanvasQtQuickAgg)
13+
from matplotlib_backend_qtquick.qt_compat import QtGui, QtQml, QtCore
14+
15+
16+
class DisplayBridge(QtCore.QObject):
17+
""" A bridge class to interact with the plot in python
18+
"""
19+
coordinatesChanged = QtCore.Signal(str)
20+
21+
def __init__(self, parent=None):
22+
super().__init__(parent)
23+
24+
# The figure and toolbar
25+
self.figure = None
26+
self.toolbar = None
27+
28+
# this is used to display the coordinates of the mouse in the window
29+
self._coordinates = ""
30+
31+
def updateWithCanvas(self, canvas):
32+
""" initialize with the canvas for the figure
33+
"""
34+
self.figure = canvas.figure
35+
self.toolbar = NavigationToolbar2QtQuick(canvas=canvas)
36+
37+
# make a small plot
38+
self.axes = self.figure.add_subplot(111)
39+
self.axes.grid(True)
40+
41+
x = np.linspace(0, 2*np.pi, 100)
42+
y = np.sin(x)
43+
44+
self.axes.plot(x, y)
45+
canvas.draw_idle()
46+
47+
# connect for displaying the coordinates
48+
self.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
49+
50+
# define the coordinates property
51+
# (I have had problems using the @QtCore.Property directy in the past)
52+
def getCoordinates(self):
53+
return self._coordinates
54+
55+
def setCoordinates(self, coordinates):
56+
self._coordinates = coordinates
57+
self.coordinatesChanged.emit(self._coordinates)
58+
59+
coordinates = QtCore.Property(str, getCoordinates, setCoordinates,
60+
notify=coordinatesChanged)
61+
62+
# The toolbar commands
63+
@QtCore.Slot()
64+
def pan(self, *args):
65+
"""Activate the pan tool."""
66+
self.toolbar.pan(*args)
67+
68+
@QtCore.Slot()
69+
def zoom(self, *args):
70+
"""activate zoom tool."""
71+
self.toolbar.zoom(*args)
72+
73+
@QtCore.Slot()
74+
def home(self, *args):
75+
self.toolbar.home(*args)
76+
77+
@QtCore.Slot()
78+
def back(self, *args):
79+
self.toolbar.back(*args)
80+
81+
@QtCore.Slot()
82+
def forward(self, *args):
83+
self.toolbar.forward(*args)
84+
85+
def on_motion(self, event):
86+
"""
87+
Update the coordinates on the display
88+
"""
89+
if event.inaxes == self.axes:
90+
self.coordinates = f"({event.xdata:.2f}, {event.ydata:.2f})"
91+
92+
if __name__ == "__main__":
93+
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
94+
app = QtGui.QGuiApplication(sys.argv)
95+
engine = QtQml.QQmlApplicationEngine()
96+
97+
# instantate the display bridge
98+
displayBridge = DisplayBridge()
99+
100+
# Expose the Python object to QML
101+
context = engine.rootContext()
102+
context.setContextProperty("displayBridge", displayBridge)
103+
104+
# matplotlib stuff
105+
QtQml.qmlRegisterType(FigureCanvasQtQuickAgg, "Backend", 1, 0, "FigureCanvas")
106+
107+
# Load the QML file
108+
qmlFile = Path(Path.cwd(), Path(__file__).parent, "main.qml")
109+
engine.load(QtCore.QUrl.fromLocalFile(str(qmlFile)))
110+
111+
win = engine.rootObjects()[0]
112+
displayBridge.updateWithCanvas(win.findChild(QtCore.QObject, "figure"))
113+
114+
# execute and cleanup
115+
app.exec_()

examples/main.qml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import QtQuick 2.12
2+
import QtQuick.Controls 2.12
3+
import QtQuick.Window 2.12
4+
import QtQuick.Layouts 1.12
5+
6+
import Backend 1.0
7+
8+
ApplicationWindow {
9+
id: mainWindow
10+
visible: true
11+
width: 800
12+
height: 600
13+
title: qsTr("QtQuick backend test")
14+
15+
16+
FigureCanvas {
17+
id: mplView
18+
objectName : "figure"
19+
dpi_ratio: Screen.devicePixelRatio
20+
anchors.fill: parent
21+
}
22+
23+
footer: ToolBar {
24+
RowLayout {
25+
ToolButton {
26+
text: qsTr("home")
27+
onClicked: {
28+
displayBridge.home();
29+
}
30+
}
31+
32+
Button {
33+
text: qsTr("back")
34+
onClicked: {
35+
displayBridge.back();
36+
}
37+
}
38+
39+
Button {
40+
text: qsTr("forward")
41+
onClicked: {
42+
displayBridge.forward();
43+
}
44+
}
45+
46+
ToolSeparator{}
47+
48+
Button {
49+
id: pan
50+
text: qsTr("pan")
51+
checkable: true
52+
onClicked: {
53+
if (zoom.checked) {
54+
zoom.checked = false;
55+
}
56+
displayBridge.pan();
57+
}
58+
}
59+
60+
Button {
61+
id: zoom
62+
text: qsTr("zoom")
63+
checkable: true
64+
onClicked: {
65+
if (pan.checked) {
66+
// toggle pan off
67+
pan.checked = false;
68+
}
69+
displayBridge.zoom();
70+
}
71+
}
72+
ToolSeparator {}
73+
TextInput {
74+
id: location
75+
readOnly: true
76+
text: displayBridge.coordinates
77+
}
78+
}
79+
}
80+
81+
}

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="matplotlib_backend_qtquick",
8-
version="0.0.6",
8+
version="0.0.7",
99
author="Jovan Mitrevski",
1010
author_email="j.p.mitrevski@gmail.com",
1111
description="A QtQuick backend for matplotlib",

0 commit comments

Comments
 (0)