Spyder的界面元件
Spyder的界面控件库的路径可以通过如下的命令获得:
>>> import spyderlib.widgets as widgets
>>> widgets
widgets目录下的每个文件都是提供了一个Spyder界面控件,本文将介绍下面三个控件:
widgets\sourcecode\codeeditor.py 代码编辑器
widgets\arrayeditor.py 数组编辑器
widgets\internalshell.py Python命令行
代码编辑器
Spyder的代码编辑器提供了Python、Cython、Fortran、css、html、C/C++等语言的代码高亮显示。如果我们想在自己的项目中使用简单的代码编辑功能,直接使用Spyder的代码编辑器是十分便捷的。
下面是使用代码编辑器的例子:
from PyQt4.QtGui import QApplication, QFont
import sys
from spyderlib.widgets.sourcecode.codeeditor import CodeEditor
app = QApplication(sys.argv)
editor = CodeEditor()
editor.setup_editor( ❶
language = "python",
font = QFont("Courier New")
)
editor.set_text(file(__file__).read()) ❷
editor.show()
sys.exit(app.exec_())
在创建CodeEditor对象之后,❶调用setup_editor()设置编辑器的各种属性。下面是setup_editor()的参数列表及其缺省值:
def setup_editor(self, linenumbers=True, language=None, markers=False,
font=None, color_scheme=None, wrap=False, tab_mode=True,
intelligent_backspace=True, highlight_current_line=True,
occurence_highlighting=True, scrollflagarea=True,
edge_line=True, edge_line_column=79,
codecompletion_auto=False, codecompletion_case=True,
codecompletion_single=False, codecompletion_enter=False,
calltips=None, go_to_definition=False,
close_parentheses=True, auto_unindent=True,
indent_chars=" "*4, tab_stop_width=40, cloned_from=None):
...
在本例中通过设置language和font参数,将语法高亮改为Python,并将字体改为等宽的”Courier New”字体。
❷调用set_text()设置编辑器的文本内容。CodeEditor的各种方法可以通过查看CodeEditor及其父类TextEditBaseWidget的代码获得。而由于TextEditBaseWidget从QPlainTextEdit继承,因此还可以查看Qt的手册以了解更多的方法,例如toPlainText()可以获得编辑器中的文本。另外还可以通过Spyder的Preference对话框查看编辑器所支持的各种快捷键。
对象编辑器
使用Qt实现一个编辑二维数据的表格控件是一件十分繁琐的工作。幸好Spyder提供了多种用于编辑对象的编辑器,可以直接用来编辑列表、字典以及数组。下面是编辑数组的演示程序:
from PyQt4.QtGui import QApplication, QFont
import sys
import numpy as np
from spyderlib.widgets.arrayeditor import ArrayEditorWidget
app = QApplication(sys.argv)
data = np.random.randn(6, 4)
editor = ArrayEditorWidget(None, data) ❶
editor.show()
app.exec_()
editor.accept_changes() ❷
print data
❶ArrayEditorWidget的个参数为拥有此控件的父控件,由于这里直接将数组编辑器显示为窗口,因此其父控件为None。第二个参数为所编辑的数组。❷在窗口关闭之后,调用编辑器的accept_changes()将编辑器中修改的内容写回数组。
在arrayeditor模块中还提供了ArrayEditor类,它是一个编辑数组的对话框,提供了OK和Cancel两个对话框按钮。
下面是使用字典编辑器的例子:
import sys
from PyQt4.QtGui import QApplication
from spyderlib.widgets.dicteditor import DictEditorWidget
app = QApplication(sys.argv)
editor =DictEditorWidget(None, globals()) ❶
editor.show()
sys.exit(app.exec_())
❶创建DictEditorWidget对象时,将全局变量字典传递给它,因此字典编辑器将显示所有的全局变量。
Python命令行
在界面中添加Python命令行可以方便我们对程序进行调试,观察程序中各个对象的属性,以及运行它们的各种方法。
from PyQt4.QtGui import QApplication, QWidget, QFont, QVBoxLayout, QLineEdit
from spyderlib.widgets.internalshell import InternalShell
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.shell = InternalShell(self, {"demo":self}, ❶
multithreaded = False,
max_line_count = 3000,
font = QFont("Courier new", 10)
)
self.line_edit = QLineEdit() ❷
vbox = QVBoxLayout()
vbox.addWidget(self.line_edit)
vbox.addWidget(self.shell)
self.setLayout(vbox)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())
❶创建一个InternalShell对象,它的第二个参数为此对象的名字空间。在本例的命令行控件中可以通过demo变量访问表示窗口的对象。❷为了演示命令行的功能,我们添加了一个行文本编辑控件。程序的运行界面如下图所示:
图中通过在命令行中运行:
demo.line_edit.setText("hello world")
将文本编辑框中的文字改为”hello world”。
使用InternalShell之后,系统的标准输入输出都会改为使用界面中的命令行。如果程序出错界面无法显示的话,那么就看不到错误信息了。可以
一个小的综合应用
下面我们结合上述的三种控件,制作一个简单的Python运行工具。在这个程序中,用户通过编辑器编辑Python程序,然后按F5运行在命令行的名字空间中运行程序。名字空间中的数据对象将显示在字典编辑器中。下面是完整的程序:
import sys
from PyQt4.QtGui import (QApplication, QWidget, QFont, QListWidget,
QHBoxLayout, QVBoxLayout, QShortcut, QKeySequence)
import numpy as np
from spyderlib.widgets.sourcecode.codeeditor import CodeEditor
from spyderlib.widgets.internalshell import InternalShell
from spyderlib.widgets.dicteditor import DictEditorWidget
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.code_editor = CodeEditor(self)
self.code_editor.setup_editor(
language = "python",
font = QFont("Courier New")
)
run_sc = QShortcut(QKeySequence("F5"), self, self.run) ❶
self.shell = InternalShell(self, {"demo":self},
multithreaded = False,
max_line_count = 3000,
font = QFont("Courier new", 10)
)
self.dict_editor = DictEditorWidget(self, {})
self.dict_editor.editor.set_filter(self.filter_namespace) ❷
self.dict_editor.set_data(self.shell.interpreter.namespace) ❸
vbox = QVBoxLayout()
vbox.addWidget(self.code_editor)
vbox.addWidget(self.shell)
hbox = QHBoxLayout()
hbox.addWidget(self.dict_editor)
hbox.addLayout(vbox)
self.setLayout(hbox)
self.resize(800, 600)
def filter_namespace(self, data):
result = {}
support_* = [np.ndarray, int, long, float, str, tuple, dict, list]
for key, value in data.iteritems():
if not key.startswith("__") and type(value) in support_*:
result[key] = value
return result
def run(self):
code = str(self.code_editor.toPlainText())
namespace = self.shell.interpreter.namespace
exec code in namespace ❹
self.dict_editor.set_data(namespace) ❺
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
try:
demo = Demo()
demo.show()
except Exception as ex:
import traceback
sys.__stdout__.write(traceback.format_exc()) ❻
sys.exit(app.exec_())
❶创建一个F5快捷键,当F5按下时将运行run()。
❷在命令行的名字空间中除了数据对象之外,还有许多非数据对象,因此这里通过filter_namespace()对名字空间进行过滤,只显示变量名不以”__”开头、如下的类型对象:
support_* = [np.ndarray, int, long, float, str, tuple, dict, list]
❸调用字典编辑器的set_data()设置其所编辑的字典,这里将命令行控件的名字空间通过传递给它。
❹在run()中,首先在命令行的名字空间中运行代码编辑器中的程序,❺然后调用字典编辑器的set_data()刷新字典编辑器的显示。
❻由于系统的标准输入输出都改为了命令行,为了显示错误信息,我们捕捉所有的异常,并通过sys.__stdout__将异常信息输出到控制台窗口中。
程序的运行界面如下: