QListWidget保留旧索引值引发索引越界错误的技术问询
问题原因分析
- QListWidget清空后未重置选中状态:调用
clear()只会清空列表项,但不会自动将当前选中行重置为无效值(比如-1),之前选中的索引会被保留。当新搜索返回的电影列表更短时,这个旧索引就会超出新列表的范围。 - 选中相关变量未主动重置:新搜索时没有手动将
self.selected_item、self.selected_index等变量重置为None,导致它们保留旧的无效值,后续逻辑可能误用。 - 信号触发时机问题:清空列表或设置新选中行时,
itemSelectionChanged信号会被触发,如果此时self.movies已经更新为新列表,但信号处理函数get_movie_index没有做索引有效性检查,就会直接用旧索引访问新列表,引发越界错误。 - 代码缩进错误:
display_movies被错误地嵌套在get_movie_input方法内部,这会导致方法无法被正确调用(除非在get_movie_input内部调用,但这不符合类方法的设计)。
修复方案
1. 修正display_movies的缩进
将display_movies从get_movie_input中移出,作为类的独立方法:
def get_movie_input(self): # 重置所有选中状态变量 self.selected_item = None self.selected_index = None self.selected_movie_title = None self.selected_episode_id = None self.selected_episode = None self.movies_episodes = [] self.selected_movie_id = None self.selected_movie = None self.image_url = None self.movie_fetcher = MovieDetails() self.query = self.query_input.text() self.movies = self.movie_fetcher.fetch_object(self.query) self.display_movies() def display_movies(self): self.clear_movie_list() print("New Movies") for movie in self.movies: self.movie_list_widget.addItem(movie['title']) # 仅当电影列表非空时设置默认选中行 if self.movies: self.movie_list_widget.setCurrentRow(0)
2. 清空列表时重置选中状态并临时断开信号
修改clear_movie_list,避免清空时触发无效的信号处理:
def clear_movie_list(self): print("CLEARING") # 临时断开信号,防止清空时触发itemSelectionChanged self.movie_list_widget.itemSelectionChanged.disconnect(self.get_movie_index) self.movie_list_widget.clear() # 重置当前选中行为-1(无选中状态) self.movie_list_widget.setCurrentRow(-1) # 重新连接信号 self.movie_list_widget.itemSelectionChanged.connect(self.get_movie_index)
3. 在get_movie_index中添加索引有效性检查
确保只有当索引有效时才访问self.movies:
def get_movie_index(self): current_row = self.movie_list_widget.currentRow() # 检查索引是否在有效范围内 if current_row < 0 or not self.movies or current_row >= len(self.movies): # 重置选中变量 self.selected_movie = None self.selected_movie_id = None self.image_url = None return self.selected_movie = self.movies[current_row] print(self.selected_movie) self.selected_movie_id = self.selected_movie['id'] title = self.selected_movie['title'] self.image_url = self.selected_movie['image'] self.display_episodes() self.set_image() self.clean_title(title)
验证修复效果
按照你的重现流程测试:
- 搜索"The Mummy",选中索引8的项;
- 搜索"Star Wars",此时会先重置所有选中变量,清空列表并重置选中行,再添加新的3项并选中第0项;
get_movie_index会用有效的索引0访问新列表,不会触发越界错误。
内容的提问来源于stack exchange,提问作者mango orange
相关产品推荐
相关产品推荐

