如何动态使用绘图仪SegmentValue?

问题描述 投票:0回答:1

我有一个结构

Band

pub struct Band{
    pub name: String,
    pub start_dt: NaiveDateTime, 
    pub end_dt: NaiveDateTime, 
    pub stage: String,
    pub selected: bool,
}

我正在使用 plotters 板条箱进行绘图。 我有一个由

Band
对象组成的向量,想要绘制矩形。我的绘图图表的 y 轴上有
DateTime
,x 轴上有阶段名称的分段值:

let mut chart = ChartBuilder::on(&drawing_area)
    .caption(current_day, ("Arial", 30))
    .set_label_area_size(LabelAreaPosition::Left, 40)
    .set_label_area_size(LabelAreaPosition::Bottom, 60)
    // the x axis are the sages. we want the names centered
    // on an entry (i.e. it starts with half in front of a segment
    // and ends half after a segment, rather than matching segments 
    // exactle)
    // ----|---------------|-------------|-------
    //   main stage     t stage      wera stage 
    // for that behaviour, we need the into_segmented() command
    .build_cartesian_2d(stages.into_segmented(), first_utc..last_utc)
    .unwrap();

如何让我的整个向量绘制它们的矩形?无论我做什么,Rust 都会抱怨我使用了不正确的字符串,因此没有满足特征界限。我已经在这上面浪费了两个小时,而且不知道如何取得进展。


以下是我的一些尝试(不是按我尝试的顺序,但无论如何)。

  1. 具有单个元素向量的 For 循环
    for band in bands{
        let stage = band.stage.clone();
        chart.draw_series(vec![
            Rectangle::new(
                [
                    (SegmentValue::Exact(&stage), band.start_dt.and_utc()),
                    (SegmentValue::CenterOf(&stage), band.end_dt.and_utc())
                ],
                Into::<ShapeStyle>::into(BLACK)
            )
        ]).unwrap();
    }
