Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Получение порядкового номера QTreeView
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt GUI
poluna
Привет всем.
Есть у меня класс TreeComboBox, как можно понять из названия в QComboBox у меня находится QTreeView.

Проблема в том, что я никак не могу получить порядковый номер элемента в QTreeView, для автоматического выбора при выделении в моей модели.
С помощью idx.row() я могу получить, но если у элемента уровень вложенности например 2, то получается ерунда.
lanz
А как вы определяете порядковый номер элемента в дереве? Всмысле что это значит? Т.е. какой порядковый номер должен быть у первого элемента вложенности 2 например?
poluna
Забыла сказать, что QTreeView всегда находится в состоянии expandAll.
Порядковый номер хочу определять визуально так же как и в QComboBox.
Например
1 Item 1
2   |-item 2
3   |-item 3
4        |-item 4
5        |-item 5
6   |-item 6
7        |-item 7
8 Item 8
9   |-item 9
Пока только приходит в голову, обход всех элементов рекурсивно с их дочерними элементами и присвоением номера.
Или ввести свою сущность (строка) в модель, и с помощью нее строить модель и нумеровать строки.

Хотя честно говоря внятной и полной картины как это сделать нет. :(
Алексей1153
poluna, расскажи поподробнее, какие действия хочешь совершить ? Для идентификации элемента вроде достаточно методов parent и data индекса

ну, и да, если хочешь такую сквозную нумерацию сделать - необходимо реализовать у элемента метод навроде GetMyNumber() , где произойдёт рекурсивный вызов метода родителя в том числе
poluna
Так как мой класс производен TreeComboBox от QComboBox, то мне нужно хотя бы переопределить функции: currentIndex, setCurrentIndex и currentText.
Это нужно например для ситуации, когда мне нужно добавить пользователя в группу, выбрав группу в дереве, нажав кнопку добавить и в появившемся диалоге добавления пользователя будет выбрана группа (выделенная ранее) и ...
Алексей1153
poluna, не совсем понимаю участия комбы в этом процессе :search: . В классе дерева обрабатываешь contextMenuEvent , там определяешь, какой элемент модели дерева щёлкнули (viewport() , indexAt() ) . По индексу модели отыскивается элемент
poluna
Мне просто нужен комбобокс с деревом! :)
Всё есть, но есть нюансы, из-за которых пока грустно
Алексей1153
Цитата(poluna @ 16.12.2015, 13:27) *
Мне просто нужен комбобокс с деревом

так он же уже есть, как я понял )) Осталось обработку в дерево добавить
poluna
И я о том же!
Видимо я не так выражаюсь.
Нажмите для просмотра прикрепленного файла
На картинке, показано, что у меня есть.
В диалоге "Создание группы" указывается, родитель он должен быть выбран таким же, как и выделенный в левом дереве основного окна.
А я пока могу выбрать только ветки первого уровня.
Так надеюсь понятней, что мне нужно. :)

Или я тебя не понимаю! :D
Алексей1153
poluna, у меня обычно есть "внемодельное" дерево - источник, по которому модель пересобирается. Контейнер обычно на основе QMap<>

struct s_item
{
s_item* m_parent;
QVector<s_item*> m_children;

...

};


s_item* m_root;
QMap<s_item*,s_item*> m_tree;


У тебя этой очень удобной детальки , похоже, нету, поэтому мы не и понимаем друг друга :D В контейнере всё ищется и перебирается запросто
poluna
Теперь я поняла тебя. :)
Вариант неплох, и вроде как даже проще в реализации.

Всё, вопрос пока снимаю. Знаю как реализовывать! :yahoo:
lanz
Цитата
"внемодельное" дерево

Ойойой, не слушайте его, он вас плохому научит! :lol:
По идее модель в комбобоксе и модель в дереве слева - это должна быть одна и та же модель.
Поэтому индекс от одного должен подходить к индексу от другого.

Т.е. вы сначала получаете выделенный индекс от дерева
(назовем его idx)

потом в комбобоксе делаете
combo->setRootModelIndex(idx.parent())
combo->setCurrentIndex(idx.row())

http://doc.qt.io/qt-4.8/qcombobox.html#setRootModelIndex
http://doc.qt.io/qt-4.8/qcombobox.html#currentIndex-prop
Алексей1153
lanz, да можно и в модели хранить, но я так не люблю делать, это же неудобно ))

lanz, оно, вообще говоря, так и происходит - противоречий нету, но некоторые операции по своему контейнеру удобнее производить

А в данном случае твой вариант лучше будет, конечно )
ViGOur
А по моему Алексей1153 предложил хороший способ, я сам подобным же пользуюсь.
Есть список (QList) или дерево(QMap), которое откуда-то загружается и которое отображается в модели. Очень удобно добавлять, редактировать, удалять. А модель это же абстракция и она не должна по идее хранить данные, как и вид. :)

