(Pyqt) Qtreeview - تريد توسيع/انهيار جميع الأطفال والأحفاد

StackOverflow https://stackoverflow.com/questions/4100139

سؤال

أريد أن أكون قادرًا على توسيع أو انهيار جميع الأطفال من فرع معين في QtreeView. أنا أستخدم PYQT4.

أعلم أن QtreeView لديها ميزة توسيع جميع الأطفال مرتبطة بـ *، لكنني بحاجة إلى شيئين: يجب أن تكون مرتبطة بمجموعة مفاتيح مختلفة (مساحة التحول) وأحتاج أيضًا إلى أن أكون قادرًا على الانهيار جميع الأطفال أيضًا .

إليكم ما جربته حتى الآن: لدي فئة فرعية من QtreeView حيث أتحقق من التحرير والسرد مفتاح Space. أعلم أن QModelIndex ستسمح لي باختيار طفل معين مع وظيفة "الطفل" ، ولكن هذا يتطلب معرفة عدد الأطفال. أنا صباحا قادرة على الحصول على عدد من الأطفال من خلال النظر إلى InternalPointer ، ولكن هذا يعطيني فقط معلومات للمستوى الأول من التسلسل الهرمي. إذا حاولت استخدام العودية ، فيمكنني الحصول على مجموعة من عدد الأطفال ، ولكن بعد ذلك فقدت حول كيفية تحويلها إلى QModelIndex صالحة.

هنا بعض التعليمات البرمجية:

def keyPressEvent(self, event):
    """
    Capture key press events to handle:
    - enable/disable
    """
    #shift - space means toggle expanded/collapsed for all children
    if (event.key() == QtCore.Qt.Key_Space and 
        event.modifiers() & QtCore.Qt.ShiftModifier):
        expanded = self.isExpanded(self.selectedIndexes()[0])
        for cellIndex in self.selectedIndexes():
            if cellIndex.column() == 0: #only need to call it once per row
                #I can get the actual object represented here
                item = cellIndex.internalPointer()
                #and I can get the number of children from that
                numChildren = item.get_child_count()
                #but now what? How do I convert this number into valid
                #QModelIndex objects? I know I could use: 
                #   cellIndex.child(row, 0)
                #to get the immediate children's QModelIndex's, but how
                #would I deal with grandchildren, great grandchildren, etc...
                self.setExpanded(cellIndex, not(expanded))
        return

فيما يلي بداية طريقة التكرار التي كنت أبحث عنها ، لكنني تتعثر عندما أحاول بالفعل تعيين الحالة الموسعة لأنه بمجرد دخول العودية ، أفقد "الاتصال" مع أي QModelIndex صالح ...

def toggle_expanded(self, item, expand):
    """
    Toggles the children of item (recursively)
    """
    for row in range(0,item.get_child_count()):
        newItem = item.get_child_at_row(row)
        self.toggle_expanded(newItem, expand)
    #well... I'm stuck here because I'd like to toggle the expanded
    #setting of the "current" item, but I don't know how to convert
    #my pointer to the object represented in the tree view back into
    #a valid QModelIndex
    #self.setExpanded(?????, expand)   #<- What I'd like to run
    print "Setting", item.get_name(), "to", str(expand) #<- simple debug statement that indicates that the concept is valid

شكرا للجميع لأخذ الوقت الكافي للنظر في هذا!

هل كانت مفيدة؟

المحلول

حسنًا ... لم ينقلني الأشقاء إلى المكان الذي أردت الذهاب إليه. تمكنت من عمل الكود على النحو التالي (ويبدو أنه تطبيق لائق). لا يزال مجد إلى البروفيسور.

