Chinaunix首页 | 论坛 | 博客
  • 博客访问: 962623
  • 博文数量: 33
  • 博客积分: 803
  • 博客等级: 军士长
  • 技术积分: 1755
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-05 18:58
个人简介

《Python科学计算》的作者

文章分类

全部博文(33)

文章存档

2016年(1)

2014年(2)

2013年(3)

2012年(27)

分类: Python/Ruby

2012-04-10 16:58:08

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变量访问表示窗口的对象。为了演示命令行的功能,我们添加了一个行文本编辑控件。程序的运行界面如下图所示:

spyder_shell.jpg

图中通过在命令行中运行:

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_types = [np.ndarray, int, long, float, str, tuple, dict, list]
        for key, value in data.iteritems():
            if not key.startswith("__") and type(value) in support_types:
                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_types = [np.ndarray, int, long, float, str, tuple, dict, list]

调用字典编辑器的set_data()设置其所编辑的字典,这里将命令行控件的名字空间通过传递给它。

在run()中,首先在命令行的名字空间中运行代码编辑器中的程序,然后调用字典编辑器的set_data()刷新字典编辑器的显示。

由于系统的标准输入输出都改为了命令行,为了显示错误信息,我们捕捉所有的异常,并通过sys.__stdout__将异常信息输出到控制台窗口中。

程序的运行界面如下:

spyder_widgets_demo.jpg
阅读(7896) | 评论(5) | 转发(2) |
给主人留下些什么吧!~~

hawkjin2012-04-15 17:53:02

HyryStudio: 嗯,Spyder的内容太多了,本文挑了几个开发界面程序时可能有用的介绍了一下。下次准备讲讲guiqwt这个绘图库。.....
有时间可以一起坐坐啊,看了你的大作,想请你吃饭了,嘿嘿

hawkjin2012-04-15 17:51:47

有时间可以一起坐坐啊,看了你的大作,想请你吃饭了,嘿嘿

3783335812012-04-12 11:05:49

比较精细了,要扩展开了讲太多,其实主要还是多用用

HyryStudio2012-04-11 19:38:01

嗯,Spyder的内容太多了,本文挑了几个开发界面程序时可能有用的介绍了一下。下次准备讲讲guiqwt这个绘图库。

认真的鱼1232012-04-11 17:24:27

~~楼主可以再精细的讲讲其他的控件嘛???