I'm trying to solve an issue in a Qt5 application that's caused by a touchscreen driver I wrote a couple years ago. The problem being that my touchscreen driver generates mouse press events to simulate touch behavior. This was because at the time I wrote it, my team was using an outdated Linux OS that didn't have a native touch driver.
The problem is that when I touch the /- buttons (the scroll buttons that increase/decrease the slider by a single tick, or cause it to rapidly scroll if held), the slider rapidly slides up/down as if I had clicked and held the button. This is because my driver uses QApplication::postEvent()
to dispatch the mouse event from a separate thread, and the delay in between touch and release is just long enough for it to register a click-and-hold type event, though the release event doesn't stop the sliding.
I would rewrite the application to use the now available native touch driver, but it doesn't offer enough control to be able to do what my driver does (my driver can generate left, right, or middle mouse events, whereas the native driver only provides left).
I tried rewriting the driver to use QApplication::sendEvent()
instead, but that was causing a segmentation fault that I couldn't figure out the cause of.
So is there a way I can disable the "click-and-hold" type behavior on the QSlider itself? So that I can still tap the buttons, but they'll only increase/decrease by a single tick at a time?
EDIT: Here's an example of how I'm generating the "touch" events via my driver.
void InputHandler::touchPress(TouchPoint * tp, QWidget * widget) {
QPoint screenPos(tp->cx(), tp->cy());
QWidget * target = widget;
if(target == NULL) target = QApplication::widgetAt(screenPos);
if(target != NULL) {
QPoint local = target->mapFromGlobal(screenPos);
QMouseEvent * press = new QMouseEvent(QEvent::MouseButtonPress, local, screenPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::postEvent(target, press);
DBG(" -- touch press on: " << typeid(*widget).name());
// Check to see if the target is a QLineEdit or QComboBox, and if so, set focus on it.
QLineEdit * lineEdit = dynamic_cast<QLineEdit*>(target);
QComboBox * comboBox = dynamic_cast<QComboBox*>(target);
if(lineEdit) lineEdit->setFocus(Qt::MouseFocusReason);
if(comboBox) comboBox->setFocus(Qt::MouseFocusReason);
}
}
EDIT 2: So a coworker played around with the slider and pointed out that he pressed the /- buttons, causing it to slide, and then he clicks the "reset" button we have to reset all controls on the form, the slider would reset and then continue sliding, indicating that the touch press was never released. He then would click the /- buttons normally with the mouse and reset again and it would stop. So even though the logs indicate that the mousePressEvent and mouseReleaseEvent methods are being triggered by my events, they don't seem to have the same behavior as using the mouse.
Any ideas?
EDIT 3: If it helps, I added an eventFilter and printed out every event type that the QSlider receives, from when I first touch the screen to when I release. The events received are:
Mouse Press (2)
Tooltip Change (184)
Paint (12)
Mouse Move (5)
Mouse Move (5)
Mouse Release (3)
But then after the release event, I get spammed in the logs with QEvent::Timer
events, which does not happen when I simply click with the mouse, as opposed to touching the slider with the touchscreen. If I then tap somewhere else, drag the slider, or click the slider with the actual mouse, these timer events stop.
Why is my generated QMouseEvent
causing these QEvent::Timer
events to be generated when I tap the slider with the touchscreen, but not with the mouse?
CodePudding user response:
Add a private integer variable (let's say pos) to your ui class. Go to slider's sliderPressed slot and get its value to pos inside sliderPressed slot
pos = ui->horizontalSlider->value();
Then go to the slider's sliderMoved slot, and set its value to pos variable's value inside sliderMoved slot
ui->horizontalSlider->setValue(pos);
You will see that you will be able to set the slider value only by clicking on it, but not moving it.
CodePudding user response:
QSlider doesn't have that functionality. You can write a custom widget that places the handle on the clicked position when you click anywhere on the widget.