Zoom Flickable's content on wheel event - qml

By default, Flickable scrolls on mouse wheel event: horizontally if Shift modifier is pressed, and vertically if no modifier is active. I'd like to override this behaviour to make it zoom in/out.
I tried to use MouseArea as a child of Flickable. Defining desired behaviour inside onWheel handler I get what I want, but it breaks flicking feature. Motion of two touch points is recognised as a wheel event on my Mac, what prevents Flickable to steel this event (MouseArea.preventSteeling is false by default). So I get somewhat mixed zooming feature that respects velocity/acceleration behaviour of Flickable.

Add an onWheel handler underneath your MouseArea:
MouseArea
{
onWheel: {
if (wheel.modifiers & Qt.ControlModifier){
if (wheel.angleDelta.y > 0)
{
zoomin()
}
else
{
zoomout()
}
}
else{
wheel.accepted=false
}
}
}

Related

TextField Covered By Software Keyboard And Doesn't Scroll Into View

When using Compose with a TextField at the bottom of the screen, when I focus the TextField, the software keyboard is opening up and covering the TextField, and it is not scrolling the TextField into view.
I am using accompanist and have things set up so that it could scroll into view, but it is not doing it automatically.
I also found that if the keyboard is already open, and you focus a TextField that is scrolled off screen, it does automatically scroll it onto screen. So it sort of seems like the behavior is there, but it just isn't working correctly because the focus happens before the keyboard opens.
Does anyone have a good solution to make the TextField scroll into view when the software keyboard opens?
Edit:
Simple Example:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
setContent {
ProvideWindowInsets {
Column(
Modifier
.statusBarsPadding()
.navigationBarsWithImePadding()
.verticalScroll(rememberScrollState())
) {
val focusManager = LocalFocusManager.current
(0..20).forEach {
var test by remember { mutableStateOf("") }
TextField(
test,
{ test = it },
label = { Text(it.toString()) },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions(onNext = {
focusManager.moveFocus(FocusDirection.Next)
})
)
}
}
}
}
}
}
With the keyboard closed, if I click a TextField near the bottom, it gets focus, then the keyboard pops up and covers it. What I want to happen is after the keyboard pops up, the TextField should scroll into view.
However if I then hit the Next button on the keyboard, it will go to the next TextField and scroll it into view. Which is what I want.
I had a similiar issue. This seems to be a bug in Compose. To fix it, add the following in your activity's onCreate:
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

Qt QML Settings.hasTouchScreen returns false

I am trying to find out why flicking is not working with a TreeView example on my Raspberry Pi3 with touch screen.
Looking at the qml code of TreeView.qml, e.g.
https://github.com/RSATom/Qt/blob/master/qtquickcontrols/src/controls/TreeView.qml:
BasicTableView {
...
__mouseArea: MouseArea {
id: mouseArea
parent: __listView
width: __listView.width
height: __listView.height
z: -1
propagateComposedEvents: true
focus: true
// If there is not a touchscreen, keep the flickable from eating our mouse drags.
// If there is a touchscreen, flicking is possible, but selection can be done only by tapping, not by dragging.
preventStealing: !Settings.hasTouchScreen
...
}
}
By similarly looking at the qml code for BasicTableView.qml, it seems that behavior is controlled by Settings.hasTouchScreen.
According to:
https://code.woboq.org/qt5/qtquickcontrols/src/controls/Private/qquickcontrolsettings.cpp.html
it corresponds to the following method:
bool QQuickControlSettings1::hasTouchScreen() const
{
const auto devices = QTouchDevice::devices();
for (const QTouchDevice *dev : devices)
if (dev->type() == QTouchDevice::TouchScreen)
return true;
return false;
}
However, in my case, Settings.hasTouchScreen returns false; i.e. the touch screen (although working for the rest), is not
correctly detected by the QML environment, which probably explains why the flicking does not work.
According to https://doc.qt.io/qt-5/qtouchdevice.html, my touch device should have been registered somehow by the private QWindowSystemInterface::registerTouchDevice() method, but wasn't.
How can I get this to work?
Thanks!
It seems not to work correctly with tslib, but works by using the evdevtouch plugin which is enabled by adding the following command line arguments when launching the program:
-plugin evdevtouch:/dev/input/eventX
where eventX is the event assigned to the touch input.
With that, QTouchDevice::devices() is no longer empty, and the flicking of the TreeView works.

MouseArea in qml(onEntered, onExited, onReleased)

I have one button. I want to change the states of button e.g:
Default image is black.
onEntered i want image as blue, onExited i want image as black(equal to default state), and onReleased i want image as blue(equal to onEntered state).
Note:
onRelease should be active inside the button and outside the button onRelease shouldn't work.
How this can be achieved?
Mouse area looks like this:
MouseArea
{
anchors.fill: firstImage(parent)
onEntered:
{
firstImage.source = "blue.img"
}
onExited:
{
firstImage.source = "black.img"
}
onReleased:
{
firstImage.source = "blue.img"
}
}
Problem i am facing is:
onRelease is active outside the button.
I want onRelease to be active when press is released inside the button.
You can leverage the fact that you can give every object in qml an extra custom property.
I came up with the following, which seems to be what you ask, however, I see a flaw, because when you are 'entered' and press, the button will go to entered state, so there is not difference in the 'released' state, and after leaving the MouseArea it will again go to 'exited' state.
Note, I did not copy the firstImage.source stuff, but you can easily tailor this example to your situation
import QtQuick.Controls 2.4
Button {
hoverEnabled: true
property bool touched : false
onHoveredChanged: touched = hovered
onReleased: touched = true
text: touched ? "touched" : "not touched"
}
The hoverEnabled needs to be set

MouseArea in a Disabled QML element

I have a widget that is widely used in my QML Application, it's enabled property has been used in most of the places to change it's view and disable it's actions. Let's say it is something like this
Item {
MouseArea {
anchors.fill: parent
onClicked: doSomething();
}
}
Now the problem is that we need to show a message when the button is disabled, but MouseArea will also be disabled when the parent is disabled. Is there any workaround for this to force the child to remain enabled?
Actually, the mouse area enabled property works differently from typical Items. It's really not disabled, but seems that way because the parent item is not enabled and thus cannot accept certain mouse events. To solve your problem just make the MouseArea a sibling.

QML: ListView delegate: items vs. MouseArea

I have the following code:
ListView {
delegate: MyDelegate {
MouseArea {
anchors.fill: parent
/*some other stuff*/
}
}
}
The problem is that MyDelegate contains checkboxes and MouseArea "steals" mouse events from them. They do not react on mouse events at all, i.e. do not work as expected.
I know about propagateComposedEvents property of MouseArea...but I'll have to implement all of its mouse events (clicked, pressed, released,...) and check whether the mouse cursor is in the checkbox or not to set mouse.accepted property accordingly.
This is how I understood all of these currently. Is there any easier way, i.e. a way to be able to process all of the mouse events for areas that does not handle mouse events explicitly? For instance static text, progress bars, etc.
You can apply negative values to the z property of the MouseArea.
From the documentation:
Items with a higher stacking value are drawn on top of siblings with a lower stacking order. Items with the same stacking value are drawn bottom up in the order they appear. Items with a negative stacking value are drawn under their parent's content.