Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a46949c

Browse files
committed
Add GTK4 to docs.
Since these examples don't need to support the very oldest GTK3, I took the opportunity to rewrite them using the recommended Application-styled model.
1 parent 11d96d6 commit a46949c

14 files changed

+282
-16
lines changed

.flake8

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,12 @@ per-file-ignores =
123123
examples/ticks_and_spines/date_concise_formatter.py: E402
124124
examples/user_interfaces/embedding_in_gtk3_panzoom_sgskip.py: E402
125125
examples/user_interfaces/embedding_in_gtk3_sgskip.py: E402
126-
examples/user_interfaces/gtk_spreadsheet_sgskip.py: E402
126+
examples/user_interfaces/embedding_in_gtk4_panzoom_sgskip.py: E402
127+
examples/user_interfaces/embedding_in_gtk4_sgskip.py: E402
128+
examples/user_interfaces/gtk3_spreadsheet_sgskip.py: E402
129+
examples/user_interfaces/gtk4_spreadsheet_sgskip.py: E402
127130
examples/user_interfaces/mpl_with_glade3_sgskip.py: E402
128-
examples/user_interfaces/pylab_with_gtk_sgskip.py: E402
131+
examples/user_interfaces/pylab_with_gtk3_sgskip.py: E402
132+
examples/user_interfaces/pylab_with_gtk4_sgskip.py: E402
129133
examples/user_interfaces/toolmanager_sgskip.py: E402
130134
examples/userdemo/pgf_preamble_sgskip.py: E402

doc/api/backend_gtk4_api.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
**NOTE** These backends are not documented here, to avoid adding a dependency
2+
to building the docs.
3+
4+
.. redirect-from:: /api/backend_gtk4agg_api
5+
.. redirect-from:: /api/backend_gtk4cairo_api
6+
7+
8+
:mod:`matplotlib.backends.backend_gtk4agg`
9+
==========================================
10+
11+
.. module:: matplotlib.backends.backend_gtk4agg
12+
13+
:mod:`matplotlib.backends.backend_gtk4cairo`
14+
============================================
15+
16+
.. module:: matplotlib.backends.backend_gtk4cairo

doc/api/index_backend_api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
backend_agg_api.rst
1111
backend_cairo_api.rst
1212
backend_gtk3_api.rst
13+
backend_gtk4_api.rst
1314
backend_nbagg_api.rst
1415
backend_pdf_api.rst
1516
backend_pgf_api.rst

doc/devel/dependencies.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ and the capabilities they provide.
4242

