在 Python GUI 中嵌入 IDL 图形窗口
12263 给这篇文章评分:
暂无评分
在 Python GUI 中嵌入 IDL 图形窗口
匿名作者 2015年10月8日,星期四
继 Jim Pendleton 上周开始的主题之后,我将展示一个反方向的例子。本例从一个使用 PyQt4 的 Python GUI 应用程序开始,展示了如何嵌入一个 IDLgrWindow 对象,以便将 IDL 对象图形渲染到 Python GUI 中所需的位置。我使用了一个未公开的 IDLgrWindow 关键字来设置目标窗口 ID。我已在 Linux 和 Windows 上运行了此代码,虽然存在一些细微差异,但下面发布的代码在两种情况下都能工作。我想指出,我在两种情况下都使用了 Anaconda-2.1.0 安装程序,以确保 Python 版本一致。我发现遵循Python 桥帮助页面上推荐的操作说明非常有用。
最终的结果是一个简单的应用程序,允许用户在 Python GUI 内部对 IDL 图形层次结构进行动画演示。图片显示了它在 Windows 7 和 Ubuntu 12.04 下的外观。


完整的 Python 源代码如下所示。
# GUI widgets
import PyQt4
from PyQt4 import QtGui
from PyQt4 import QtCore
import sys
# numpy needed for IDL
import numpy
from numpy import array
from idlpy import IDL
# OS is needed to handle Linux vs. Windows
import os
class MainWin(QtGui.QMainWindow):
def __init__(self, win_parent=None):
QtGui.QMainWindow.__init__(self,win_parent)
# widget layout
wcol = QtGui.QVBoxLayout()
wrow = QtGui.QHBoxLayout()
wcol.addLayout(wrow)
self.check = QtGui.QCheckBox('Animate')
self.slider = QtGui.QSlider(1)
self.text = QtGui.QLabel('Speed')
# EmbedContainer only works on Linux, for Windows use QWidget
if os.name== 'nt':
self.idldraw = QtGui.QWidget()
else:
self.idldraw = QtGui.QX11EmbedContainer()
self.idldraw.setFixedHeight(500)
self.idldraw.setFixedWidth(500)
wrow.addWidget(self.check)
wrow.addWidget(self.slider)
wrow.addWidget(self.text)
wcol.addWidget(self.idldraw)
w = QtGui.QWidget()
w.setLayout(wcol)
self.setCentralWidget(w)
self.setWindowTitle('IDL-Python Viewer')
self.timer = QtCore.QTimer()
# Set the timer delay in milliseconds
self.delay = 100
self.timer.start(self.delay)
self.hasDraw = False
# connect event handlers
QtCore.QObject.connect(self.check,
QtCore.SIGNAL('clicked()'),
self.on_check_clicked)
QtCore.QObject.connect(self.timer,
QtCore.SIGNAL('timeout()'),
self.on_timeout)
def on_check_clicked(self):
print 'click'
# Animate checkbox was clicked for the first time
if self.hasDraw == False:
# Create the IDL graphics objects only once
# Windows comes up as 'nt'
if os.name == 'nt':
winid = int(self.idldraw.winId())
else:
winid = self.idldraw.effectiveWinId()
# Create the IDLgrWindow, using software rendering
# connect to the Python widget using EXTERNAL_WINDOW
self.win = IDL.obj_new('IDLgrWindow', external_window=winid,
renderer=1)
self.view = IDL.obj_new('IDLgrView', color=array([128,255,128]),projection=2)
self.model = IDL.obj_new('IDLgrModel')
self.view.add(self.model)
self.planet = IDL.obj_new('orb', radius=0.1, color=array([20,20,255]))
self.moon = IDL.obj_new('orb', radius=0.03, pos=array([0.75,0,0]),
color=array([128,128,128]))
self.sun = IDL.obj_new('IDLgrLight', type=1, location=array([0,18,8]))
self.model.rotate(array([1,0,0]), 10)
self.model.add(self.sun)
self.model.add(self.planet)
self.model.add(self.moon)
self.hasDraw = True
if self.hasDraw:
self.win.draw(self.view)
def on_timeout(self):
# handle timer event, draw the scene, rotate by 2 degrees
# and check the slider value to determine the new
# timer interval
if self.hasDraw & self.check.isChecked():
self.model.rotate(array([0,0.9848,0.1736]),-2)
self.win.draw(self.view)
# slider goes from 0-99, so delay goes from 1 ms to 100 ms
speed = 100-self.slider.value()
if self.delay != speed:
self.delay = speed
self.timer.setInterval(self.delay)
if __name__ == '__main__':
# Someone is launching this directly
# Create the QApplication
app = QtGui.QApplication(sys.argv)
# The Main window
main_window = MainWin()
main_window.show()
# Enter the main loop
app.exec_()