admin管理员组文章数量:1297129
I use iced_0.13.1 to build up my app and want to realize a draggable item.
A minimal(ish) reproduceable example:
use iced::{
advanced::{image, mouse},
widget::{
canvas::{self, Geometry, Program},
column, mouse_area, Canvas,
},
Color, Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector,
};
use iced::Task as Command;
fn main() -> iced::Result {
iced::application("A draggable picture", MyApp::update, MyApp::view)
.run()
}
impl Default for MyApp {
fn default() -> Self {
MyApp::new().0
}
}
#[derive(Debug, Clone)]
enum Message {
DragStarted(),
DragEnded(),
}
struct MyApp {
is_dragging: bool,
image_size: Size,
}
impl MyApp {
fn new() -> (Self, Command<Message>) {
(
Self {
is_dragging: false,
image_size: Size {
width: 300.,
height: 200.,
},
},
Command::none(),
)
}
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::DragStarted() => {
self.is_dragging = true;
}
Message::DragEnded() => {
self.is_dragging = false;
}
}
Command::none()
}
fn view(&self) -> Element<Message> {
let draggable_image = mouse_area(
Canvas::new(DraggableImage::new(Rectangle::with_size(self.image_size)))
.width(self.image_size.width)
.height(self.image_size.height),
)
.on_press(Message::DragStarted())
.on_release(Message::DragEnded());
column![
draggable_image,
]
.height(Length::Fill)
.width(Length::Fill)
.into()
}
}
struct DraggableImage {
cache: canvas::Cache,
image: image::Handle,
image_size: Rectangle,
}
impl DraggableImage {
fn new(image_size: Rectangle) -> Self {
Self {
cache: canvas::Cache::default(),
image: image::Handle::from_bytes(include_bytes!("../ferris.png").as_slice()),
image_size,
}
}
}
impl<Message> Program<Message> for DraggableImage {
type State = ();
fn draw(
&self,
_state: &Self::State,
renderer: &Renderer,
_theme: &Theme,
bounds: iced::Rectangle,
_cursor: iced::advanced::mouse::Cursor,
) -> Vec<Geometry<Renderer>> {
let pic = self.cache.draw(renderer, bounds.size(), |frame| {
frame.with_save(|frame| {
//? Uncomment it to visualize the bounds.
// frame.fill_rectangle(Point::ORIGIN, frame.size(), Color::BLACK);
// Move the picture.
frame.translate(Vector::new(300., 200.));
frame.fill_rectangle(Point::ORIGIN, frame.size(), Color::BLACK);
// Finally, render the image.
frame.draw_image(self.image_size, &self.image);
});
});
vec![pic]
}
fn mouse_interaction(
&self,
_state: &Self::State,
bounds: iced::Rectangle,
cursor: iced::advanced::mouse::Cursor,
) -> iced::advanced::mouse::Interaction {
if cursor.is_over(bounds) {
mouse::Interaction::Pointer
} else {
mouse::Interaction::Idle
}
}
}
While iced doesn't provide a method like pub fn position(self, Point) -> Element<'a, Message, Theme, Renderer>
(if that, I could use subscription to handle it), I have tried to customize a canvas item and then move it manually.
frame.translate(Vector::new(300., 200.));
However, the mouse_interaction
, on_press
, on_release
are still bound to the bounds
of DraggableImage
at top-left corner, not the picture itself.
So, how to realize a method manually to move canvas (such as a pressable circle, not just a shape) or widgets (such as a button) manually.
horizontal_space().height(Length::FillPortion())
or vertical_space().width(Length::FillPortion())
might not be a good option, either.
本文标签: user interfaceHow to create draggable widgets in iced013xStack Overflow
版权声明:本文标题:user interface - How to create draggable widgets in iced-0.13.x - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741625428a2389053.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论