首先,我的问题只能在带触摸屏的设备上重现, 用PC /鼠标一切正常。
如果我使用QTableView
+ QScroller
作为独立窗口,一切正常 - 我将手指从下往上滚动,从上到下向上滚动。
但如果我将QTableView
放在QWidget
Qt::Popup
属性中,那么滚动会改变方向!我将手指从下往上移动,然后向上滚动,从上到下向下滚动。
这是我的代码:
#include <QAbstractTableModel>
#include <QScroller>
#include <QTouchDevice>
#include <QVBoxLayout>
#include <QtDebug>
#include <QtWidgets/QApplication>
#include <QtWidgets/QTableView>
class MyModel : public QAbstractTableModel {
public:
MyModel(QObject *parent) : QAbstractTableModel(parent) {}
int rowCount(const QModelIndex &parent = QModelIndex()) const override {
return 100;
}
int columnCount(const QModelIndex &parent = QModelIndex()) const override {
return 3;
}
QVariant data(const QModelIndex &index,
int role = Qt::DisplayRole) const override {
if (role == Qt::DisplayRole) {
return QString("Row%1, Column%2")
.arg(index.row() + 1)
.arg(index.column() + 1);
}
return QVariant();
}
QVariant headerData(int section, Qt::Orientation orientation,
int role) const override {
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal) {
switch (section) {
case 0:
return QString("first");
case 1:
return QString("second");
case 2:
return QString("third");
}
}
}
return QVariant();
}
};
bool is_touch_screen_avaible() {
const auto devs = QTouchDevice::devices();
for (const auto &dev : devs) {
if (dev->type() == QTouchDevice::TouchScreen) {
return true;
}
}
return false;
}
void configure_scoller_for_item_view(QAbstractItemView *view) {
QScroller *scroller = QScroller::scroller(view);
view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
QScrollerProperties properties =
QScroller::scroller(scroller)->scrollerProperties();
QVariant overshootPolicy =
QVariant::fromValue<QScrollerProperties::OvershootPolicy>(
QScrollerProperties::OvershootAlwaysOff);
properties.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy,
overshootPolicy);
scroller->setScrollerProperties(properties);
properties.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy,
overshootPolicy);
scroller->setScrollerProperties(properties);
if (is_touch_screen_avaible())
scroller->grabGesture(view, QScroller::TouchGesture);
else
scroller->grabGesture(view, QScroller::LeftMouseButtonGesture);
}
#define POPUP
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
#ifdef POPUP
QWidget *mainWin = new QWidget;
mainWin->setWindowFlags(Qt::Popup);
auto lay = new QVBoxLayout(mainWin);
mainWin->setLayout(lay);
auto tableView = new QTableView(mainWin);
lay->addWidget(tableView);
#else
auto tableView = new QTableView;
#endif
MyModel myModel(nullptr);
tableView->setModel(&myModel);
tableView->setSelectionMode(QAbstractItemView::NoSelection);
tableView->setFocusPolicy(Qt::NoFocus);
configure_scoller_for_item_view(tableView);
#ifdef POPUP
mainWin->resize(500, 500);
mainWin->show();
#else
tableView->resize(500, 500);
tableView->show();
#endif
return a.exec();
}
答案 0 :(得分:1)
Qt并未在可滚动区域中完全实现手势explained in their own documentation:
Qt并没有真正反映出可滚动视图(继承QAbstractItemView,QML类的小部件类)上的手势的系统行为。
[...]
在小部件中,平移识别器目前硬编码为使用2个触摸点。对于触摸屏,应将其更改为一个。但只要保留单指平移选择文本,就无法做到这一点。
使用触摸屏时,小部件中的选择由系统(Windows)或Qt本身(其他平台)触摸合成的鼠标事件驱动。相同的触摸事件驱动QGestureManager。
另一方面,QTouchEvents
(和known)未定义的行为带有QWidget::grabGesture(Qt::PanGesture)
和弹出窗口小部件:
当有多个活动触摸点时,打开弹出窗口或抓取鼠标时,QTouchEvents的行为未定义。
两个问题的结合可能是问题的根源。
作为一种可能的解决方法(尽管不完全符合您的要求),您可以使用Qt::FramelessWindowHint | Qt::Tool
作为替代方案启用双指滚动。另外,正如@ mohammad-kanan在评论中所提到的,您可以尝试使用Qt::Popup
代替xmlns:cdv="http://cordova.apache.org/ns/1.0"
。