【问题标题】:How to move between TableView items by sending QKeyEvent?如何通过发送 QKeyEvent 在 TableView 项目之间移动?
【发布时间】:2016-01-09 09:40:31
【问题描述】:

我的 QML 文件中有一个 TableView,通过向它提供模型加载了几个项目。我可以通过箭头键(向上、向下)在项目之间导航,但我不知道如何通过代码在项目之间导航。

这是我尝试发送事件的方式,但似乎我将我的事件发送到了错误的组件:

QQuickItem* focusedItem = qobject_cast<QQuickItem*>(QGuiApplication::focusObject());

QKeyEvent *event1 = new QKeyEvent(QEvent::KeyPress,Qt::Key_Up,Qt::NoModifier);
QKeyEvent *event2 = new QKeyEvent(QEvent::KeyRelease,Qt::Key_Up,Qt::NoModifier);
QCoreApplication::postEvent (focusedItem, event1);
QCoreApplication::postEvent (focusedItem, event2);

焦点项目似乎是一个focusScope,它的父项是一个空QObject!我已经对此进行了测试:

qDebug () << "ITEM =>" << focusedItem;
qDebug () << "PARENT=>" << focusedItem->parent();

【问题讨论】:

    标签: qt focus qml tableview


    【解决方案1】:

    寻找这样的东西的好地方是 Qt 本身的自动测试。例如,如果您查看tst_tableview.qml,您会看到关键事件并未发送到特定项目。而是预先给目标项赋予焦点,并将事件发送到窗口:

    table.forceActiveFocus();
    keyClick(Qt.Key_Down);
    

    所以,举个小例子:

    #include <QtGui>
    #include <QtQuick>
    
    class Controller : public QObject
    {
        Q_OBJECT
    
    public:
        Controller() :
            mTarget(0),
            mTimerId(0) {
        }
    
        void setTarget(QQuickItem *item) {
            if (item == mTarget)
                return;
    
            mTarget = item;
    
            if (mTarget)
                mTimerId = startTimer(1000);
            else
                killTimer(mTimerId);
        }
    
        void timerEvent(QTimerEvent *) {
            if (mTarget) {
                QKeyEvent *event1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
                QKeyEvent *event2 = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Down, Qt::NoModifier);
                QCoreApplication::postEvent(mTarget->window(), event1);
                QCoreApplication::postEvent(mTarget->window(), event2);
            }
        }
    
    private:
        QQuickItem *mTarget;
        int mTimerId;
    };
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        Controller controller;
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        controller.setTarget(engine.rootObjects().first()->property("target").value<QQuickItem*>());
    
        return app.exec();
    }
    
    #include "main.moc"
    

    当在控制器上设置了一个目标项目时,我们启动一个计时器,它每秒向该项目所在的窗口发送一个向下事件。如果您只有一个窗口,则没有必要有目标的概念;只需在发送事件之前将焦点放在 QML 中的正确项目上即可。

    然后,在 main.qml

    import QtQuick 2.5
    import QtQuick.Controls 1.3
    import QtQuick.Layouts 1.1
    
    ApplicationWindow {
        id:  winRoot
        visible: true
        width: 500
        height: 500
    
        property alias target: tableView
    
        TableView {
            id: tableView
            focus: true
            model: ListModel {
                id: libraryModel
                ListElement {
                    title: "A Masterpiece"
                    author: "Gabriel"
                }
                ListElement {
                    title: "Brilliance"
                    author: "Jens"
                }
                ListElement {
                    title: "Outstanding"
                    author: "Frederik"
                }
            }
    
            TableViewColumn {
                role: "title"
                title: "Title"
                width: 100
            }
            TableViewColumn {
                role: "author"
                title: "Author"
                width: 200
            }
        }
    }
    

    【讨论】:

    • 谢谢@Mitch :) 但我认为那里有一个小错字,我改用了它,它作为一个魅力:QCoreApplication::sendEvent((QQuickItem*)(m_target-&gt;window()), event1);
    • 我没有编译你的确切代码,但没有强制转换我的编译器会生我的气。顺便说一句,我正在使用 c++11。你能给我解释一下什么是窗口方法以及它对我有什么帮助吗?我无法在控制台上将它的演员表打印到 QQuickItem*。
    • 它返回给定项目所在的窗口。就像我在答案中所说,如果你只有窗口,你可以把它传递给控制器​​。
    猜你喜欢
    • 1970-01-01
    • 2022-01-06
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 2015-03-09
    • 1970-01-01
    • 2020-05-22
    相关资源
    最近更新 更多