لاحظ أن هناك الافتراض التالي في الكود: يفترض أن كائنات مخزن البيانات الأساسية لديك لديها القدرة على الإبلاغ عن عدد الأطفال الذين لديهم (get_child_count () في الكود الخاص بي). إذا لم يكن الأمر كذلك ، فسيتعين عليك بطريقة ما الحصول على عدد الأطفال بشكل مختلف ... ربما من خلال محاولة تعسفي فقط للحصول على فهارس الأطفال - باستخدام qmodelindex.child (الصف ، العقيد) - مع عدد الصفوف المتزايدة حتى تعود فهرس غير صالح؟ - هذا ما اقترحه البروفيسور.

لاحظ أيضًا أنني أقوم بالفعل بتوسيع/collpase كل عقدة في نقطة مختلفة في العودية بناءً على ما إذا كنت أتوسع أو انهار. هذا لأنه ، من خلال التجربة والخطأ ، اكتشفت أن مشاهدات الأشجار المتحركة ستتلعثم وتتأثر إذا فعلت ذلك في مكان واحد في الكود. الآن ، من خلال عكس الترتيب الذي أقوم به بناءً على ما إذا كنت في المستوى العلوي (أي جذر الفرع الذي يؤثر عليه - وليس جذر TreeView بأكمله) أحصل على رسوم متحركة ناعمة لطيفة. تم توثيق هذا أدناه.

الكود التالي في فئة فرعية QtreeView.

#---------------------------------------------------------------------------
def keyPressEvent(self, event):

    if (event.key() == QtCore.Qt.Key_Space and self.currentIndex().column() == 0):
        shift = event.modifiers() & QtCore.Qt.ShiftModifier
        if shift:
            self.expand_all(self.currentIndex())
        else:                
            expand = not(self.isExpanded(self.currentIndex()))
            self.setExpanded(self.currentIndex(), expand)


#---------------------------------------------------------------------------
def expand_all(self, index):
    """
    Expands/collapses all the children and grandchildren etc. of index.
    """
    expand = not(self.isExpanded(index))
    if not expand: #if collapsing, do that first (wonky animation otherwise)
        self.setExpanded(index, expand)    
    childCount = index.internalPointer().get_child_count()
    self.recursive_expand(index, childCount, expand)
    if expand: #if expanding, do that last (wonky animation otherwise)
        self.setExpanded(index, expand)


#---------------------------------------------------------------------------
def recursive_expand(self, index, childCount, expand):
    """
    Recursively expands/collpases all the children of index.
    """
    for childNo in range(0, childCount):
        childIndex = index.child(childNo, 0)
        if expand: #if expanding, do that first (wonky animation otherwise)
            self.setExpanded(childIndex, expand)
        subChildCount = childIndex.internalPointer().get_child_count()
        if subChildCount > 0:
            self.recursive_expand(childIndex, subChildCount, expand)
        if not expand: #if collapsing, do it last (wonky animation otherwise)
            self.setExpanded(childIndex, expand)

نصائح أخرى

Model.RowCount (الفهرس) هي الطريقة التي تريدها.

model = index.model()   # or some other way of getting it
for i in xrange(model.rowCount(index)):
  child = model.index(i,0, index)
  # do something with child

Model.Index (Row ، Col ، Parent) هو نفسه في الأساس مثل INDEX.CHILD (ROW ، COL) ؛ فقط مع عدد أقل من الاتجاهات.

أود أن أوصي باستخدام qtreewIdget الذي يرث QtreeView. يمكنك بعد ذلك الاستيلاء على الأطفال باعتبارها qtreewidgetItem.

نظرًا لأنك لا ترغب في استخدام QTREewIdget ولكنك تريد التمسك بنموذجك الحالي .. يمكنك التكرار من خلال الأطفال "المحتملون" الذين يستخدمون. iSvalId (). يجب ألا تستخدم InternalPointer () رغم ذلك. بدلاً من ذلك ، استخدم CellItem لديك ، حيث إنه ModalIndex الأصلي .. ثم حاول العثور على أشقائها. شيء مثل

x = 0; y =0
while cellIndex.sibling(x, y).isValid():
    child = cellIndex.sibling(x, y)
    x += 1
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top