【问题标题】:Can I force matplotlib to block in a PyQt thread / process?我可以强制 matplotlib 在 PyQt 线程/进程中阻塞吗?
【发布时间】:2016-04-28 06:13:23
【问题描述】:

我有一个 PyQt gui,我使用上下文菜单操作来执行一个功能。这个函数启动了一个 matplotlib 交互,我使用鼠标在图像上绘制。

问题是,当我通过 PyQt 上下文菜单操作 plt.show(block=True) 调用此函数时,不会阻止该线程上的执行,并且我无法与 matplotlib 窗口进行交互。

代码中发生的或多或少看起来像这样。当我右键单击 PyQt 小部件中的一个项目时,我会得到一个上下文菜单:

@QtCore.pyqtSlot(QtCore.QModelIndex, QtCore.QPoint)
def on_contextMenuClicked(widget, qtindex, pos):
  menu = QtGui.QMenu(widget)
  shortcut = QtGui.QKeySequence(0)
  action = menu.addAction('edit mask', edit_mask_func, shortcut)
  menu.exec_(widget.mapToGlobal(pos))

然后,当我单击编辑掩码函数时,它会调用此函数:

import matplotlib.pyplot as plt
import numpy as np

def edit_mask_func():
    # code to start a matplotlib interaction
    plt.ion()
    fig = plt.figure(1)
    ax = plt.subplot(111)
    imgOver = np.zeros(img.shape, np.uint8) + 255
    ax.imshow(img, interpolation='nearest', alpha=1)
    ax.imshow(imgOver, interpolation='nearest', alpha=0.6)
    ax.grid(False)

    # This code handles the matplotlib interactive stuff
    # like setting up callbacks 
    # eg: fig.canvas.mpl_connect('motion_notify_event', on_move)
    # and doing blit stuff. 
    pntr = Painter(fig, ax, imgOver)
    plt.title('Click on the image to draw. exit to finish')

    # THIS SHOULD BLOCK, BUT IT DOES NOT IF A CALLED BY 
    # QT INSTEAD OF THE MAIN THREAD
    plt.show(block=True)

    return pntr.img

如果我从主线程调用edit_mask_func,它工作得很好。如果我通过 PyQt 线程调用该函数,这似乎只是一个问题。

可以说明的是,如果我尝试通过输入 raw_input / input 调用来强制程序在那里阻塞,我会在 stdout 中得到这个:

>>> input('hack to block... press enter when done')
QCoreApplication::exec: The event loop is already running
hack to block... press enter when doneQCoreApplication::exec: The   event loop is already running

最终,我需要使用回调系统来集成这种交互,但我希望我现在可以做一些快速而肮脏的事情。有什么方法可以在不编写回调的情况下轻松做到这一点?

我目前正在运行 matplotlib_version 1.5.0 和 PyQt4_version 4.10.4

【问题讨论】:

  • 您的代码有很多不清楚的地方,但看起来您正在从辅助线程进行与 GUI 相关的调用。 PyQt(matplotlib 使用)不是线程安全的,如果你继续沿着这条路走,你会得到段错误。如果您需要线程,请确保所有与 GUI 相关的代码都在主线程中执行,方法是从连接到主线程中的插槽的辅助线程发出信号。

标签: python multithreading matplotlib pyqt pyqt4


【解决方案1】:

我认为这不会起作用,因为一旦你调用“plt.show()”,“pyplot”就会尝试使用嵌入式 matplotlib 画布启动第二个 pyqt gui 应用程序。

您应该尝试将 matplotlib 图形嵌入到您的 qt 应用程序中,如下所示: http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html

【讨论】:

    猜你喜欢
    • 2013-12-03
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    相关资源
    最近更新 更多