简体   繁体   中英

TableView is invisible

I'm trying to set something up, where there's aa HorizontalHeaderView that spans the entire width of the window, and a TableView that also spans the entire width of the window, along with stretching down to the bottom of the window. I also wanted a TextField and Button side by side, to sit on top of all this.

So far, I've gotten the TextField and Button to sit at the top, and part of the HorizontalHeaderView to be visible, but the TableView is completely invisible. I've tried fiddling around with height , Layout.preferredHeight , etc. but nothing makes it stretch to the bottom and fill the width of the window.

Here's what I've got so far:

import QtQuick 6.0
import QtQuick.Controls.Basic 6.0
import QtQuick.Layouts 6.0

ApplicationWindow {
    title: "Portmod"
    width: 640
    height: 480
    visible: true

    header: TabBar {
        id: mainTabBar
        width: parent.width

        TabButton {
            text: "Manage"
            width: implicitWidth
        }

        TabButton {
            text: "Search"
            width: implicitWidth
        }
    }

    StackLayout {
        id: mainStackLayout
        currentIndex: mainTabBar.currentIndex

        ColumnLayout {
            id: manageTab

            RowLayout {

                TextField {
                    placeholderText: "Filter packages..."
                }

                Button {
                    text: "Filter"
                }
            }

            HorizontalHeaderView {
                id: installedPackagesHeader
                syncView: installedPackagesTable
            }

            TableView {
                id: installedPackagesTable
                columnSpacing: 1
                rowSpacing: 1
                clip: true

                model: installedPackagesModel

                Keys.onUpPressed: installedPackagesTableVerticalScrollBar.decrease()
                Keys.onDownPressed: installedPackagesTableVerticalScrollBar.increase()
                Keys.onLeftPressed: installedPackagesTableHorizontalScrollBar.decrease()
                Keys.onRightPressed: installedPackagesTableHorizontalScrollBar.increase()

                ScrollBar.vertical: ScrollBar {
                    id: installedPackagesTableVerticalScrollBar
                    parent: installedPackagesTable
                }

                ScrollBar.horizontal: ScrollBar {
                    id: installedPackagesTableHorizontalScrollBar
                    parent: installedPackagesTable
                }

                delegate: Rectangle {
                    implicitWidth: 300
                    implicitHeight: 25

                    Text {
                        text: display
                        anchors.left: parent.left
                    }

                }
            }
        }

        Rectangle {
            id: searchTab
            width: parent.parent.width
            height: parent.parent.height
        }
    }
}

Here's my custom QSortFilterProxyModel and QAbstractItemModel :

class InstalledPackagesProxyModel(QSortFilterProxyModel):
    def __init__(self, data: list[list]) -> None:
        super().__init__()

        self.realModel = InstalledPackagesModel(data)
        self.setSourceModel(self.realModel)

    def get_atom(self, index: QModelIndex) -> Atom:
        """
        Returns a reference to the source index instead of proxy index, to handle the sorted view.
        """
        mapped_index = self.mapToSource(index)
        data = [tuple(pkg_data_list) for pkg_data_list in self.realModel._data]
        return Atom(f"{data[mapped_index.row()][2]}/{data[mapped_index.row()][0]}")


class InstalledPackagesModel(QAbstractTableModel):
    def __init__(self, data: list[list]):
        super(InstalledPackagesModel, self).__init__()
        self._data = data
        self.header_labels = ["Name", "Use Flags", "Category", "Version"]

    def data(self, index, role):
        if role == Qt.DisplayRole:  # type: ignore
            value = self._data[index.row()][index.column()]

            if isinstance(value, Atom):
                return str(value)

            return value

    def rowCount(self, index):
        return len(self._data)

    def columnCount(self, index):
        try:
            return len(self._data[0])
        # If there are no installed mods in the prefix
        except IndexError:
            return 1

    def headerData(self, section, orientation, role=Qt.DisplayRole):  # type: ignore
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:  # type: ignore
            return self.header_labels[section]
        return QAbstractTableModel.headerData(self, section, orientation, role)

This is what it looks like: 进步