4343
* Tk_ (>= 8.4, != 8.6.0 or 8.6.1) [#]_: for the Tk-based backends.
4444
* PyQt6_ (>= 6.1), PySide6_, PyQt5_, or PySide2_: for the Qt-based backends.
45-
* PyGObject_: for the GTK3-based backends [#]_.
45+
* PyGObject_: for the GTK-based backends [#]_.
4646
* wxPython_ (>= 4) [#]_: for the wx-based backends.
47-
* pycairo_ (>= 1.11.0) or cairocffi_ (>= 0.8): for the GTK3 and/or cairo-based
47+
* pycairo_ (>= 1.11.0) or cairocffi_ (>= 0.8): for the GTK and/or cairo-based
4848
backends.
4949
* Tornado_: for the WebAgg backend.
5050

examples/user_interfaces/embedding_in_gtk3_panzoom_sgskip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
win = Gtk.Window()
2121
win.connect("delete-event", Gtk.main_quit)
2222
win.set_default_size(400, 300)
23-
win.set_title("Embedding in GTK")
23+
win.set_title("Embedding in GTK3")
2424

2525
fig = Figure(figsize=(5, 4), dpi=100)
2626
ax = fig.add_subplot(1, 1, 1)

examples/user_interfaces/embedding_in_gtk3_sgskip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
win = Gtk.Window()
2020
win.connect("delete-event", Gtk.main_quit)
2121
win.set_default_size(400, 300)
22-
win.set_title("Embedding in GTK")
22+
win.set_title("Embedding in GTK3")
2323

2424
fig = Figure(figsize=(5, 4), dpi=100)
2525
ax = fig.add_subplot()
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
===========================================
3+
Embedding in GTK4 with a navigation toolbar
4+
===========================================
5+
6+
Demonstrate NavigationToolbar with GTK4 accessed via pygobject.
7+
"""
8+
9+
import gi
10+
gi.require_version('Gtk', '4.0')
11+
from gi.repository import Gtk
12+
13+
from matplotlib.backends.backend_gtk4 import (
14+
NavigationToolbar2GTK4 as NavigationToolbar)
15+
from matplotlib.backends.backend_gtk4agg import (
16+
FigureCanvasGTK4Agg as FigureCanvas)
17+
from matplotlib.figure import Figure
18+
import numpy as np
19+
20+
21+
def on_activate(app):
22+
win = Gtk.ApplicationWindow(application=app)
23+
win.set_default_size(400, 300)
24+
win.set_title("Embedding in GTK4")
25+
26+
fig = Figure(figsize=(5, 4), dpi=100)
27+
ax = fig.add_subplot(1, 1, 1)
28+
t = np.arange(0.0, 3.0, 0.01)
29+
s = np.sin(2*np.pi*t)
30+
ax.plot(t, s)
31+
32+
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
33+
win.set_child(vbox)
34+
35+
# Add canvas to vbox
36+
canvas = FigureCanvas(fig) # a Gtk.DrawingArea
37+
canvas.set_hexpand(True)
38+
canvas.set_vexpand(True)
39+
vbox.append(canvas)
40+
41+
# Create toolbar
42+
toolbar = NavigationToolbar(canvas, win)
43+
vbox.append(toolbar)
44+
45+
win.show()
46+
47+
48+
app = Gtk.Application(
49+
application_id='org.matplotlib.examples.EmbeddingInGTK4PanZoom')
50+
app.connect('activate', on_activate)
51+
app.run(None)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
=================
3+
Embedding in GTK4
4+
=================
5+
6+
Demonstrate adding a FigureCanvasGTK4Agg widget to a Gtk.ScrolledWindow using
7+
GTK4 accessed via pygobject.
8+
"""
9+
10+
import gi
11+
gi.require_version('Gtk', '4.0')
12+
from gi.repository import Gtk
13+
14+
from matplotlib.backends.backend_gtk4agg import (
15+
FigureCanvasGTK4Agg as FigureCanvas)
16+
from matplotlib.figure import Figure
17+
import numpy as np
18+
19+
20+
def on_activate(app):
21+
win = Gtk.ApplicationWindow(application=app)
22+
win.set_default_size(400, 300)
23+
win.set_title("Embedding in GTK4")
24+
25+
fig = Figure(figsize=(5, 4), dpi=100)
26+
ax = fig.add_subplot()
27+
t = np.arange(0.0, 3.0, 0.01)
28+
s = np.sin(2*np.pi*t)
29+
ax.plot(t, s)
30+
31+
# A scrolled margin goes outside the scrollbars and viewport.
32+
sw = Gtk.ScrolledWindow(margin_top=10, margin_bottom=10,
33+
margin_start=10, margin_end=10)
34+
win.set_child(sw)
35+
36+
canvas = FigureCanvas(fig) # a Gtk.DrawingArea
37+
canvas.set_size_request(800, 600)
38+
sw.set_child(canvas)
39+
40+
win.show()
41+
42+
43+
app = Gtk.Application(application_id='org.matplotlib.examples.EmbeddingInGTK4')
44+
app.connect('activate', on_activate)
45+
app.run(None)

examples/user_interfaces/gtk_spreadsheet_sgskip.py renamed to examples/user_interfaces/gtk3_spreadsheet_sgskip.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
2-
===============
3-
GTK Spreadsheet
4-
===============
2+
================
3+
GTK3 Spreadsheet
4+
================
55
66
Example of embedding Matplotlib in an application and interacting with a
77
treeview to store data. Double click on an entry to update plot data.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""
2+
================
3+
GTK4 Spreadsheet
4+
================
5+
6+
Example of embedding Matplotlib in an application and interacting with a
7+
treeview to store data. Double click on an entry to update plot data.
8+
"""
9+
10+
import gi
11+
gi.require_version('Gtk', '4.0')
12+
gi.require_version('Gdk', '4.0')
13+
from gi.repository import Gtk
14+
15+
from matplotlib.backends.backend_gtk4agg import FigureCanvas # or gtk4cairo.
16+
17+
from numpy.random import random
18+
from matplotlib.figure import Figure
19+
20+
21+
class DataManager(Gtk.ApplicationWindow):
22+
num_rows, num_cols = 20, 10
23+
24+
data = random((num_rows, num_cols))
25+
26+
def __init__(self, *args, **kwargs):
27+
super().__init__(*args, **kwargs)
28+
self.set_default_size(600, 600)
29+
30+
self.set_title('GtkListStore demo')
31+
32+
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False,
33+
spacing=8)
34+
self.set_child(vbox)
35+
36+
label = Gtk.Label(label='Double click a row to plot the data')
37+
vbox.append(label)
38+
39+
sw = Gtk.ScrolledWindow()
40+
sw.set_has_frame(True)
41+
sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
42+
sw.set_hexpand(True)
43+
sw.set_vexpand(True)
44+
vbox.append(sw)
45+
46+
model = self.create_model()
47+
self.treeview = Gtk.TreeView(model=model)
48+
self.treeview.connect('row-activated', self.plot_row)
49+
sw.set_child(self.treeview)
50+
51+
# Matplotlib stuff
52+
fig = Figure(figsize=(6, 4), constrained_layout=True)
53+
54+
self.canvas = FigureCanvas(fig) # a Gtk.DrawingArea
55+
self.canvas.set_hexpand(True)
56+
self.canvas.set_vexpand(True)
57+
vbox.append(self.canvas)
58+
ax = fig.add_subplot()
59+
self.line, = ax.plot(self.data[0, :], 'go') # plot the first row
60+
61+
self.add_columns()
62+
63+
def plot_row(self, treeview, path, view_column):
64+
ind, = path # get the index into data
65+
points = self.data[ind, :]
66+
self.line.set_ydata(points)
67+
self.canvas.draw()
68+
69+
def add_columns(self):
70+
for i in range(self.num_cols):
71+
column = Gtk.TreeViewColumn(str(i), Gtk.CellRendererText(), text=i)
72+
self.treeview.append_column(column)
73+
74+
def create_model(self):
75+
types = [float] * self.num_cols
76+
store = Gtk.ListStore(*types)
77+
for row in self.data:
78+
# Gtk.ListStore.append is broken in PyGObject, so insert manually.
79+
it = store.insert(-1)
80+
store.set(it, {i: val for i, val in enumerate(row)})
81+
return store
82+
83+
84+
def on_activate(app):
85+
manager = DataManager(application=app)
86+
manager.show()
87+
88+
89+
app = Gtk.Application(application_id='org.matplotlib.examples.GTK4Spreadsheet')
90+
app.connect('activate', on_activate)
91+
app.run()

examples/user_interfaces/pylab_with_gtk_sgskip.py renamed to examples/user_interfaces/pylab_with_gtk3_sgskip.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
2-
===============
3-
pyplot with GTK
4-
===============
2+
================
3+
pyplot with GTK3
4+
================
55
66
An example of how to use pyplot to manage your figure windows, but modify the
77
GUI by accessing the underlying GTK widgets.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
================
3+
pyplot with GTK4
4+
================
5+
6+
An example of how to use pyplot to manage your figure windows, but modify the
7+
GUI by accessing the underlying GTK widgets.
8+
"""
9+
10+
import matplotlib
11+
matplotlib.use('GTK4Agg') # or 'GTK4Cairo'
12+
import matplotlib.pyplot as plt
13+
14+
import gi
15+
gi.require_version('Gtk', '4.0')
16+
from gi.repository import Gtk
17+
18+
19+
fig, ax = plt.subplots()
20+
ax.plot([1, 2, 3], 'ro-', label='easy as 1 2 3')
21+
ax.plot([1, 4, 9], 'gs--', label='easy as 1 2 3 squared')
22+
ax.legend()
23+
24+
manager = fig.canvas.manager
25+
# you can access the window or vbox attributes this way
26+
toolbar = manager.toolbar
27+
vbox = manager.vbox
28+
29+
# now let's add a button to the toolbar
30+
button = Gtk.Button(label='Click me')
31+
button.connect('clicked', lambda button: print('hi mom'))
32+
button.set_tooltip_text('Click me for fun and profit')
33+
toolbar.append(button)
34+
35+
# now let's add a widget to the vbox
36+
label = Gtk.Label()
37+
label.set_markup('Drag mouse over axes for position')
38+
vbox.insert_child_after(label, fig.canvas)
39+
40+
41+
def update(event):
42+
if event.xdata is None:
43+
label.set_markup('Drag mouse over axes for position')
44+
else:
45+
label.set_markup(
46+
f'<span color="#ef0000">x,y=({event.xdata}, {event.ydata})</span>')
47+
48+
49+
fig.canvas.mpl_connect('motion_notify_event', update)
50+
51+
plt.show()

tutorials/introductory/sample_plots.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@
338338
339339
For examples of how to embed Matplotlib in different toolkits, see:
340340
341+
* :doc:`/gallery/user_interfaces/embedding_in_gtk4_sgskip`
341342
* :doc:`/gallery/user_interfaces/embedding_in_gtk3_sgskip`
342343
* :doc:`/gallery/user_interfaces/embedding_in_wx2_sgskip`
343344
* :doc:`/gallery/user_interfaces/mpl_with_glade3_sgskip`

tutorials/introductory/usage.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,10 @@ def my_plotter(ax, data1, data2, param_dict):
300300
# Without a backend explicitly set, Matplotlib automatically detects a usable
301301
# backend based on what is available on your system and on whether a GUI event
302302
# loop is already running. The first usable backend in the following list is
303-
# selected: MacOSX, Qt5Agg, Gtk3Agg, TkAgg, WxAgg, Agg. The last, Agg, is a
304-
# non-interactive backend that can only write to files. It is used on Linux,
305-
# if Matplotlib cannot connect to either an X display or a Wayland display.
303+
# selected: MacOSX, QtAgg, GTK4Agg, Gtk3Agg, TkAgg, WxAgg, Agg. The last, Agg,
304+
# is a non-interactive backend that can only write to files. It is used on
305+
# Linux, if Matplotlib cannot connect to either an X display or a Wayland
306+
# display.
306307
#
307308
# Here is a detailed description of the configuration methods:
308309
#
@@ -370,7 +371,7 @@ def my_plotter(ax, data1, data2, param_dict):
370371
# from the canvas (the place where the drawing goes). The canonical
371372
# renderer for user interfaces is ``Agg`` which uses the `Anti-Grain
372373
# Geometry`_ C++ library to make a raster (pixel) image of the figure; it
373-
# is used by the ``QtAgg``, ``GTK3Agg``, ``wxAgg``, ``TkAgg``, and
374+
# is used by the ``QtAgg``, ``GTK4Agg``, ``GTK3Agg``, ``wxAgg``, ``TkAgg``, and
374375
# ``macosx`` backends. An alternative renderer is based on the Cairo library,
375376
# used by ``QtCairo``, etc.
376377
#
@@ -419,6 +420,9 @@ def my_plotter(ax, data1, data2, param_dict):
419420
# GTK3Agg Agg rendering to a GTK_ 3.x canvas (requires PyGObject_,
420421
# and pycairo_ or cairocffi_). This backend can be activated in
421422
# IPython with ``%matplotlib gtk3``.
423+
# GTK4Agg Agg rendering to a GTK_ 4.x canvas (requires PyGObject_,
424+
# and pycairo_ or cairocffi_). This backend can be activated in
425+
# IPython with ``%matplotlib gtk4``.
422426
# macosx Agg rendering into a Cocoa canvas in OSX. This backend can be
423427
# activated in IPython with ``%matplotlib osx``.
424428
# TkAgg Agg rendering to a Tk_ canvas (requires TkInter_). This
@@ -430,6 +434,8 @@ def my_plotter(ax, data1, data2, param_dict):
430434
# figure.
431435
# GTK3Cairo Cairo rendering to a GTK_ 3.x canvas (requires PyGObject_,
432436
# and pycairo_ or cairocffi_).
437+
# GTK4Cairo Cairo rendering to a GTK_ 4.x canvas (requires PyGObject_,
438+
# and pycairo_ or cairocffi_).
433439
# wxAgg Agg rendering to a wxWidgets_ canvas (requires wxPython_ 4).
434440
# This backend can be activated in IPython with ``%matplotlib wx``.
435441
# ========= ================================================================

0 commit comments

Comments
 (0)