lanz, выше сказано
Цитата(poluna @ 15.12.2015, 17:11) *
Есть у меня класс TreeComboBox, как можно понять из названия в QComboBox у меня находится QTreeView.
и как я понимаю твой метод идеально подходит для QComboBox, но не для переопределенного класса. Дождемся автора, что она скажет!
poluna
lanz, если в комбобоксе стандартными средствами можно показать дерево, то твой метод подойдет, но я не смогла.
Как я поняла для показа дерева в комбобокс нужно переопределять класс, я сделала так:
#! /usr/bin/python
# -*- coding: UTF-8 -*-

from PyQt4 import QtCore, QtGui


class TreeComboBox(QtGui.QComboBox):
    def __init__(self, parent=None):
        super(QtGui.QComboBox, self).__init__(parent)
        self._skipNextHide = False
        self._treeView = QtGui.QTreeView(self)
        self.setView(self._treeView)
        self._treeView.header().hide()
        self._treeView.viewport().installEventFilter(self)

    def eventFilter( self, object, event):
        if event.type() == QtCore.QEvent.MouseButtonPress and object == self.view().viewport():
            index = self.view().indexAt(event.pos())
            if not self.view().visualRect(index).contains(event.pos()):
                self._skipNextHide = True
        return False

    def showPopup(self):
        self.setRootModelIndex(QtCore.QModelIndex())
        self._treeView.expandAll()
        QtGui.QComboBox.showPopup(self)

    def hidePopup(self):
        self.setRootModelIndex(self.view().currentIndex().parent())
        self.setCurrentIndex(self.view().currentIndex().row())
        if self._skipNextHide:
            self._skipNextHide = False
        else:
            QtGui.QComboBox.hidePopup(self)
если я не права, то буду только рада, сразу куча проблем исчезнет! :)
Но пока не знаю как!
lanz
poluna, ну у меня ваш код вроде работает как надо, ЧЯДНТ? :lol:
Немножко поменял hidePopup, чтобы он сразу все не корячил:
    def hidePopup(self):
        if self._skipNextHide:
            self._skipNextHide = False
        else:
            self.setRootModelIndex(self.view().currentIndex().parent())
            self.setCurrentIndex(self.view().currentIndex().row())
            QtGui.QComboBox.hidePopup(self)
poluna
Все, поняла, все работает! :)

Выкладываю работающий пример, так же на python:
пример
#! /usr/bin/python
# -*- coding: UTF-8 -*-

import sys
from PyQt4 import QtCore, QtGui

class TreeComboBox(QtGui.QComboBox):
    def __init__(self, parent=None):
        super(QtGui.QComboBox, self).__init__(parent)
        self._skipNextHide = False
        self._treeView = QtGui.QTreeView(self)
        self.setView(self._treeView)
        self._treeView.header().hide()
        self._treeView.viewport().installEventFilter(self)

    def eventFilter( self, object, event):
        if event.type() == QtCore.QEvent.MouseButtonPress and object == self.view().viewport():
            index = self.view().indexAt(event.pos())
            if not self.view().visualRect(index).contains(event.pos()):
                self._skipNextHide = True
        return False

    def showPopup(self):
        self.setRootModelIndex(QtCore.QModelIndex())
        self._treeView.expandAll()
        QtGui.QComboBox.showPopup(self)

    def hidePopup(self):
        if self._skipNextHide:
            self._skipNextHide = False
        else:
            self.setRootModelIndex(self.view().currentIndex().parent())
            self.setCurrentIndex(self.view().currentIndex().row())
            QtGui.QComboBox.hidePopup(self)

class Main(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self._comboBox = TreeComboBox(self)
        self._treeView = QtGui.QTreeView(self)

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self._comboBox)
        layout.addWidget(self._treeView)
        self.setLayout(layout)

        model = QtGui.QStandardItemModel()
        for a in range(3):
            i = QtGui.QStandardItem('Item ' + str(a))
            for b in range(3):
                ii = QtGui.QStandardItem('sub 1 Item ' + str(b))
                i.setChild(b, ii)
                for c in range(3):
                    iii = QtGui.QStandardItem('sub 2 Item ' + str(c))
                    ii.setChild(c, iii)
            model.appendRow(i)

        self._comboBox.setModel(model)
        self._treeView.setModel(model)

        self.connect(self._treeView, QtCore.SIGNAL("clicked(const QModelIndex&)"), self.comboSelect)

    def comboSelect(self, idx):
        self._comboBox.setRootModelIndex(idx.parent())
        self._comboBox.setCurrentIndex(idx.row())

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)

    main = Main()
    main.show()

    sys.exit(app.exec_())


lanz, спасибо огромное! :)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2021 IPS, Inc.