Rust-Qt : Implementation of Signals and Slots for QThread

Hi,

i am trying to implement a multithreaded QT5 GUI, but it seems that i some issues using the connection between signals and slots. It's working perfectly in C++.

I create a worker thread (worker1) that generate a integer and should pass it through an argument (emit) to the main GUI:

The code looks like this :

#![windows_subsystem = "windows"]

// Includes /////////////////////////////////////
use cpp_core::{Ptr, Ref, StaticUpcast};
use qt_core::{qs, slot, QBox, QObject, Signal, SlotNoArgs, SlotOfI64, SignalOfI64, QString, QThread, QVariant};
use qt_widgets::{QApplication, QLineEdit, QPushButton,QVBoxLayout, QWidget,};
use std::rc::Rc;
use std::{time, thread};

// Worker definition ////////////////////////////
struct Worker1 {
    widget: QBox<QObject>,
    val:    QBox<SignalOfI64>
}

impl StaticUpcast<QObject> for Worker1 {
    unsafe fn static_upcast(ptr: Ptr<Self>) -> Ptr<QObject> {
        ptr.widget.as_ptr().static_upcast()
    }
}

impl Worker1 {
    fn new() -> Rc<Worker1> {
        unsafe {
            let widget = QObject::new_0a();
            let val = SignalOfI64::new();

            let this = Rc::new(Self {
                widget, val,
            });
        this
        }
    }

    // #[signal(SignalOfI64)]
    unsafe fn update_val(self: &Rc<Self>, val: QBox<SignalOfI64>) {}

    #[slot(SlotNoArgs)]
    unsafe fn do_work(self: &Rc<Self>) {
        // let t = time::Duration::from_millis(10);
        // do work here
        for i in 0..100 {
            self.val.emit(i);
            // self.update_val(&val).SignalOfI64.emit();
        }
    }
} // end impl worker1


// QT5 GUI definition////////////////////////////

struct Form {
    widget:      QBox<QWidget>,
    line_edit:   QBox<QLineEdit>,
    startbutton: QBox<QPushButton>,
    stopbutton:  QBox<QPushButton>,
}

impl StaticUpcast<QObject> for Form {
    unsafe fn static_upcast(ptr: Ptr<Self>) -> Ptr<QObject> {
        ptr.widget.as_ptr().static_upcast()
    }
}

impl Form {
    fn new() -> Rc<Form> {
        unsafe {
            let widget = QWidget::new_0a();
            let layout = QVBoxLayout::new_1a(&widget);

            let line_edit = QLineEdit::new();
            layout.add_widget(&line_edit);

            let startbutton = QPushButton::from_q_string(&qs("Start"));
            startbutton.set_enabled(true);
            layout.add_widget(&startbutton);

            let stopbutton = QPushButton::from_q_string(&qs("Stop"));
            stopbutton.set_enabled(false);
            layout.add_widget(&stopbutton);

            widget.show();

            let this = Rc::new(Self {
                widget, startbutton, stopbutton, line_edit,
            });
            this.init();
            this
        }
    }

    unsafe fn init(self: &Rc<Self>) {
        self.startbutton.clicked().connect(&self.slot_on_startbutton_clicked());
    }

    #[slot(SlotOfI64)]
    unsafe fn updateval(self: &Rc<Self>, val: Ref<i64>) {
        self.line_edit.set_text(&qs(val.to_string()));
    }

    #[slot(SlotNoArgs)]
    unsafe fn on_startbutton_clicked(self: &Rc<Self>) {

        self.stopbutton.set_enabled(true);

        // Create Thread & Workers
        let thread1 = QThread::new_0a();
        let worker1 = Worker1::new();

        // Connect signals to slots
        worker1.move_to_thread(thread1);
        thread1.started().connect(worker1.do_work());
        worker1.update_val().connect(self.updateval());
        self.stopbutton.clicked().connect(thread1.finished());
        thread1.start_0a();
    }
}

// Main Definition///////////////////////////////
fn main() {
    QApplication::init(|_| unsafe {
        let _form = Form::new();
        QApplication::exec()
    })
}
 

Any help would be be very appreciated. Don't be too hard with me it's my first utilisation of Qthread with Rust.

Than you in advance !

Best Regards.
Olivier.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.