'Tui-rs: flickering when drawing multiple widgets

Good evening!

I'm trying to write a very simple terminal application that draws two textboxes on screen, accepting input on one and showing output on the other, using Rust and tui-rs. The first part works perfectly, but my problems arose when i tried to draw two blocks at the same time: for some reason, it only shows the second block (in order of drawing) and if i move my mouse, it flickers between the two in a weird way. My best guess is that this is due to my drawing implementation, which somehow "clears" the screen whenever it needs to draw something, but if that's the case, i couldn't find any doc on it, and i wouldn't know how to go about working around this. I've provided some code that should be enough to replicate the issue on a smaller scale.

#![allow(unused_imports)]
#![allow(unused_variables)]

use crossterm::{
    event::{self, DisableMouseCapture, EnableMouseCapture, Event},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use std::io
use tui::{
    backend::CrosstermBackend,
    layout::Rect,
    widgets::{Block, Borders},
    Terminal,
};

struct FirstStruct {}

impl FirstStruct {
    pub fn draw(&self, term: &mut Terminal<CrosstermBackend<io::Stdout>>) -> io::Result<()> {
        term.draw(|f| {
            let size = f.size();
            let (w, h) = (size.width / 2, size.height);
            let (x, y) = (size.x, size.y);
            let rect = Rect::new(x, y, w, h);
            let block = Block::default()
                .title("One")
                .borders(Borders::ALL);
            
            f.render_widget(block, rect)
        })?;

        Ok(())
    }
}

struct SecondStruct {  }

impl SecondStruct {
    pub fn draw(&self, term: &mut Terminal<CrosstermBackend<io::Stdout>>) -> io::Result<()> {
        term.draw(|f| {
            let size = f.size();
            let (w, h) = (size.width / 2, size.height);
            let (x, y) = (size.x + w, size.y);
            let rect = Rect::new(x, y, w, h);
            let block = Block::default()
                .title("Two")
                .borders(Borders::ALL);
            
            f.render_widget(block, rect)
        })?;
        Ok(())
    }
}

fn main() -> io::Result<()>{
    enable_raw_mode()?;
    let mut stdout = io::stdout();
    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    let first = FirstStruct {};
    let second = SecondStruct {};
    let mut running = true; 

    while running {
        if let Event::Key(key) = event::read()? {
            running = false;
        }
        second.draw(&mut terminal)?;
        first.draw(&mut terminal)?;
    }

    disable_raw_mode()?;
    execute!(
        terminal.backend_mut(),
        LeaveAlternateScreen,
        DisableMouseCapture
    )?;
    terminal.show_cursor()?;

    Ok(())
}

Does anybody know how i can fix this issue? Thanks in advance!!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source