Hello,
currently I am working on a GUI based on native_windows_gui and native_windows_derive. The GUI has two buttons and a textfield. If the start button is clicked, two threads(start_threads) should write "Lorem" in the textfield. At the moment the gui prints the text in the console. Up to now I am not able to write a text from the two threads in this textfield.
Executing
self.text_box.set_text("Lorem");
in the thread is not possible
I have also tried to protect the textfield with Arc(Mutex), but then I get the errors "*mut winapi::shared::windef::HWND__
cannot be shared between threads safely" and "*mut winapi::shared::windef::HMENU__
cannot be shared between threads safely":
let text_box=Arc::new(Mutex::new(&self.text_box));
at the beginning of the method start_thread and
text_box.lock().unwrap().set_text("LOREM");"
one line above the sleep-command.
Any hints what I am doing wrong? Or is it not possible? I have to admit, that I am quit new in Rust.
Cargo.toml
[package]
name = "gui"
version = "0.1.0"
edition = "2024"
[dependencies]
native-windows-gui = "1.0.12"
native-windows-derive = "1.0.3"
rand = "0.8"
chrono = "0.4"
main.rs
use native_windows_gui as nwg;
use native_windows_derive::NwgUi;
use std::{sync::{Arc, Mutex, mpsc}, thread, time::Duration};
use std::sync::MutexGuard;
use rand::{thread_rng, Rng};
use crate::nwg::NativeUi;
use chrono::Local;
use native_windows_gui::TextBox;
#[derive(NwgUi)]
pub struct GitBackup {
sender: mpsc::Sender<String>,
receiver: Arc<Mutex<mpsc::Receiver<String>>>,
#[nwg_control(size: (300, 200), title: "GIT Backup", flags: "WINDOW|VISIBLE|MINIMIZE_BOX")]
#[nwg_events( OnWindowClose: [GitBackup::exit], OnWindowMinimize: [GitBackup::minimize] )]
window: nwg::Window,
#[nwg_control(parent: window, text: "Starten", position: (20, 20), size: (120, 40))]
#[nwg_events( OnButtonClick: [GitBackup::start_threads] )]
start_button: nwg::Button,
#[nwg_control(parent: window, text: "Stoppen", position: (160, 20), size: (120, 40))]
#[nwg_events( OnButtonClick: [GitBackup::stop_threads] )]
stop_button: nwg::Button,
#[nwg_control(parent: window, position: (20, 80), size: (260, 40), text: "", flags: "VISIBLE|VSCROLL|AUTOVSCROLL", readonly: true)]
text_box: nwg::TextBox,
#[nwg_control(parent: window, icon: Some(&data.icon), tip: Some("Rust GUI"))]
#[nwg_events( MousePressLeftUp: [GitBackup::restore] )]
tray: nwg::TrayNotification,
#[nwg_resource(source_file: Some("icon.ico"))]
icon: nwg::Icon,
#[nwg_resource]
font: nwg::Font,
threads: Arc<Mutex<Vec<thread::JoinHandle<()>>>>,
stop_signal: Arc<Mutex<bool>>,
}
impl Default for GitBackup
{
//TODO!!
fn default() -> Self
{
let (sender, receiver) = mpsc::channel();
Self{
text_box: nwg::TextBox::default(),
tray:Default::default(),
icon:Default::default(),
stop_button:Default::default(),
start_button:Default::default(),
window:Default::default(),
font:Default::default(),
threads:Default::default(),
sender,
receiver:Arc::new(Mutex::new(receiver)),
stop_signal:Default::default()
}
}
}
impl GitBackup {
fn start_threads(&self) {
let stop_signal = Arc::clone(&self.stop_signal);
*stop_signal.lock().unwrap() = false;
for _ in 0..2
{
let stop_signal = Arc::clone(&stop_signal);
let handle = thread::spawn( move || {
//If stop_signal==true -> die!!
while !*stop_signal.lock().unwrap() {
println!("Lorem");
thread::sleep(Duration::from_millis(1500));
}
});
}
}
fn stop_threads(&self) {
*self.stop_signal.lock().unwrap() = true;
let mut threads = self.threads.lock().unwrap();
threads.clear();
}
fn minimize(&self) {
self.window.set_visible(false);
let flags = nwg::TrayNotificationFlags::USER_ICON | nwg::TrayNotificationFlags::LARGE_ICON;
self.tray.show("",Some("Blabla"),Some(flags), Some(&self.icon));
}
fn restore(&self) {
self.window.set_visible(true);
self.tray.set_visibility(false);
}
fn exit(&self) {
self.stop_threads();
nwg::stop_thread_dispatch();
}
}
fn main() {
nwg::init().expect("Failed to init Native Windows GUI");
nwg::Font::set_global_family("Segoe UI").expect("Failed to set default font");
let _app = GitBackup::build_ui(Default::default()).expect("Failed to build UI");
nwg::dispatch_thread_events();
}