Python的TraitsUI - 如何控制“字符串”特质编辑/视图的滚动条位置(Python T

2019-10-19 00:45发布

我用性状4构建一个简单的交互式GUI应用程序。 此应用程序将在GUI的专用部分显示事件的时间戳日志。 此日志目前作为字符串存储特性。

默认编辑器(或看法?不知道确切的命名)的字符串特征是一个滚动的多行显示小部件。 当内部字符串值发生改变时,窗口小部件更新,以显示新的价值。 如果内容长度超过微件的可见尺寸,则滚动条看上去允许用户向上和向下滚动,整个值。

看来,当微件刷新和垂直滚动条,然后可见的(含量超过插件尺寸),该视图重置为值(顶部)的开始,并且滚动条返回到顶部也,模糊值的最后部分。

在我的应用我想日志(底部)在最新事件的值刷新后始终显示。 但由于视图重置价值的顶端,它不遵循最新的条目,用户必须不断滚动每次刷新后的底部。 这是这种形式不能使用。

有没有配置此特征的编辑/查看从底部滚动一个简单的方法?

如果不是,怎么会去写这个字符串性状的自定义编辑器/查看? 难道有必要使用WX / QT4原语从头开始写一个新的观点,或者是有一些方法来获得从现有的一个新的视图,并覆盖只有那些以实现所需的功能所需要的零件?

以下是一个演示的问题的一些示例代码:

# from https://svn.enthought.com/enthought/ticket/1619 - broken SSL cert
from threading import Thread
from time import sleep
from enthought.traits.api import *
from enthought.traits.ui.api import View, Item, ButtonEditor

class TextDisplay(HasTraits):
    string =  String()

    view= View( Item('string',show_label=False, springy=True, style='custom' ))


class CaptureThread(Thread):
    def run(self):
        self.display.string = 'Camera started\n' + self.display.string
        n_img = 0
        while not self.wants_abort:
            sleep(.5)
            n_img += 1
            self.display.string += '%d image captured\n' % n_img
        self.display.string += 'Camera stopped\n'

class Camera(HasTraits):
    start_stop_capture = Button()
    display = Instance(TextDisplay)
    capture_thread = Instance(CaptureThread)

    view = View( Item('start_stop_capture', show_label=False ))

    def _start_stop_capture_fired(self):
        if self.capture_thread and self.capture_thread.isAlive():
            self.capture_thread.wants_abort = True
        else:
            self.capture_thread = CaptureThread()
            self.capture_thread.wants_abort = False
            self.capture_thread.display = self.display
            self.capture_thread.start()

class MainWindow(HasTraits):
    display = Instance(TextDisplay, ())

    camera = Instance(Camera)

    def _camera_default(self):
        return Camera(display=self.display)

    view = View('display', 'camera', style="custom", resizable=True)


if __name__ == '__main__':
    MainWindow().configure_traits()

点击“开始停止捕获”按钮多次,直到观点已经满了,你会观察到,随后刷新重置滚动条位置到视图的顶部。

Answer 1:

我需要类似的东西在几年前。 你可以找到我想出了这里: https://svn.enthought.com/enthought/wiki/OutputStream

OutputStream类有一个类似文件的接口为一个字符串。 特别是,您添加到其字符串write方法。 一个默认视图OutputStream是多行文本字段。 它具有使用适当的工具包的方法时,它被改变成将光标移动到所述串的端部的处理程序。 其使用的两种不同的演示output_stream_demo.pyoutput_stream_demo2.py ,在维基页面中给出。

你可能会想砸enthought命名空间的进口。 也就是说,变化

from enthought.traits.api import ...
from enthought.traits.ui.api import ...
from enthought.etsconfig.api import ETSConfig

from traits.api import ...
from traitsui.api import ...
from traits.etsconfig.api import ETSConfig

更新 ,以解决意见:

显然,一个的“只读”的风格TextEditor在Qt的后端采用了QLabel文本字段,而不是一个QTextEditQLabel不提供moveCursor方法。 以下修改处理程序提供了一种只读同时仍然使用强制文本字段style="custom"

def _get_editor(uiinfo, name):
    ui = uiinfo.ui
    if ui is None:
        return None
    for ed in ui._editors:
        if ed.name == name:
            return ed
    return None


class _OutputStreamViewHandler(Handler):

    def init(self, uiinfo):
        if ETSConfig.toolkit == 'qt4':
            ed = _get_editor(uiinfo, 'text')
            if ed is not None:
                # Make the text field read-only.
                ed.control.setReadOnly(True)
        return True

    def object_text_changed(self, uiinfo):
        ed = _get_editor(uiinfo, 'text')
        if ed is None:
            return

        if ETSConfig.toolkit == 'wx':
            # With wx, the control is a TextCtrl instance.
            ed.control.SetInsertionPointEnd()
        elif ETSConfig.toolkit == 'qt4':
            # With qt4, the control is a PyQt4.QtGui.QTextEdit instance.
            from PyQt4.QtGui import QTextCursor
            ed.control.moveCursor(QTextCursor.End)


文章来源: Python TraitsUI - how to control scrollbar position of a 'String' trait editor/view