[Interest] Keyboard navigation into, out of and within TableView in QML

Elvis Stansvik elvstone at gmail.com
Tue Jun 7 16:39:29 CEST 2016


Another solution is this (showing a button both above and below):

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.3

Window {
    visible: true
    width: 400
    height: 400

    ListModel {
        id: libraryModel

        ListElement {
            title: "A Masterpiece"
            author: "Gabriel"
        }
        ListElement {
            title: "Brilliance"
            author: "Jens"
        }
        ListElement {
            title: "Outstanding"
            author: "Frederik"
        }

    }

    Column {
        Button {
            id: buttonAbove
            text: "Button Above"
            focus: true

            Keys.onDownPressed: libraryView.enterFrom(Qt.TopEdge)
        }

        TableView {
            id: libraryView

            property Item previousItem: buttonAbove
            property Item nextItem: buttonBelow

            TableViewColumn {
                role: "title"
                title: "Title"
                width: 100
            }
            TableViewColumn {
                role: "author"
                title: "Author"
                width: 200
            }
            model: libraryModel

            function firstSelectedRow() {
                var result = rowCount;
                selection.forEach(function (row) {
                    result = Math.min(row, result);
                });
                return result == rowCount ? -1 : result;
            }

            function lastSelectedRow() {
                var result = -1;
                selection.forEach(function (row) {
                    result = Math.max(row, result);
                });
                return result;
            }

            Keys.onUpPressed: {
                var row = firstSelectedRow();
                if (row > 0) {
                    selection.clear();
                    selection.select(row - 1);
                    event.accepted = true;
                } else if (previousItem) {
                    selection.clear();
                    previousItem.forceActiveFocus();
                    event.accepted = true;
                }
            }

            Keys.onDownPressed: {
                var row = lastSelectedRow();
                if (row != -1 && row < rowCount - 1) {
                    selection.clear();
                    selection.select(row + 1);
                    event.accepted = true;
                } else if (nextItem) {
                    selection.clear();
                    nextItem.forceActiveFocus();
                    event.accepted = true;
                }
            }

            function enterFrom(edge) {
                forceActiveFocus();
                if (rowCount != 0) {
                    selection.clear();
                    if (edge == Qt.BottomEdge) {
                        selection.select(rowCount - 1);
                    } else if (edge == Qt.TopEdge) {
                        selection.select(0);
                    }
                }
            }
        }

        Button {
            id: buttonBelow
            text: "Button Below"

            Keys.onUpPressed: libraryView.enterFrom(Qt.BottomEdge)
        }
    }
}

But this is also a horrible kludge. Surely there's some easier way of
achieving such a simple thing?

2016-06-07 15:31 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
> Hi all,
>
> I'm working with a device that has only a pushwheel button as input.
> Turning the button gives keyboard Up/Down presses.
>
> Given:
>
> import QtQuick 2.4
> import QtQuick.Window 2.2
> import QtQuick.Controls 1.3
>
> Window {
>     visible: true
>     width: 400
>     height: 400
>
>     ListModel {
>         id: libraryModel
>         ListElement {
>             title: "A Masterpiece"
>             author: "Gabriel"
>         }
>         ListElement {
>             title: "Brilliance"
>             author: "Jens"
>         }
>         ListElement {
>             title: "Outstanding"
>             author: "Frederik"
>         }
>     }
>
>     Column {
>         TableView {
>             id: libraryView
>             TableViewColumn {
>                 role: "title"
>                 title: "Title"
>                 width: 100
>             }
>             TableViewColumn {
>                 role: "author"
>                 title: "Author"
>                 width: 200
>             }
>             model: libraryModel
>         }
>
>         Button {
>             id: button
>             text: "Button"
>             focus: true
>         }
>     }
> }
>
> What is the most elegant way of having the Up key move focus+select
> the last row in tableView, and then allow moving between rows in the
> tableView with Up/Down, where Down on the last row brings you back to
> the button?
>
> At the moment I have this horrible solution where I add
>
>             Keys.onUpPressed: {
>                 if (currentRow > 0) {
>                     console.log('moving up');
>                     var newRow = currentRow - 1;
>                     selection.clear();
>                     selection.select(newRow);
>                     currentRow = newRow;
>                 }
>             }
>
>             Keys.onDownPressed: {
>                 selection.clear();
>                 if (currentRow == rowCount - 1) {
>                     console.log('moving to button');
>                     currentRow = -1;
>                     button.forceActiveFocus();
>                 } else {
>                     console.log('moving down');
>                     var newRow = currentRow + 1;
>                     selection.select(newRow);
>                     currentRow = newRow;
>                 }
>             }
>
> to the TableView and
>
>             Keys.onUpPressed: {
>                 if (libraryView.rowCount != 0) {
>                     console.log('moving to table view');
>                     var newRow = libraryView.rowCount - 1;
>                     libraryView.forceActiveFocus();
>                     libraryView.selection.clear();
>                     libraryView.selection.select(newRow);
>                     libraryView.currentRow = newRow;
>                 }
>             }
>
> to the Button, but surely there's some better way of achieving this?
>
> Thanks in advance,
> Elvis



More information about the Interest mailing list