|| the trait bound `for<'b> &'b  plotters::element::Rectangle<(plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>: PointCollection<'b, (plotters::prelude::SegmentValue<&&str>, DateTime<Utc>)>` is not satisfied 
||     | 
|| 97  |         chart.draw_series(vec![ 
||     |   ^^^^^^^^^^^ the trait `for<'b> PointCollection<'b, (plotters::prelude::SegmentValue<&&str>, DateTime<Utc>)>` is not implemented for `&'b plotters::element::Rectangle<(plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>` 
||     | 
||     = help: the trait `PointCollection<'_, (plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>` is implemented for `&plotters::element::Rectangle<(plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>` 
||     = help: for that trait implementation, expected `String`, found `&str` 
|| required by a bound in `ChartContext::<'a, DB, CT>::draw_series` 
||     | 
|| 120 |     pub fn draw_series<B, E, R, S>( 
||     |            ----------- required by a bound in this associated function 
|| ... 
|| 126 |         for<'b> &'b E: PointCollection<'b, CT::From, B>, 
||     |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ChartContext::<'a, DB, CT>::draw_series`
  1. 与 1 相同,但选择所需的字符串类型
    for band in bands{
        let stage = band.stage.clone();
        chart.draw_series(vec![
            Rectangle::new(
                [
                    (SegmentValue::Exact(&stage.as_str()), band.start_dt.and_utc()),
                    (SegmentValue::CenterOf(&band.stage.as_str()), band.end_dt.and_utc())
                ],
                Into::<ShapeStyle>::into(BLACK)
            )
        ]).unwrap();
    }

舞台的寿命不够

|| `stage` does not live long enough 
||     | 
|| 96  |         let stage = band.stage.clone(); 
||     |             ----- binding `stage` declared here 
|| 97  |         chart.draw_series(vec![ 
||     |  
||   
----- borrow later used here 
|| ... 
|| 100 |                     (SegmentValue::Exact(&stage.as_str()), band.start_dt.and_utc()), 
||    |                                           ^^^^^ borrowed value does not live long enough 
|| ... 
|| 106 |     } 
||     |     - `stage` dropped here while still borrowed 
|| temporary value dropped while borrowed 
||     | 
|| 97  |         chart.draw_series(vec![ 
||     |   
----- borrow later used here 
|| ... 
|| 100 |                     (SegmentValue::Exact(&stage.as_str()), band.start_dt.and_utc()), 
||    |                                           ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use 
|| ... 
|| 105 |      ]).unwrap(); 
||     |                    - temporary value is freed at the end of this statement 
||     | 
||     = note: consider using a `let` binding to create a longer lived value 
|| `band.stage` does not live long enough 
||     | 
|| 95  |     for band in bands{ 
||     |    
---- binding `band` declared here 
|| 96  |         let stage = band.stage.clone(); 
|| 97  |         chart.draw_series(vec![ 
||     | 
----- borrow later used here 
|| ... 
|| 101 |                     (SegmentValue::CenterOf(&band.stage.as_str()), band.end_dt.and_utc()) 
||     |                                              ^^^^^^^^^^ borrowed value does not live long enough 
|| ... 
|| 106 |     } 
||     |     - `band.stage` dropped here while still borrowed 
|| temporary value dropped while borrowed 
||     | 
|| 97  |         chart.draw_series(vec![ 
||     |         ----- borrow later used here 
|| ... 
|| 101 |                     (SegmentValue::CenterOf(&band.stage.as_str()), band.end_dt.and_utc()) 
||     |                                              ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use 
|| ... 
|| 105 |         ]).unwrap(); 
||     |            
- temporary value is freed at the end of this statement 
||     | 
||     = note: consider using a `let` binding to create a longer lived value
  1. 带向量的包围
    chart.draw_series(
        bands.iter().map(|band| {
            Rectangle::new(
                [((SegmentValue::Exact(&band.stage.as_str())).clone(), band.start_dt.and_utc()),
                    ((SegmentValue::CenterOf(&band.stage.as_str())).clone(), band.end_dt.and_utc())],
                Into::<ShapeStyle>::into(BLACK).filled()
            )
        })
    ).unwrap();

返回仍然引用临时值的值

|| cannot return value referencing temporary value 
||     | 
|| 99  | / Rectangle::new( 
|| 100 | |                 [((SegmentValue::Exact(&band.stage.as_str())).clone(), band.start_dt.and_utc()), 
|| 101  
|| | |                     ((SegmentValue::CenterOf(&band.stage.as_str())).clone(), band.end_dt.and_utc())], 
||     | |                                   
------------------- temporary value created here 
|| 102 | |                 Into::<ShapeStyle>::into(BLACK).filled() 
|| 103 | |             ) 
||   | |_____________^ returns a value referencing data owned by the current function 
|| cannot return value referencing temporary value 
|| | 
|| 99  | /             Rectangle::new( 
|| 100 | |                 [((SegmentValue::Exact(&band.stage.as_str())).clone(), band.start_dt.and_utc()), 
||     | |                                  
------------------- temporary value created here 
|| 101 | |                     ((SegmentValue::CenterOf(&band.stage.as_str())).clone(), band.end_dt.and_utc())], 
|| 102 | |                 Into::<ShapeStyle>::into(BLACK).filled() 
|| 103 | |             ) 
||   | |_____________^ returns a value referencing data owned by the current function

这个板条箱有一个(GitHub)论坛,你在其中得不到答案,否则我会在那里问......

string rust plot lifetime
1个回答
0
投票

我遇到的问题主要是关于输入数据。最初,为了测试我使用了

stages.into_segmented()' where 
stages
was an array of
&str` 元素:

let stages = [ 
    "Main Stage", 
    "T Stage", 
    "Wera Stage" 
];

因此,

into_segmented()
调用创建了
SegmentValue(&&str)
元素,但我仍然不知道如何解决此数据类型的问题。

但是,当我意识到这种数据类型有问题时,我将其更改为字符串向量:

let stages: Vec<String> = vec![ 
    String::from("Main Stage"), 
    String::from("T Stage"), 
    String::from("Wera Stage") 
];

有了这个,让

SegmentValue
接受我的动态输入就变得相当简单了。我现在可以从我的
stage
结构中借用
Band
字符串并完成它。使用闭包,它看起来像这样:

    // draw all bands into the chart
    chart.draw_series(
        bands.iter().map(|band| {

            Rectangle::new(
                [
                    (SegmentValue::Exact(&band.stage), band.start_dt.and_utc()),
                    (SegmentValue::CenterOf(&band.stage), band.end_dt.and_utc()),
                ],
                Into::<ShapeStyle>::into(BLACK).filled()
            )
        })
    ).unwrap();
© www.soinside.com 2019 - 2024. All rights reserved.