6 个版本
0.1.6 | 2023 年 7 月 30 日 |
---|---|
0.1.5 | 2023 年 7 月 29 日 |
#1203 in GUI
每月 43 次下载
17KB
184 代码行
qt-cb
此包提供了一些 traits,这些 traits 定义了方便的方法来为 qt_widgets 类型。这些方法的形式为 connect_<signal>
,它接受一个闭包。闭包的参数是触发信号的控件,以及信号的参数。如果你熟悉 Gtk-rs api,这应该对你来说也很熟悉。
本质上,它实例化了必要的 Slot,并直接将闭包传递给它。它还将控件本身传递到闭包中,因此你可以在闭包中访问控件。
即它给你
checkbox.connect_clicked(|checkbox, checked| {
// access checkbox
// handle signal argument checked
});
而不是
checkbox.clicked().connect(&SlotOfBool::new({
let checkbox = checkbox.as_ptr();
move |checked| {
// access checkbox
// handle signal argument checked
}
}));
或者
struct SomeStruct {
checkbox: QBox<QCheckBox>,
}
impl StaticUpcast<QObject> for SomeStruct {
// snipped
}
impl SomeStruct {
unsafe fn init(self: &Rc<Self>) {
self.checkbox.clicked().connect(&self.slot_on_checkbox_clicked());
}
#[slot(SlotOfBool)]
unsafe fn connect_checkbox_clicked(self: &Rc<Self>, checked: bool) {
// access self.checkbox
// handle signal argument checked
}
}
要求
此包具有与 rust-qt 相同的要求。
用法
[dependencies]
qt-cb = "0.1.0"
# other rust-qt packages
qt_core = "0.5.0"
qt_widgets = "0.5.0"
# other deps
在你的 Rust 源代码中,use qt_cb::prelude::*;
use qt_cb::prelude::*;
use qt_core::qs;
use qt_widgets::{
QApplication, QCheckBox, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, QWidget,
};
fn main() {
QApplication::init(|_| unsafe {
QApplication::set_style_q_string(&qs("Fusion"));
let win = QWidget::new_0a();
win.set_fixed_size_2a(400, 300);
let vbox = QVBoxLayout::new_1a(&win);
let ed = QLineEdit::new();
ed.set_placeholder_text(&qs("Enter name"));
ed.connect_text_changed(|_ed, txt| {
println!("current lineedit text: {}", txt.to_std_string());
});
vbox.add_widget(&ed);
let hbox = QHBoxLayout::new_0a();
vbox.add_layout_1a(&hbox);
let checkbox = QCheckBox::new();
hbox.add_widget(&checkbox);
checkbox.set_text(&qs("Check me!"));
checkbox.connect_clicked(|b, checked| {
println!(
"{} is {}checked",
b.text().to_std_string(),
if checked { "" } else { "un" }
);
});
let button = QPushButton::new();
hbox.add_widget(&button);
button.set_text(&qs("Greet!"));
button.connect_pressed(move |_b| {
println!("Hello {}", ed.text().to_std_string());
});
win.show();
QApplication::exec()
})
}
理由
定义 slots,尤其是在 Rust 端,可能会很冗长。你可能只需要快速调试某事或向控件添加一些简单的功能,而不必通过定义 slots 的仪式。在 rust-qt 中定义 slots 有两种主要方法,简要介绍如下:(以下程序与 README 中的第一个程序执行相同的操作,该程序使用此包)
1- 使用 slot 宏,这需要定义一个类型,该类型也实现了 StaticUpcast<QObject>
use cpp_core::{Ptr, Ref, StaticUpcast};
use qt_core::{qs, slot, QBox, QObject, QString, SlotNoArgs, SlotOfBool, SlotOfQString};
use qt_widgets::{
QApplication, QCheckBox, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, QWidget,
};
use std::rc::Rc;
struct Form {
win: QBox<QWidget>,
ed: QBox<QLineEdit>,
checkbox: QBox<QCheckBox>,
button: QBox<QPushButton>,
}
impl StaticUpcast<QObject> for Form {
unsafe fn static_upcast(ptr: Ptr<Self>) -> Ptr<QObject> {
ptr.win.as_ptr().static_upcast()
}
}
impl Form {
fn new() -> Rc<Form> {
unsafe {
let win = QWidget::new_0a();
win.set_fixed_size_2a(400, 300);
let vbox = QVBoxLayout::new_1a(&win);
let ed = QLineEdit::new();
ed.set_placeholder_text(&qs("Enter name"));
vbox.add_widget(&ed);
let hbox = QHBoxLayout::new_0a();
vbox.add_layout_1a(&hbox);
let checkbox = QCheckBox::new();
hbox.add_widget(&checkbox);
checkbox.set_text(&qs("Check me!"));
let button = QPushButton::new();
hbox.add_widget(&button);
button.set_text(&qs("Greet!"));
win.show();
let this = Rc::new(Self {
win,
ed,
checkbox,
button,
});
this.init();
this
}
}
unsafe fn init(self: &Rc<Self>) {
self.ed
.text_changed()
.connect(&self.slot_on_lineedit_text_changed());
self.button
.pressed()
.connect(&self.slot_on_button_pressed());
self.checkbox
.clicked()
.connect(&self.slot_on_checkbox_clicked());
}
#[slot(SlotNoArgs)]
unsafe fn on_button_pressed(self: &Rc<Self>) {
println!("Hello {}", self.ed.text().to_std_string());
}
#[slot(SlotOfBool)]
unsafe fn on_checkbox_clicked(self: &Rc<Self>, checked: bool) {
println!(
"{} is {}checked",
self.checkbox.text().to_std_string(),
if checked { "" } else { "un" }
);
}
#[slot(SlotOfQString)]
unsafe fn on_lineedit_text_changed(self: &Rc<Self>, txt: Ref<QString>) {
println!("current lineedit text: {}", txt.to_std_string());
}
}
fn main() {
QApplication::init(|_| unsafe {
let _form = Form::new();
QApplication::exec()
})
}
2- 定义 slots 的第二种方法,是实例化与信号提供的参数相对应的 Slot 对象,即 SlotOfBool,SlotOfQString 等。闭包不暴露控件在参数中,因此需要手动捕获(可以使用 Rc 智能指针或获取 Ptr<Widget>
)
use qt_core::{qs, SlotNoArgs, SlotOfBool, SlotOfQString};
use qt_widgets::{
QApplication, QCheckBox, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, QWidget,
};
fn main() {
QApplication::init(|_| unsafe {
QApplication::set_style_q_string(&qs("Fusion"));
let win = QWidget::new_0a();
win.set_fixed_size_2a(400, 300);
let vbox = QVBoxLayout::new_1a(&win);
let ed = QLineEdit::new();
ed.set_placeholder_text(&qs("Enter name"));
ed.text_changed().connect(&SlotOfQString::new(&ed, |txt| {
println!("current lineedit text: {}", txt.to_std_string());
}));
vbox.add_widget(&ed);
let hbox = QHBoxLayout::new_0a();
vbox.add_layout_1a(&hbox);
let checkbox = QCheckBox::new();
hbox.add_widget(&checkbox);
checkbox.set_text(&qs("Check me!"));
checkbox.clicked().connect(&SlotOfBool::new(&checkbox, {
let checkbox = checkbox.as_ptr();
move |checked| {
println!(
"{} is {}checked",
checkbox.text().to_std_string(),
if checked { "" } else { "un" }
);
}
}));
let button = QPushButton::new();
hbox.add_widget(&button);
button.set_text(&qs("Greet!"));
button.pressed().connect(&SlotNoArgs::new(&button, move || {
println!("Hello {}", ed.text().to_std_string());
}));
win.show();
QApplication::exec()
})
}
依赖关系
~104MB
~816K SLoC