You need to use anchors.fill: parent on the StackView so it fills out its parent and has a proper size. Furthermore the HorizontalHeaderView needs to get a implicitHeight and the TableView should set Layout.fillWidth and Layout.fillHeight to true .

You need to use Layout.fillWidth and Layout.fillHeight to span to the full width and height of layouts.

import QtQuick 6.0
import QtQuick.Controls.Basic 6.0
import QtQuick.Layouts 6.0
import Qt.labs.qmlmodels 1.0

ApplicationWindow {
    title: "Portmod"
    width: 640
    height: 480
    visible: true

    header: TabBar {
        id: mainTabBar
        width: parent.width

        TabButton { text: "Manage" }
        TabButton { text: "Search" }
    }

    StackLayout {
        id: mainStackLayout
        currentIndex: mainTabBar.currentIndex
        anchors.fill: parent

        ColumnLayout {
            id: manageTab
            Layout.fillWidth: true

            RowLayout {
                Layout.fillWidth: true

                TextField {
                    Layout.fillWidth: true
                    placeholderText: "Filter packages..."
                }
                Button {
                    Layout.fillWidth: true
                    text: "Filter"
                }
            }

            HorizontalHeaderView {
                id: installedPackagesHeader
                syncView: tableView
                implicitHeight: 30
                Layout.fillWidth: true
            }

            TableView {
                id: tableView
                Layout.fillWidth: true
                Layout.fillHeight: true
                columnSpacing: 1
                rowSpacing: 1
                clip: true

                columnWidthProvider: function (column) {
                    return tableView.model ? tableView.width / tableView.model.columnCount : 0
                }
                rowHeightProvider: function (row) { return 30 }

                onWidthChanged: tableView.forceLayout()

                model: TableModel {
                    TableModelColumn { display: "name" }
                    TableModelColumn { display: "color" }

                    rows: [
                        { "name": "cat", "color": "black" },
                        { "name": "dog", "color": "brown" },
                        { "name": "bird", "color": "white" }
                    ]
                }

                delegate: Rectangle {
                    Text {
                        text: display
                        anchors.left: parent.left
                    }
                }
            }
        }

        Rectangle {
            id: searchTab
            Layout.fillWidth: true
            Layout.fillHeight: true
            color: "red"
        }
    }
}

I figured out that I needed to set the columnWidthProvider to this:

return Window.width / installedPackagesTableView.model.columnCount()

This is my full code for the TableView:

TableView {
    id: installedPackagesTableView

    property int selectedRow: 0

    focus: true
    columnSpacing: 1
    rowSpacing: 1
    clip: true
    model: installedPackagesModel

    columnWidthProvider: function () {
        return Window.width / installedPackagesTableView.model.columnCount()
    }

    rowHeightProvider: function (row) {
        return 30;
    }

    onWidthChanged: installedPackagesTableView.forceLayout()

    Layout.fillWidth: true
    Layout.fillHeight: true

    Keys.onUpPressed: function () {
        if (selectedRow != 0) {
            selectedRow -= 1;
        }

        // Move scrollbar up if the selectedRow is going to be invisible
        if (selectedRow == topRow) {
            installedPackagesTableVerticalScrollBar.decrease()
        }
    }

    Keys.onDownPressed: function () {
        if (selectedRow != installedPackagesModel.rowCount() - 1) {
            selectedRow += 1;

            // Move scrollbar down if the selectedRow is going to be invisible
            if (selectedRow == bottomRow) {
                installedPackagesTableVerticalScrollBar.increase()
            }
        }
    }

    Keys.onReturnPressed: installedPackagesModel.getAtom(selectedRow)

    ScrollBar.vertical: ScrollBar {
        id: installedPackagesTableVerticalScrollBar
    }

    ScrollBar.horizontal: ScrollBar {
        id: installedPackagesTableHorizontalScrollBar
    }

    delegate: ItemDelegate {
        highlighted: row == installedPackagesTableView.selectedRow
        onClicked: installedPackagesTableView.selectedRow = row
        onDoubleClicked: installedPackagesModel.getAtom(row)
        text: model.display
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM