configure_traits freezes console in Spyder/Anaconda

huangapple go评论100阅读模式
英文:

configure_traits freezes console in Spyder/Anaconda

问题

以下是代码的翻译部分:

尝试在traitsui文档中的第一个示例:

from traits.api import HasTraits, Str, Int
from traitsui.api import View, Item
import traitsui

class SimpleEmployee(HasTraits):
    first_name = Str
    last_name = Str
    department = Str
    employee_number = Str
    salary = Int

view1 = View(Item(name='first_name'),
             Item(name='last_name'),
             Item(name='department'))

sam = SimpleEmployee()
sam.configure_traits(view=view1)

这会导致Spyder IPython控制台挂起,即使UI窗口已关闭。

MacOSX 10.14.6,Spyder 4.0.0,Python 3.7.0,IPython 7.10.2,traitsui 6.1.3

可能需要配置有关UI事件循环的某些内容,但是怎么做呢?

英文:

Trying the very first example in traitsui doc:

from traits.api import HasTraits, Str, Int
from traitsui.api import View, Item
import traitsui

class SimpleEmployee(HasTraits):
    first_name = Str
    last_name = Str
    department = Str
    employee_number = Str
    salary = Int

view1 = View(Item(name = 'first_name'),
             Item(name = 'last_name'),
             Item(name = 'department'))

sam = SimpleEmployee()
sam.configure_traits(view=view1)

makes the Spyder IPython console hang, even after the UI window has been closed.

MacOSX 10.14.6, Spyder 4.0.0, Python 3.7.0, IPython 7.10.2, traitsui 6.1.3

Probably something to configure about the UI event loop, but what and how ?

答案1

得分: 0

以下是您提供的代码的翻译部分:

差异在于Canopy IPython控制台和Spyder IPython控制台之间的区别在于

app = QtGui.QApplication.instance()
print(app)

对于两者都返回:

<PyQt5.QtWidgets.QApplication at 0xXXXXXXXX>

但是在Canopy IPython终端中,以下代码

is_event_loop_running_qt4(app)

返回True,而在Spyder IPython终端中返回False

需要通过注释掉启动新的ViewApplication实例的行来修复traits.qt4.view_application()。而不是更改原始文件,可以运行以下代码:

# -*- coding: utf-8 -*-

"""避免Spyder控制台在使用configure_traits()时挂起"""

from IPython import get_ipython

from pyface.qt import QtCore, QtGui, qt_api
from pyface.util.guisupport import is_event_loop_running_qt4

from traitsui.api import toolkit
from traitsui.qt4.view_application import ViewApplication

KEEP_ALIVE_UIS = set()

def on_ui_destroyed(object, name, old, destroyed):
    """从KEEP_ALIVE_UIS中删除UI对象。"""
    assert name == 'destroyed'
    if destroyed:
        assert object in KEEP_ALIVE_UIS
        KEEP_ALIVE_UIS.remove(object)
        object.on_trait_change(on_ui_destroyed, 'destroyed', remove=True)

def _view_application(context, view, kind, handler, id, scrollable, args):
    """创建一个独立的PyQt应用程序来显示指定的traits UI视图。"""

    if (kind == 'panel') or ((kind is None) and (view.kind == 'panel')):
        kind = 'modal'
        
    # !!!!!!! 以下4行已被注释掉 !!!!!!!!!!!
    # app = QtGui.QApplication.instance()
    # if app is None or not is_event_loop_running_qt4(app):
    #     return ViewApplication(context, view, kind, handler, id,
    #                            scrollable, args).ui.result
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
    ui = view.ui(context,
                 kind=kind,
                 handler=handler,
                 id=id,
                 scrollable=scrollable,
                 args=args)

    # 如果UI尚未关闭,我们需要保持对其的引用,直到它关闭。
    if not ui.destroyed:
        KEEP_ALIVE_UIS.add(ui)
        ui.on_trait_change(on_ui_destroyed, 'destroyed')
    return ui.result

def view_application(self, context, view, kind=None, handler=None,
                     id='', scrollable=None, args=None):
    """创建一个PyQt模态对话框用户界面,使用来自指定View对象的信息运行作为完整应用程序。"""

    return _view_application(context, view, kind, handler,
                                             id, scrollable, args)

from traitsui.qt4.toolkit import GUIToolkit

GUIToolkit.view_application = view_application

因此,在Spyder和Canopy IPython控制台中,行为都是正常的。请注意,configure_traits(kind='modal')在两者中也都正常工作。

