-
Hi, I would like to have an element that can be panned by dragging like a Flickable, while also having scroll bars like a ScrollView. My use case is an image viewer, which I would like to pan by dragging with the mouse, with the scroll wheel, or by dragging the scroll bars (I would also like to zoom, so this is another vote for #1280 and #680). Here is my attempt at manually tracking the dragging: import { ScrollView } from "std-widgets.slint";
// this is whatever I would put inside the ScrollView (i.e. an image)
component InnerContent inherits Rectangle {
width: 600px; height: 600px;
// so that we see where we are
Rectangle {
width: 100px; height: 100px;
background: green;
}
}
export component MainWindow inherits Window {
preferred-width: 400px;
preferred-height: 400px;
scroll := ScrollView {
HorizontalLayout {
InnerContent {
background: touch.pressed ? gray : black; // just to show mouse clicks
touch := TouchArea {
property<length> drag-start-x;
property<length> drag-start-y;
pointer-event(e) => {
if (e.kind == PointerEventKind.down
&& e.button == PointerEventButton.left) {
self.drag-start-x = scroll.viewport-x;
self.drag-start-y = scroll.viewport-y;
}
}
moved => {
scroll.viewport-x = self.drag-start-x + (self.mouse-x - self.pressed-x);
scroll.viewport-y = self.drag-start-y + (self.mouse-y - self.pressed-y);
}
}
}
}
}
} However, this is buggy, the viewport jitters while dragging: slint-drag.2023-02-14.20-21.mp4I guess this happens because two elements are fighting over setting the viewport position? I tried to implement something like the solution in #343 (comment), but it had the same jittering problem. I also tried to do it by calculating the delta: touch := TouchArea {
property<length> mouse-prev-x;
property<length> mouse-prev-y;
pointer-event(e) => {
if (e.kind == PointerEventKind.down
&& e.button == PointerEventButton.left) {
self.mouse-prev-x = self.mouse-x;
self.mouse-prev-y = self.mouse-y;
}
}
moved => {
scroll.viewport-x += self.mouse-x - self.mouse-prev-x;
scroll.viewport-y += self.mouse-y - self.mouse-prev-y;
self.mouse-prev-x = self.mouse-x;
self.mouse-prev-y = self.mouse-y;
}
} but it didn't help either. I'm probably doing something wrong. How could I make this work? Another option would be to use a Flickable instead of the ScrollView, and re-implement the scrollbars myself, but that feels quite hacky, and it would require a lot of effort to be consistent with the styling and so on. I couldn't see a separate widget for the scrollbars in the std. I see that ScrollView has a Flickable inside it, with |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
Yes, this is tricky because the TouchArea itself is moving. Have you tried this:
Looks like it works
Yes, that is a good point. We could forward that property. But |
Beta Was this translation helpful? Give feedback.
Yes, this is tricky because the TouchArea itself is moving.
But you can also take that to your adventage and you don't need the state.
Have you tried this:
Looks like it works
Yes, that is a good point. We could forward that property. But
interactive
would not be the right name for that property bec…