matplotlib.widgets.TextBox 在包含多个子图的图中交互速度较慢。

huangapple go评论67阅读模式
英文:

matplotlib.widgets.TextBox interaction is slow when figure contains several subplots

问题

以下是演示问题的Python代码。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.widgets import TextBox

class Textbox_Demo(object):
    def __init__(self):
        self.fig = plt.figure(figsize=(8,8))
        self.string = 'label'

        self.rows = 5   # reducing rows speeds up textbox interaction
        self.cols = 5   # reducing cols speeds up textbox interaction
        self.plot_count = self.rows * self.cols
        self.gs = gridspec.GridSpec(self.rows, self.cols,
            left=0.05, right=1-0.02, top=1-0.02,  bottom=0.10, wspace=0.3, hspace=0.4)
        for k in range(self.plot_count):
            ax = self.fig.add_subplot(self.gs[k])
            #ax.set_xticks([])  # showing axes slows textbox interaction
            #ax.set_yticks([])  # showing axes slows textbox interaction
            data = np.atleast_2d(np.sin(np.linspace(1,255,255) * 50))
            ax.imshow(data, aspect="auto", cmap='ocean')

        # this is the user-input textbox
        tb_axis = plt.axes([0.125, 0.02, 0.8, 0.05])
        self.tb = TextBox(tb_axis, 'Enter label:', initial=self.string, label_pad=0.01)
        self.tb.on_submit(self.on_submit)

        plt.show()

    def on_submit(self, text):
        pass

if __name__ == "__main__":
    Textbox_Demo()
英文:

Below is python code to demonstrate the problem.<br>
If there are 2 rows and 2 columns of images, for example, typing/erasing in the textbox is reasonably fast. However, if there are 5 rows and 5 columns, typing/erasing in the textbox is quite slow. If the xticks and yticks are drawn, interaction is even slower. So, it seems as if the entire figure is redrawn after every keystroke.<br>
Is there a solution for this (apart from putting the textbox on a separate figure)?<br>
(My development platform is MacOS Mojave, Python 3.7.5.)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.widgets import TextBox

