Прокручиваемый список фреймов на холсте. После удаления кадра в конец списка добавляется пробел

Это одна проблема, которую я не могу понять самостоятельно. Вот:

У меня есть прокручиваемый список кадров, которые помещаются в один больший кадр, который затем упаковывается в холст. Код выглядит следующим образом:

### begin canvas/frame/picture 
self.picFrame = Frame(self, width = 450, height = 300)
        
self.picFrame.grid_rowconfigure(0, weight = 1)
self.picFrame.grid_columnconfigure(0, weight = 1)
self.picFrame.pack()
        
self.canvas = Canvas(self.picFrame, width = 450, height = 300)
self.canFrame = Frame(self.canvas)

self.canvas.create_window((0,0), window = self.canFrame, anchor = 'nw')
self.canvas.pack(side="left")

Я создаю один кадр, который содержит все вкусности, а затем помещаю этот кадр в self.canFrame:

self.itemFrame = Frame(self.canFrame, width = 450, height = 50)
self.itemFrame.grid(row = i, column = 0)
self.itemFrame.pack_propagate(0) 

У меня также есть несколько методов, которые я вызываю на холсте, чтобы заставить его правильно прокручиваться. Они следующие:

def setFrame(self, event = None):
    """ Sets the canvas dimensions and the scroll area """
    self.canvas.configure(scrollregion = self.canvas.bbox('all'))


def setScroll(self):
    ##### part of another function #######
    # create frame to hold scrollbar so we can
    # use grid on the scrollbar
    self.scrollFrame = Frame(self.picFrame)

    # set rows and column configures so we can
    # make scrollbar take up entire row/column
    self.scrollFrame.rowconfigure(1, weight = 1)
    self.scrollFrame.columnconfigure(1, weight = 1)
    self.scroll = AutoScrollbar(self.scrollFrame,
                            orient = "vertical",
                            command = self.canvas.yview)

    # set scrollbar as callback to the canvas
    self.canvas.configure(yscrollcommand = self.scroll.set)

    # set the scrollbar to be the height of the canvas
    self.scroll.grid(sticky = 'ns', row = 1, column = 0)

    # set the scrollbar to be packed on the right side

    self.scrollFrame.pack(side="right", fill="y")

    # bind the picture frame to the canvas
    self.picFrame.bind("<Configure>", self.setFrame) 

У меня также есть список, который содержит все кадры, которые я поместил на холст, и в каждом кадре есть флажок, поэтому я могу проверить, выбран ли этот флажок и хочу ли я его удалить или нет. Когда я удаляю кадр, я вызываю что-то вроде:

self.frames[i].destroy()

и этот индекс соответствует элементу фрейма, который я хочу уничтожить и который содержит все вкусности.

Когда я удаляю кадр, я чувствую, что мне не хватает изменения размера или удаления этого кадра из другого виджета, который все еще может «помнить» его. Все это прекрасно расширяется, но при удалении itemFrames у меня возникает проблема. Я довольно долго пытался понять это, но просто не мог этого сделать. Любые подсказки или указатели на то, куда идти отсюда, были бы замечательными. Я также извиняюсь за то, что это пост с большим количеством кода, я не был точно уверен, что понадобится или нет. Спасибо, что терпели меня.

Ваше здоровье!

Изменить/обновить:

Я забыл упомянуть, что я использую

to_del = self.frames.pop(i)
to_del.destroy()

а также сброс полосы прокрутки (по крайней мере, насколько мне известно)

self.scroll.destroy()
self.scrollFrame.destroy()
self.setScroll()  # defined up above

это все еще сохраняет ссылку, даже если я вставляю указанный кадр? Кроме того, может ли он каким-то образом пройти весь путь до self.picFrame? Это используется для удержания холста. Если я удалю все элементы в списке self.frames и попытаюсь снова обновить список, изображения не появятся.

Изменить. Также изменено использование «упаковки» в предложениях выше. Не следует быть небрежным с этим использованием.


person Cameron Gagnon    schedule 13.07.2015    source источник
comment
Я не вижу назначения self.frames, но учтите, что destroy() только уничтожит виджет, но не удалит его ссылку. Если вы хотите это сделать, вам придется сделать что-то вроде del self.frames[i].   -  person TigerhawkT3    schedule 14.07.2015
comment
Будьте осторожны с вашей терминологией. Слово pack в контексте вопроса о макете означает что-то очень конкретное (я назвал функцию pack), но вы, кажется, используете его для обозначения того, что я что-то добавил — иногда с помощью pack, иногда с помощью create_window. Это делает ваш вопрос немного трудным для чтения.   -  person Bryan Oakley    schedule 14.07.2015
comment
@TigerhawkT3: Держу пари, проблема в этом. Возможно, вы захотите рассмотреть возможность ответа на этот комментарий.   -  person Bryan Oakley    schedule 14.07.2015
comment
Вы сбрасываете атрибут scrollregion при удалении фрейма?   -  person Bryan Oakley    schedule 14.07.2015
comment
Я использую scrollregion = self.canvas.bbox('all'). Я прочитал документацию, но не совсем понимаю, что означает .bbox(). Я изучу его подробнее, хотя сразу вопросов не вижу, может быть, выделю его в отдельный вопрос.   -  person Cameron Gagnon    schedule 14.07.2015
comment
Это не ответило на вопрос. Вы настраиваете scrollregion каждый раз, когда удаляете что-то из кадра?   -  person Bryan Oakley    schedule 14.07.2015
comment
Да. Каждый раз, когда я удаляю кадр, я вызываю self.setScroll(), что в конечном итоге вызывает self.setFrame, а затем устанавливает self.canvas.configure(scrollregion = self.canvas.bbox('all'))   -  person Cameron Gagnon    schedule 14.07.2015


Ответы (1)


Вы уничтожили фрейм с помощью self.frames[i].destroy(), но ссылка все еще существует в self.frames. Чтобы удалить ссылку из list, используйте del self.frames[i].

person TigerhawkT3    schedule 13.07.2015