英文:

The difference between the Canopy IPython console and the Spyder IPython console is that

app = QtGui.QApplication.instance()
print(app)

returns

<PyQt5.QtWidgets.QApplication at 0xXXXXXXXX>

for both, but

is_event_loop_running_qt4(app)

returns Truein Canopy IPython terminal and False in Spyder IPython terminal.

It is necessary to patch view_application() in traits.qt4.view_application by commenting out the lines starting a new ViewApplication instance depending on that test. Instead of changing the original file, it is possible to run the following code:

# -*- coding: utf-8 -*-

"""Avoid Spyder console to hang when using configure_traits()
"""

from IPython import get_ipython

from pyface.qt import QtCore, QtGui, qt_api
from pyface.util.guisupport import is_event_loop_running_qt4

from traitsui.api import toolkit
from traitsui.qt4.view_application import ViewApplication

KEEP_ALIVE_UIS = set()

def on_ui_destroyed(object, name, old, destroyed):
    """ Remove the UI object from KEEP_ALIVE_UIS.
    """
    assert name == 'destroyed'
    if destroyed:
        assert object in KEEP_ALIVE_UIS
        KEEP_ALIVE_UIS.remove(object)
        object.on_trait_change(on_ui_destroyed, 'destroyed', remove=True)

def _view_application(context, view, kind, handler, id, scrollable, args):
    """ Creates a stand-alone PyQt application to display a specified traits UI
        View.

    Parameters
    ----------
    context : object or dictionary
        A single object or a dictionary of string/object pairs, whose trait
        attributes are to be edited. If not specified, the current object is
        used.
    view : view object
        A View object that defines a user interface for editing trait attribute
        values.
    kind : string
        The type of user interface window to create. See the
        **traitsui.view.kind_trait** trait for values and
        their meanings. If *kind* is unspecified or None, the **kind**
        attribute of the View object is used.
    handler : Handler object
        A handler object used for event handling in the dialog box. If
        None, the default handler for Traits UI is used.
    scrollable : Boolean
        Indicates whether the dialog box should be scrollable. When set to
        True, scroll bars appear on the dialog box if it is not large enough
        to display all of the items in the view at one time.


    """
    if (kind == 'panel') or ((kind is None) and (view.kind == 'panel')):
        kind = 'modal'
        
    # !!!!!!! The following 4 lines commented out !!!!!!!!!!!
    # app = QtGui.QApplication.instance()
    # if app is None or not is_event_loop_running_qt4(app):
    #     return ViewApplication(context, view, kind, handler, id,
    #                            scrollable, args).ui.result
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    ui = view.ui(context,
                 kind=kind,
                 handler=handler,
                 id=id,
                 scrollable=scrollable,
                 args=args)

    # If the UI has not been closed yet, we need to keep a reference to
    # it until it does close.
    if not ui.destroyed:
        KEEP_ALIVE_UIS.add(ui)
        ui.on_trait_change(on_ui_destroyed, 'destroyed')
    return ui.result

def view_application(self, context, view, kind=None, handler=None,
                     id='', scrollable=None, args=None):
    """ Creates a PyQt modal dialog user interface that
        runs as a complete application, using information from the
        specified View object.

    Parameters
    ----------
    context : object or dictionary
        A single object or a dictionary of string/object pairs, whose trait
        attributes are to be edited. If not specified, the current object is
        used.
    view : view or string
        A View object that defines a user interface for editing trait
        attribute values.
    kind : string
        The type of user interface window to create. See the
        **traitsui.view.kind_trait** trait for values and
        their meanings. If *kind* is unspecified or None, the **kind**
        attribute of the View object is used.
    handler : Handler object
        A handler object used for event handling in the dialog box. If
        None, the default handler for Traits UI is used.
    id : string
        A unique ID for persisting preferences about this user interface,
        such as size and position. If not specified, no user preferences
        are saved.
    scrollable : Boolean
        Indicates whether the dialog box should be scrollable. When set to
        True, scroll bars appear on the dialog box if it is not large enough
        to display all of the items in the view at one time.

    """
    return _view_application(context, view, kind, handler,
                                             id, scrollable, args)

from traitsui.qt4.toolkit import GUIToolkit

GUIToolkit.view_application = view_application

Thus, the behavior is OK in both Spyder and Canopy IPython consoles. Note that configure_traits(kind='modal') is also OK in both.

huangapple
  • 本文由 发表于 2020年1月3日 17:31:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/59576045.html
  • traitsui
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定