能否在PyCharm等IDE中使用ipywidgets实现交互式可视化?
问题描述
现有基于Python的交互式绘图代码在Jupyter Notebook中可正常运行,但在PyCharm IDE中执行时无图表显示,仅输出widget的文本信息。
复现代码
import matplotlib.pyplot as plt import numpy as np import SimpleITK as sitk from ipywidgets import interact, fixed def display_center_effect(x, y, tx, point_list, xlim, ylim): tx.SetCenter((x, y)) transformed_point_list = [tx.TransformPoint(p) for p in point_list] plt.scatter( list(np.array(transformed_point_list).T)[0], list(np.array(transformed_point_list).T)[1], marker="^", color="red", label="transformed points", ) plt.scatter( list(np.array(point_list).T)[0], list(np.array(point_list).T)[1], marker="o", color="blue", label="original points", ) plt.xlim(xlim) plt.ylim(ylim) plt.legend(loc=(0.25, 1.01)) # plt.show() # 2D square centered on (0,0) points = [ np.array((-1.0, -1.0)), np.array((-1.0, 1.0)), np.array((1.0, 1.0)), np.array((1.0, -1.0)), ] # Scale by 2 similarity = sitk.Similarity2DTransform() similarity.SetScale(2) interact( display_center_effect, x=(-10, 10), y=(-10, 10), tx=fixed(similarity), point_list=fixed(points), xlim=fixed((-10, 10)), ylim=fixed((-10, 10)), )
执行输出
interactive(children=(IntSlider(value=0, description='x', max=10, min=-10), IntSlider(value=0, description='y', max=10, min=-10), Output()), _dom_classes=('widget-interact',))
已尝试TKinter、IPython.core.display等方法,均未解决问题。
可行解决方案
方案1:改用Matplotlib原生交互式组件替代ipywidgets
ipywidgets依赖Jupyter的前端渲染环境,PyCharm普通Python运行环境无法解析其UI组件。可以用Matplotlib自带的Slider实现交互:
import matplotlib.pyplot as plt import numpy as np import SimpleITK as sitk from matplotlib.widgets import Slider # 初始化画布和坐标轴 fig, ax = plt.subplots() plt.subplots_adjust(bottom=0.25) # 初始参数 init_x, init_y = 0, 0 points = [ np.array((-1.0, -1.0)), np.array((-1.0, 1.0)), np.array((1.0, 1.0)), np.array((1.0, -1.0)), ] similarity = sitk.Similarity2DTransform() similarity.SetScale(2) # 绘制初始图形 similarity.SetCenter((init_x, init_y)) transformed_points = [similarity.TransformPoint(p) for p in points] original_scatter = ax.scatter([p[0] for p in points], [p[1] for p in points], marker="o", color="blue", label="original points") transformed_scatter = ax.scatter([p[0] for p in transformed_points], [p[1] for p in transformed_points], marker="^", color="red", label="transformed points") ax.set_xlim(-10, 10) ax.set_ylim(-10, 10) ax.legend(loc=(0.25, 1.01)) # 创建滑块区域 ax_x = plt.axes([0.25, 0.1, 0.65, 0.03]) ax_y = plt.axes([0.25, 0.05, 0.65, 0.03]) slider_x = Slider(ax_x, 'X Center', -10, 10, valinit=init_x) slider_y = Slider(ax_y, 'Y Center', -10, 10, valinit=init_y) # 更新函数 def update(val): x = slider_x.val y = slider_y.val similarity.SetCenter((x, y)) new_transformed = [similarity.TransformPoint(p) for p in points] transformed_scatter.set_offsets(new_transformed) fig.canvas.draw_idle() # 绑定滑块事件 slider_x.on_changed(update) slider_y.on_changed(update) plt.show(block=True)
方案2:配置PyCharm使用Jupyter内核运行代码
如果坚持使用ipywidgets,可在PyCharm中切换到Jupyter内核执行:
- 打开
Run菜单 →Edit Configurations - 在配置窗口中,将
Python interpreter切换为你的Jupyter内核环境 - 运行代码时选择
Run with Jupyter Notebook选项,PyCharm会在内置Jupyter环境中执行,正常渲染交互组件
方案3:使用PyQtGraph实现桌面端交互
PyQtGraph专为桌面环境设计,适配PyCharm这类IDE:
import pyqtgraph as pg import numpy as np import SimpleITK as sitk from pyqtgraph.Qt import QtCore, QtGui # 初始化应用和窗口 app = QtGui.QApplication([]) win = pg.GraphicsLayoutWidget(show=True, title="Center Transform Effect") win.resize(800, 600) plot = win.addPlot(title="Point Transformation") # 初始数据 points = np.array([ (-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0), ]) similarity = sitk.Similarity2DTransform() similarity.SetScale(2) # 绘制初始点 original_plot = plot.plot(points, pen=None, symbol='o', symbolSize=10, symbolBrush='b', name='original points') transformed_plot = plot.plot(points, pen=None, symbol='^', symbolSize=10, symbolBrush='r', name='transformed points') plot.setXRange(-10, 10) plot.setYRange(-10, 10) plot.addLegend() # 创建滑块控件 widget = QtGui.QWidget() layout = QtGui.QVBoxLayout() widget.setLayout(layout) win.addWidget(widget) slider_x = QtGui.QSlider(QtCore.Qt.Horizontal) slider_x.setRange(-10, 10) slider_x.setValue(0) slider_x.setTickInterval(1) slider_x.setTickPosition(QtGui.QSlider.TicksBelow) layout.addWidget(QtGui.QLabel("X Center")) layout.addWidget(slider_x) slider_y = QtGui.QSlider(QtCore.Qt.Horizontal) slider_y.setRange(-10, 10) slider_y.setValue(0) slider_y.setTickInterval(1) slider_y.setTickPosition(QtGui.QSlider.TicksBelow) layout.addWidget(QtGui.QLabel("Y Center")) layout.addWidget(slider_y) # 更新函数 def update_slider(): x = slider_x.value() y = slider_y.value() similarity.SetCenter((x, y)) transformed_points = np.array([similarity.TransformPoint(p) for p in points]) transformed_plot.setData(transformed_points) # 绑定滑块事件 slider_x.valueChanged.connect(update_slider) slider_y.valueChanged.connect(update_slider) # 启动应用 if __name__ == '__main__': QtGui.QApplication.instance().exec_()
内容的提问来源于stack exchange,提问作者banikr
相关产品推荐
相关产品推荐

