- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想编写一个带有T基于用户用户接口(interface)的程序(TUI),它由几个部分组成表格。
这是我的尝试,它使用了库 npyscreen但不会返回到第一种形式。该代码也不包含更改列表项的逻辑。
#! /usr/bin/env python3
# coding:utf8
import npyscreen
# content
headers = ["column 1", "column 2", "column 3", "column 4"]
entries = [["a1", "a2", "a3", "a4"],
["b1", "b2", "b3", "b4"],
["c1", "c2", "c3", "c4"],
["d1", "d2", "d3", "d4"],
["e1", "e2", "e3", "e4"]]
# returns a string in which the segments are padded with spaces.
def format_entry(entry):
return "{:10} | {:10} | {:10} | {:10}".format(entry[0], entry[1] , entry[2], entry[3])
class SecondForm(npyscreen.Form):
def on_ok(self):
self.parentApp.switchFormPrevious()
# add the widgets of the second form
def create(self):
self.col1 = self.add(npyscreen.TitleText, name="column 1:")
self.col2 = self.add(npyscreen.TitleText, name="column 2:")
self.col3 = self.add(npyscreen.TitleText, name="column 3:")
self.col4 = self.add(npyscreen.TitleText, name="column 4:")
class MainForm(npyscreen.Form):
def on_ok(self):
self.parentApp.switchForm(None)
def changeToSecondForm(self):
self.parentApp.change_form("SECOND")
# add the widgets of the main form
def create(self):
self.add(npyscreen.FixedText, value=format_entry(headers), editable=False, name="header")
for i, entry in enumerate(entries):
self.add(npyscreen.ButtonPress, when_pressed_function=self.changeToSecondForm, name=format_entry(entry))
class TestTUI(npyscreen.NPSAppManaged):
def onStart(self):
self.addForm("MAIN", MainForm)
self.addForm("SECOND", SecondForm, name="Edit row")
def onCleanExit(self):
npyscreen.notify_wait("Goodbye!")
def change_form(self, name):
self.switchForm(name)
if __name__ == "__main__":
tui = TestTUI()
tui.run()
最佳答案
下面是我对这个问题的看法,它可以描述为 master-detail user interface 的实现。对于控制台。
这使用了 urwid library , build 一些 custom widgets实现所描述的 UI,它有两种模式:主视图(其中主要小部件是一堆记录)和详细 View (覆盖对话框,主视图在后面)。
有很多地方可以改进,包括让它看起来更漂亮。 :)
代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Sample program demonstrating how to implement widgets for a master-detail UI
for a list of records using the urwid library (http://urwid.org)
"""
from __future__ import print_function, absolute_import, division
from functools import partial
import urwid
PALETTE = [
('bold', 'bold', ''),
('reveal focus', 'black', 'dark cyan', 'standout'),
]
def show_or_exit(key):
if key in ('q', 'Q', 'esc'):
raise urwid.ExitMainLoop()
HEADERS = ["Field 1", "Field 2", "Field 3", "Field 4"]
ENTRIES = [
["a1", "a2", "a3", "a4"],
["b1", "b2", "b3", "b4"],
["c1", "c2", "c3", "c4"],
["d1", "d2", "d3", "d4"],
["e1", "e2", "e3", "e4"],
["e1", "e2", "e3", "e4"],
["f1", "f2", "f3", "f4"],
["g1", "g2", "g3", "g4"],
["h1", "h2", "h3", "h4"],
]
class SelectableRow(urwid.WidgetWrap):
def __init__(self, contents, on_select=None):
self.on_select = on_select
self.contents = contents
self._columns = urwid.Columns([urwid.Text(c) for c in contents])
self._focusable_columns = urwid.AttrMap(self._columns, '', 'reveal focus')
super(SelectableRow, self).__init__(self._focusable_columns)
def selectable(self):
return True
def update_contents(self, contents):
# update the list record inplace...
self.contents[:] = contents
# ... and update the displayed items
for t, (w, _) in zip(contents, self._columns.contents):
w.set_text(t)
def keypress(self, size, key):
if self.on_select and key in ('enter',):
self.on_select(self)
return key
def __repr__(self):
return '%s(contents=%r)' % (self.__class__.__name__, self.contents)
class CancelableEdit(urwid.Edit):
def __init__(self, *args, **kwargs):
self.on_cancel = kwargs.pop('on_cancel', None)
super(CancelableEdit, self).__init__(*args, **kwargs)
def keypress(self, size, key):
if key == 'esc':
self.on_cancel(self)
else:
return super(CancelableEdit, self).keypress(size, key)
def build_dialog(title, contents, background, on_save=None, on_cancel=None):
buttons = urwid.Columns([
urwid.Button('Save', on_press=on_save),
urwid.Button('Cancel', on_press=on_cancel),
])
pile = urwid.Pile(
[urwid.Text(title), urwid.Divider('-')]
+ contents
+ [urwid.Divider(' '), buttons]
)
return urwid.Overlay(
urwid.Filler(urwid.LineBox(pile)),
urwid.Filler(background),
'center',
('relative', 80),
'middle',
('relative', 80),
)
class App(object):
def __init__(self, entries):
self.entries = entries
self.header = urwid.Text('Welcome to the Master Detail Urwid Sample!')
self.footer = urwid.Text('Status: ready')
contents = [
SelectableRow(row, on_select=self.show_detail_view)
for row in entries
]
listbox = urwid.ListBox(urwid.SimpleFocusListWalker(contents))
# TODO: cap to screen size
size = len(entries)
self.master_pile = urwid.Pile([
self.header,
urwid.Divider(u'─'),
urwid.BoxAdapter(listbox, size),
urwid.Divider(u'─'),
self.footer,
])
self.widget = urwid.Filler(self.master_pile, 'top')
self.loop = urwid.MainLoop(self.widget, PALETTE, unhandled_input=show_or_exit)
def show_detail_view(self, row):
self._edits = [
CancelableEdit('%s: ' % key, value, on_cancel=self.close_dialog)
for key, value in zip(HEADERS, row.contents)
]
self.loop.widget = build_dialog(
title='Editing',
contents=self._edits,
background=self.master_pile,
on_save=partial(self.save_and_close_dialog, row),
on_cancel=self.close_dialog,
)
self.show_status('Detail: %r' % row)
def save_and_close_dialog(self, row, btn):
new_content = [e.edit_text for e in self._edits]
row.update_contents(new_content)
self.show_status('Updated')
self.loop.widget = self.widget
def close_dialog(self, btn):
self.loop.widget = self.widget
def show_status(self, mesg):
self.footer.set_text(str(mesg))
def start(self):
self.loop.run()
if __name__ == '__main__':
app = App(ENTRIES)
app.start()
App
类保存应用程序的状态,跟踪主要小部件,并包含在用户操作(例如点击保存/取消按钮)时调用的方法。
记录在 SelectableRow 小部件的方法 update_contents
中就地更新,它表示一条记录显示在主列表中。
CancelableEdit
小部件的存在只是为了能够对对话窗口中的 esc 使用react。
请随时提出任何进一步澄清的问题,我尝试使用体面的名称并或多或少地保持代码的可读性,但我知道这里还有很多事情要做,我不确定需要解释什么详细点。
这是一个有趣的练习,感谢您给我这样做的借口! =)
关于python - 如何组合多个 TUI 表单来编写更复杂的应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52106244/
我有一个 mysql 表,其中包含一些随机数字组合。为简单起见,以下表为例: index|n1|n2|n3 1 1 2 3 2 4 10 32 3 3 10 4 4
我有以下代码: SELECT sdd.sd_doc_classification, sdd.sd_title, sdd.sd_desc, sdr.sd_upl
如果我有两个要合并的数据框 Date RollingSTD 01/06/2012 0.16 01/07/2012 0.18 01/08/2012 0.17 01/09/20
我知道可以使用 lein ring war 创建一个 war 文件,但它似乎仍然包含码头依赖项。当我构建 war (并在 tomcat 上部署)时,有没有办法排除码头依赖项? 如果我根本不能做这件事,
维基百科关于封装的文章指出: “封装还通过防止用户将组件的内部数据设置为无效或不一致的状态来保护组件的完整性” 我在一个论坛上开始讨论封装,在那里我问你是否应该始终在 setter 和/或 gette
对于我使用的组合框内的复选框: AOEDComboAssociationName = new Ext.form.ComboBox({ id: 'AOEDComboAssociationName',
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How do I combine LINQ expressions into one? public boo
如何在 rust 中找到排列或组合的数量? 例如C(10,6) = 210 我在标准库中找不到这个函数,也找不到那里的阶乘运算符(这就足够了)。 最佳答案 以@vallentin 的回答为基础,可以进
我有一个复杂的泛型类型用例,已在下面进行了简化 trait A class AB extends A{ val v = 10 } trait X[T<:A]{ def request: T }
如何使用 Hibernate 限制来实现此目的? (((A='X') and (B in('X',Y))) or ((A='Y') and (B='Z'))) 最佳答案 思考有效 Criteria c
我一定会在我的一个项目中使用谷歌图表。我需要的是,显示一个条形图,并且在条形图中,与每个条形相交的线代表另一个值。如果您查看下面的 jsfiddle,您会发现折线图仅与中间的条形图相交,并继续向其他条
只是一个简单的问题,我也很想得到答案,因为我不能百分百理解 Javascript 示例:假设您提示用户输入名称。够简单吧?但是你有一个数组,上面写着一些名字(其中之一就是),基本上就是我到目前为止所说
我试图通过 Haskell 理解函数式编程,但在处理函数组合时遇到了很多麻烦。 其实我有这两个功能: add:: Integer -> Integer -> Integer add x y = x
我正在寻找一种在 Realm 查询中组合 AND 和 OR 的方法。 这是我的课: class Event extends RealmObject { String id; String
例如,我有一个包含 5 个元素的哈希: my_hash = {a: 'qwe', b: 'zcx', c: 'dss', d: 'ccc', e: 'www' } 我的目标是每次循环哈希时都返回,但没
我是Combine 的新手,我想得到一个看似简单的东西。假设我有一个整数集合,例如: let myCollection = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 我想以例如 0
关于“优先组合而不是继承”的问题,我的老师是这样说的: 组合:现有类成为新类的组件 转发:新类中的每个实例方法,在现有类的包含实例上调用相应的方法并返回结果 包装器:新类封装了现有的 这三个概念我不是
我正在尝试将单个整数从 ASCII 值转换为 0 和 1。相关代码如下所示: int num1 = bin.charAt(0); int num2 = bin.charAt(1);
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 7 年前。 我经常看到“嵌套”类中的非静态变
我尝试合并两个数据集(DataFrame),如下所示: D1 = pd.DataFrame({'Village':['Ampil','Ampil','Ampil','Bachey','Bachey',
我是一名优秀的程序员,十分优秀!