简体   繁体   中英

How do I fix my compatability errors when using plotters::CairoBackend with GTK

I am trying to draw an image on a very basic GUI. I am using GTK for the GUI and want to use the plotters crate for the drawing but am having issues initiating the Backend that plotters uses.

I have successfully managed to use the BitMapBackend to draw to a file - there is no shortage of examples on the inte.net for this. However, I cannot for the life of me find an example of how to use the CairoBackend to draw onto a gtk DrawingArea.

My issue arises when I try to connect the draw event to the GTK DrawingArea. I use the connect_draw method which works as expected returning a context to pass to the CairoBackEnd. The problem is that the type of context returned by connect_draw is not compatible with the type of context required by the CairoBackend. I receive context of type 'gtk::cairo::Context' (defined in cairo-rs v0.16.7) but the backend requires a context of 'cairo::context:Context' (defined in cairo-rs v0.15.12). Clearly my dependencies are using different versions of the cairo-rs crate. Presumably, the versions of my dependencies are not compatible with each other. How can I fix this? How do I find out what version of each dependency will work with the others? My cargo.toml file contains:

[package]
name = "testing3"
version = "0.1.0"
edition = "2021"

[dependencies]
gtk = "0.16.2"
plotters = "0.3.4"
plotters-cairo = "0.3.2"

My rust code is:

use gtk::prelude::*;
use plotters::prelude::*;
use gtk::{Application, ApplicationWindow};

fn main() {
    let app = Application::builder().build();
    
    app.connect_activate(build_gui);
    app.run();
}

fn build_gui(app: &Application){
    let win = ApplicationWindow::builder().application(app).default_width(320).default_height(200).title("Test").build();
    let da: gtk::DrawingArea = gtk::DrawingArea::builder().build();
    
    da.connect_draw(move|_, c|{
            let root = plotters_cairo::CairoBackend::new(c, (1024, 768)).unwrap().into_drawing_area();
            gtk::Inhibit(false)
        });
    win.add(&da);
    win.show_all();
}

my error message is:

  --> src/main.rs:21:49
   |
21 |             let root = plotters_cairo::CairoBackend::new(c, (1024, 768)).unwrap().into_drawing_area();
   |                        --------------------------------- ^ expected struct `cairo::context::Context`, found struct `gtk::cairo::Context`
   |                        |
   |                        arguments to this function are incorrect
   |
   = note: struct `gtk::cairo::Context` and struct `cairo::context::Context` have similar names, but are actually distinct types
note: struct `gtk::cairo::Context` is defined in crate `cairo`
  --> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/cairo-rs-0.16.7/src/context.rs:72:1
   |
72 | pub struct Context(ptr::NonNull<cairo_t>);
   | ^^^^^^^^^^^^^^^^^^
note: struct `cairo::context::Context` is defined in crate `cairo`
  --> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/cairo-rs-0.15.12/src/context.rs:72:1
   |
72 | pub struct Context(ptr::NonNull<cairo_t>);
   | ^^^^^^^^^^^^^^^^^^
   = note: perhaps two different versions of crate `cairo` are being used?
note: associated function defined here
  --> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-cairo-0.3.2/src/backend.rs:70:12
   |
70 |     pub fn new(context: &'a CairoContext, (w, h): (u32, u32)) -> Result<Self, CairoError> {
   |            ^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `testing3` due to previous error


------------------
(program exited with code: 101)

So with more digging around I have found the solution.

As I identified from the error message, my code had a compatibility problem. The gtk v0.16.2 dependency in my toml file depended itself on cairo-rs v0.16.7 where as the plotters-cairo v0.3.2 depended on cairo-rs v15.12. Clearly, I had to use an earlier version of the gtk dependency - one that depended on cairo-rs v15.12. But which one.

On the Doc.rs website I could find the gtk crate documents on https://docs.rs/gtk/0.6.0/gtk/ . A tab on top left, gtk-0.6.0, on being selected provided both dependency data and versioning options. I could see that the latest version of the gtk crate did indeed depend on cairo-rs 0.6.0. Selecting the various versions I was able to find the latest version that still depended on cairo-rs v15.xx. In this case it was gtk v0.15.5. Once I replaced my gtk dependency with that version, all was good. So my new toml was:

[package]
name = "testing3"
version = "0.1.0"
edition = "2021"

[dependencies]
gtk = "0.15.5"
plotters = "0.3.4"
plotters-cairo = "0.3.2"

Now by adding the code:

c.rectangle(10.0, 10.0, 70.0, 70.0);
c.fill().expect("Drawing failed");
root.fill(&RED).unwrap();

above my gtk::Inhibit(false) statement, I could indeed create a red rectangle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM