Rust GUI库Slint初探(二):在.slint和.rs文件间使用回调函数
在上一篇中,我们为GUI窗口实现了一些简单的功能:
Rust GUI库Slint初探(一):编写.slint文件,改变图标和标题栏
但还并没有使用回调函数在slint文件和rs文件中进行交互。
这一次我们来实现一下。
在main.rs中编写回调函数内容
首先我们修改我们的main.slint文件,在MainWindow的定义中,首先将上一次自定义的属性property <int> count:0;
前增添in
关键字。这表示这一自定义属性的值由外部更新。如果使用out
关键字则表示该自定义属性的值由组件内部更新,外部可读。如果关键字为in-out
则表示其读写权限完全公开。然后我们再定义一个回调函数,使用:callback button_clicked;
。之后我们再于button的clicked=>{}
方法中,填入root.button-clicked();
。其中root表示该button控件的父级控件。于是button能够调用MainWindow中我们定义的名为button_clicked的回调函数。这里留意到,我们再定义该回调函数时使用的名字为button_clicked,而给button调用时使用的名字为button-clicked。这是因为在slint语言中,_与-是通用的,可以互换使用。
于是,mian.slint文件现在为:
import { Button } from "std-widgets.slint";
export component MainWindow inherits Window {
in property <int> count:0;
callback button_clicked;
height: 600px;
width: 800px;
title: "小试牛刀";
icon: @image-url("icon.png");
VerticalLayout {
height: 300px;
width: 400px;
Text {
font-size: 30px;
text: "你好世界";
color: green;
}
Text {
font-size: 30px;
text: "Hello World!";
color: green;
}
Button {
text:"点击试试";
height: 50px;
width: 150px;
clicked=>{root.button-clicked();}
}
Text {
font-size: 30px;
text: "Pressed:"+count;
color: orange;
}
}
}
接下来我们可以修改main.rs文件了:
slint::include_modules!();
fn main() {
let main_window=MainWindow::new().unwrap();
let weak=main_window.as_weak();
main_window.on_button_clicked(move||{
let res=weak.upgrade().unwrap();
res.set_count(res.get_count()+1);
});
main_window.run().unwrap();
}
我们将新建的MainWindow赋值给一个main_window变量,并取它的弱引用,才方便在后续的闭包中进行可变引用的操作。调用main_window变量的on_button_clicked()方法,其中button_clicked为我们在slint文件中定义的回调函数名称。给on_button_clicked()传递一个闭包,该闭包则是回调函数会执行的具体代码实现。使用move取得weak的所有权并upgrade()后赋给res变量。于是可以借助res变量对MainWindow进行操作,改变其count属性的值。
编译运行后,发现和前面在slint单文件中实现的逻辑是一模一样的。
在.slint中,我们定义callback的时候也可以写为callback button_clicked<=>btn.clicked;
,然后在定义Button组件时写为:
btn:=Button {
text:"点击试试";
height: 50px;
width: 150px;
}
其中定义Button组件时使用btn:=表示给该组件取了一个名字为btn。定义callback时,使用<=>表示button_clicked这个回调等价于btn组件的clicked方法。这样改写也可以达到和前述代码完全一样的效果。
slint中的按键响应与条件判断
在slint文件中,MainWindow的定义内,新增一个FocusScope组件。该组件表示其父组件获得关注时生效。由于是在MainWindow内定义,所以只要我们的主窗口是激活状态,FocusScope组件就可以一直生效。FocusScope组件内具有key-pressed和key-released函数可以定义。定义FocuseScope及key-pressed函数如下:
FocusScope {
key-pressed(k) => {
root.button-clicked();
accept
}
}
这样在触发key-pressed事件后,执行MainWindow的button-clicked回调。key-pressed函数需要一个返回值,返回值是一个枚举。所以最后我们写入accept作为返回值。
现在我们编译运行后发现,除了点击界面中的按钮,能够增加计数以外,按下键盘上的任意键,都可以增加计数。
接下来我们想要判断按下的按键是我们想要的,才触发事件。例如按下“F”建,才触发事件,则将上述代码改写为:
FocusScope {
key-pressed(k) => {
if(k.text=="f"){root.button-clicked();}
accept
}
}
如果我们想要指定组合按键响应事件,如“Ctrl+F”,则改写代码如下:
FocusScope {
key-pressed(k) => {
if(k.modifiers.control&&k.text=="f"){
root.button-clicked();
};
accept
}
}
编译运行,可以验证现在键盘按下我们指定的组合键后,计数才会增加了。
接下来我们试试用组合快捷键改变界面颜色,修改代码如下:
FocusScope {
key-pressed(k) => {
if(k.modifiers.control&&k.text=="f"){
root.button-clicked();
};
if(k.modifiers.control&&k.text=="b"){
root.background=@linear-gradient(45deg,white 0%,blue 100%);
};
if(k.modifiers.control&&k.text=="r"){
root.background=@radial-gradient(circle, red 0%,white 100%)
};
accept
}
}
该段代码增加了按下“Ctrl+B”和“Ctrl+R”的功能:
按下“Ctrl+B”时,效果为调整MainWindow的背景为渐变蓝色,使用45°的线性渐变色。
按下“Ctrl+R”时,效果为调整MainWindow的背景为渐变红色,使用环状的渐变色。
此时编译运行代码,使用快捷键改变界面效果如下:
至此,我们就实现了基本的回调函数使用,以及使用回调函数在slint文件和rs文件中进行交互。同时熟悉了slint文件中的if语句以及按键事件的使用。其实slint文件中还能使用for循环实现更为复杂的功能。下一次我们将去熟悉它。