class Textbox_Demo(object):
    def __init__(self):
        self.fig = plt.figure(figsize=(8,8))
        self.string = &#39;label&#39;

        self.rows = 5   # reducing rows speeds up textbox interaction
        self.cols = 5   # reducing cols speeds up textbox interaction
        self.plot_count = self.rows * self.cols
        self.gs = gridspec.GridSpec(self.rows, self.cols,
            left=0.05, right=1-0.02, top=1-.02,  bottom=0.10, wspace=0.3, hspace=0.4)
        for k in range(self.plot_count):
            ax = self.fig.add_subplot(self.gs[k])
            #ax.set_xticks([])  # showing axes slows textbox interaction
            #ax.set_yticks([])  # showing axes slows textbox interaction
            data = np.atleast_2d(np.sin(np.linspace(1,255,255) * 50))
            ax.imshow(data, aspect=&quot;auto&quot;, cmap=&#39;ocean&#39;)

        # this is the user-input textbox
        tb_axis = plt.axes([0.125, 0.02, 0.8, 0.05])
        self.tb = TextBox(tb_axis, &#39;Enter label:&#39;, initial=self.string, label_pad=0.01)
        self.tb.on_submit(self.on_submit)

        plt.show()

    def on_submit(self, text):
        pass

if __name__ == &quot;__main__&quot;:
    Textbox_Demo()

答案1

得分: 2

Matplotlib的TextBox本质上较慢,因为它使用matplotlib本身提供的绘图工具,因此在更改时重新绘制整个图形。

我建议使用GUI工具包中的文本框。例如,对于PyQt,可能会像这样:

import numpy as np
import sys
from matplotlib.backends.backend_qt5agg import (
    FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.backends.qt_compat import QtCore, QtWidgets
import matplotlib.gridspec as gridspec
from matplotlib.figure import Figure


class Textbox_Demo(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)
        layout = QtWidgets.QVBoxLayout(self._main)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self.fig = Figure(figsize=(8, 8))
        self.canvas = FigureCanvas(self.fig)
        layout.addWidget(self.canvas)
        self.addToolBar(NavigationToolbar(self.canvas, self))

        self._textwidget = QtWidgets.QWidget()
        textlayout = QtWidgets.QHBoxLayout(self._textwidget)
        self.textbox = QtWidgets.QLineEdit(self)
        self.textbox.editingFinished.connect(self.on_submit)
        # or, if wanting to have changed apply directly:
        # self.textbox.textEdited.connect(self.on_submit)
        textlayout.addWidget(QtWidgets.QLabel("Enter Text: "))
        textlayout.addWidget(self.textbox)
        layout.addWidget(self._textwidget)

        self.fill_figure()

    def fill_figure(self):
        self.string = 'label'

        self.rows = 5   # reducing rows speeds up textbox interaction
        self.cols = 5   # reducing cols speeds up textbox interaction
        self.plot_count = self.rows * self.cols
        self.gs = gridspec.GridSpec(self.rows, self.cols,
            left=0.05, right=1-0.02, top=1-.02,  bottom=0.10, wspace=0.3, hspace=0.4)
        for k in range(self.plot_count):
            ax = self.fig.add_subplot(self.gs[k])
            # ax.set_xticks([])  # showing axes slows textbox interaction
            # ax.set_yticks([])  # showing axes slows textbox interaction
            data = np.atleast_2d(np.sin(np.linspace(1, 255, 255) * 50))
            ax.imshow(data, aspect="auto", cmap='ocean')

    def on_submit(self):
        text = self.textbox.text()
        print(text)
        pass


if __name__ == "__main__":
    qapp = QtWidgets.QApplication(sys.argv)
    app = Textbox_Demo()
    app.show()
    qapp.exec_()

matplotlib.widgets.TextBox 在包含多个子图的图中交互速度较慢。

英文:

Matplotlib's TextBox is inherently slow, because it uses the drawing tools provided by matplotlib itself and hence redraws the complete figure upon changes.

I would propose to use a text box of a GUI kit instead. For example for PyQt this might look like:

matplotlib.widgets.TextBox 在包含多个子图的图中交互速度较慢。

import numpy as np
import sys
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.backends.qt_compat import QtCore, QtWidgets
import matplotlib.gridspec as gridspec
from matplotlib.figure import Figure
class Textbox_Demo(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
layout = QtWidgets.QVBoxLayout(self._main)
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
self.fig = Figure(figsize=(8,8))
self.canvas = FigureCanvas(self.fig)
layout.addWidget(self.canvas)
self.addToolBar(NavigationToolbar(self.canvas, self))
self._textwidget = QtWidgets.QWidget()
textlayout = QtWidgets.QHBoxLayout(self._textwidget)
self.textbox = QtWidgets.QLineEdit(self)
self.textbox.editingFinished.connect(self.on_submit)
# or, if wanting to have changed apply directly:
# self.textbox.textEdited.connect(self.on_submit)
textlayout.addWidget(QtWidgets.QLabel(&quot;Enter Text: &quot;))
textlayout.addWidget(self.textbox)
layout.addWidget(self._textwidget)
self.fill_figure()
def fill_figure(self):
self.string = &#39;label&#39;
self.rows = 5   # reducing rows speeds up textbox interaction
self.cols = 5   # reducing cols speeds up textbox interaction
self.plot_count = self.rows * self.cols
self.gs = gridspec.GridSpec(self.rows, self.cols,
left=0.05, right=1-0.02, top=1-.02,  bottom=0.10, wspace=0.3, hspace=0.4)
for k in range(self.plot_count):
ax = self.fig.add_subplot(self.gs[k])
#ax.set_xticks([])  # showing axes slows textbox interaction
#ax.set_yticks([])  # showing axes slows textbox interaction
data = np.atleast_2d(np.sin(np.linspace(1,255,255) * 50))
ax.imshow(data, aspect=&quot;auto&quot;, cmap=&#39;ocean&#39;)
def on_submit(self):
text = self.textbox.text()
print(text)
pass
if __name__ == &quot;__main__&quot;:
qapp = QtWidgets.QApplication(sys.argv)
app = Textbox_Demo()
app.show()
qapp.exec_()

huangapple
  • 本文由 发表于 2020年1月6日 18:27:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/59610425.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定