问题描述
我目前正在为个人项目中的服务器应用程序编写 tui,我选择了草书库来完成它。我的应用程序的一个组件遇到了问题,该组件应该用作服务器的控制台窗口。在设置将文本输出到窗口的功能时,我遇到了无法更新 TextView 的问题。
根据 this issue 中的最后一条评论,这样做的方法是使用 TextContent 并更新它,我在下面设置了它。虽然初始内容会显示在 UI 中,但不会对内容进行更新。我已经尝试通过给它一个名字来直接在 TextView 上设置内容,但没有运气。我已经能够在 TextView 本身上获取 get_content 并看到内容已更新,只是没有反映在 UI 中。
这是有问题的代码:
use std::ops::Add;
use std::borrow::{BorrowMut,Borrow};
use cursive::{View,Printer,Vec2,Rect,With};
use cursive::event::{Event,EventResult,AnyCb,Key};
use cursive::view::{Selector,ViewNotFound,ViewWrapper};
use cursive::direction::Direction;
use cursive::views::{EditView,LinearLayout,OnEventView,DummyView,TextView,TextContent};
use cursive::traits::{Nameable,Scrollable,Resizable};
use cursive::view::scroll::Scroller;
pub const CONSOLE_INPUT_NAME: &str = "console_input";
pub const CONSOLE_OUTPUT_LENGTH: u16 = 1000;
pub(crate) struct ConsoleView {
inner_view: LinearLayout,console_output: TextContent,console_output_history: LinkedList<String>
}
impl Default for ConsoleView {
fn default() -> Self {
let console_output = TextContent::new("This content should get replaced.");
let inner_view = LinearLayout::vertical()
.child(TextView::new_with_content(console_output.clone())
.full_screen()
.scrollable()
.wrap_with(OnEventView::new)
.on_pre_event_inner(Key::PageUp,|v,_| {
let scroller = v.get_scroller_mut();
if scroller.can_scroll_up() {
scroller.scroll_up(
scroller.last_outer_size().y.saturating_sub(1),);
}
Some(EventResult::Consumed(None))
})
.on_pre_event_inner(Key::PageDown,_| {
let scroller = v.get_scroller_mut();
if scroller.can_scroll_down() {
scroller.scroll_down(
scroller.last_outer_size().y.saturating_sub(1),);
}
Some(EventResult::Consumed(None))
}))
.child(DummyView)
.child(EditView::new().with_name(CONSOLE_INPUT_NAME));
return Self {
inner_view,console_output,console_output_history: LinkedList::new()
}
}
}
impl ViewWrapper for ConsoleView {
type V = LinearLayout;
fn with_view<F,R>(&self,f: F) -> Option<R> where F: FnOnce(&Self::V) -> R {
return Some(f(self.inner_view.borrow()));
}
fn with_view_mut<F,R>(&mut self,f: F) -> Option<R> where F: FnOnce(&mut Self::V) -> R {
return Some(f(self.inner_view.borrow_mut()));
}
fn into_inner(self) -> Result<Self::V,Self> where Self: Sized,Self::V: Sized {
return Ok(self.inner_view);
}
fn wrap_draw(&self,printer: &Printer) {
self.inner_view.draw(printer);
}
fn wrap_required_size(&mut self,req: Vec2) -> Vec2 {
return req;
}
fn wrap_on_event(&mut self,ch: Event) -> EventResult {
return self.inner_view.on_event(ch);
}
fn wrap_layout(&mut self,size: Vec2) {
self.inner_view.layout(size);
}
fn wrap_take_focus(&mut self,source: Direction) -> bool {
return self.inner_view.take_focus(source);
}
fn wrap_call_on_any<'a>(&mut self,selector: &Selector<'_>,callback: AnyCb<'a>) {
self.inner_view.call_on_any(selector,callback);
}
fn wrap_focus_view(&mut self,selector: &Selector<'_>) -> Result<(),ViewNotFound> {
return self.inner_view.focus_view(selector);
}
fn wrap_needs_relayout(&self) -> bool {
return self.inner_view.needs_relayout();
}
fn wrap_important_area(&self,size: Vec2) -> Rect {
return self.inner_view.important_area(size);
}
}
impl ConsoleView {
pub fn print(&mut self,line: &str) {
log::info!("Printing to console: {}",line);
self.console_output_history.push_back(line.to_string());
if self.console_output_history.len() > CONSOLE_OUTPUT_LENGTH as usize {
self.console_output_history.pop_front();
}
let out = self.console_output_history.iter().fold("".to_string(),|acc,s| {
return acc.add(s.as_str()).add("\n");
});
self.console_output.set_content(out);
}
}
这是用来演示问题的 main()。基本上,一旦设置了 UI 并启动了事件循环,我就无法更新 UI 中显示的信息。鉴于在我启动事件循环之前 UI 不会显示,这是一个问题。
let mut siv = cursive::default();
siv.add_layer(ConsoleView::default().with_name("view_name"));
siv.add_global_callback(Key::Esc,|s| s.quit());
siv.run();
siv.call_on_name("view_name",|view: &mut ConsoleView| {
view.print("I should see this text in the app.");
});
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)