mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
继续为scene.py添加中文注释
This commit is contained in:
parent
6aa3251e81
commit
063a19b25f
1 changed files with 186 additions and 185 deletions
371
beeref/scene.py
371
beeref/scene.py
|
|
@ -265,302 +265,303 @@ class BeeGraphicsScene(QtWidgets.QGraphicsScene): # 定义场景类,继承自
|
|||
|
||||
# We want the items to center around the selection's center,
|
||||
# not (0, 0)
|
||||
center = self.get_selection_center()
|
||||
bounds = rpack.bbox_size(sizes, positions)
|
||||
diff = center - QtCore.QPointF(bounds[0]/2, bounds[1]/2)
|
||||
positions = [QtCore.QPointF(*pos) + diff for pos in positions]
|
||||
center = self.get_selection_center() # 获取选择项目的中心位置
|
||||
bounds = rpack.bbox_size(sizes, positions) # 计算打包后的边界矩形大小
|
||||
diff = center - QtCore.QPointF(bounds[0]/2, bounds[1]/2) # 计算中心位置与边界矩形中心位置的差值
|
||||
positions = [QtCore.QPointF(*pos) + diff for pos in positions] # 为每个项目计算新的位置,考虑中心位置的偏移
|
||||
|
||||
self.undo_stack.push(commands.ArrangeItems(self, items, positions))
|
||||
self.undo_stack.push(commands.ArrangeItems(self, items, positions)) # 将排列操作添加到撤销栈中
|
||||
|
||||
def arrange_square(self):
|
||||
self.cancel_active_modes()
|
||||
max_width = 0
|
||||
max_height = 0
|
||||
gap = self.settings.valueOrDefault('Items/arrange_gap')
|
||||
items = sort_by_filename(self.selectedItems(user_only=True))
|
||||
def arrange_square(self): # 按正方形方式排列选择的项目
|
||||
self.cancel_active_modes() # 取消所有活动模式,确保没有正在进行的操作干扰
|
||||
max_width = 0 # 初始化最大宽度为0
|
||||
max_height = 0 # 初始化最大高度为0
|
||||
gap = self.settings.valueOrDefault('Items/arrange_gap') # 获取项目之间的间距
|
||||
items = sort_by_filename(self.selectedItems(user_only=True)) # 获取当前用户选择的项目,并按文件名排序
|
||||
|
||||
if len(items) < 2:
|
||||
return
|
||||
if len(items) < 2: # 如果选择的项目数量小于2
|
||||
return # 直接返回,无需排列
|
||||
|
||||
for item in items:
|
||||
rect = self.itemsBoundingRect(items=[item])
|
||||
max_width = max(max_width, rect.width() + gap)
|
||||
max_height = max(max_height, rect.height() + gap)
|
||||
for item in items: # 遍历选择的项目
|
||||
rect = self.itemsBoundingRect(items=[item]) # 获取项目的边界矩形
|
||||
max_width = max(max_width, rect.width() + gap) # 更新最大宽度,考虑项目宽度和间距
|
||||
max_height = max(max_height, rect.height() + gap) # 更新最大高度,考虑项目高度和间距
|
||||
|
||||
# We want the items to center around the selection's center,
|
||||
# not (0, 0)
|
||||
num_rows = math.ceil(math.sqrt(len(items)))
|
||||
center = self.get_selection_center()
|
||||
diff = center - num_rows/2 * QtCore.QPointF(max_width, max_height)
|
||||
num_rows = math.ceil(math.sqrt(len(items))) # 计算需要的行数,向上取整
|
||||
center = self.get_selection_center() # 获取选择项目的中心位置
|
||||
diff = center - num_rows/2 * QtCore.QPointF(max_width, max_height) # 计算中心位置与边界矩形中心位置的差值
|
||||
|
||||
iter_items = iter(items)
|
||||
positions = []
|
||||
for j in range(num_rows):
|
||||
for i in range(num_rows):
|
||||
iter_items = iter(items) # 创建一个迭代器,用于遍历选择的项目
|
||||
positions = [] # 创建一个空列表,用于存储每个项目的新位置
|
||||
for j in range(num_rows):# 遍历行数
|
||||
for i in range(num_rows):# 遍历列数
|
||||
try:
|
||||
item = next(iter_items)
|
||||
rect = self.itemsBoundingRect(items=[item])
|
||||
point = QtCore.QPointF(
|
||||
i * max_width + (max_width - rect.width())/2,
|
||||
j * max_height + (max_height - rect.height())/2)
|
||||
positions.append(point + diff)
|
||||
except StopIteration:
|
||||
break
|
||||
item = next(iter_items) # 从迭代器中获取下一个项目
|
||||
rect = self.itemsBoundingRect(items=[item]) # 获取项目的边界矩形
|
||||
point = QtCore.QPointF( # 计算项目的新位置
|
||||
i * max_width + (max_width - rect.width())/2, # 计算项目在当前行的水平位置
|
||||
j * max_height + (max_height - rect.height())/2) # 计算项目在当前列的垂直位置
|
||||
positions.append(point + diff) # 计算项目的新位置,考虑中心位置的偏移
|
||||
except StopIteration:# 当迭代器没有更多项目时,跳出循环
|
||||
break # 跳出当前列的循环,继续下一行
|
||||
|
||||
self.undo_stack.push(commands.ArrangeItems(self, items, positions))
|
||||
self.undo_stack.push(commands.ArrangeItems(self, items, positions)) # 将排列操作添加到撤销栈中
|
||||
|
||||
def flip_items(self, vertical=False):
|
||||
def flip_items(self, vertical=False): # 垂直或水平翻转选择的项目
|
||||
"""Flip selected items."""
|
||||
self.cancel_active_modes()
|
||||
self.cancel_active_modes() # 取消所有活动模式,确保没有正在进行的操作干扰
|
||||
self.undo_stack.push(
|
||||
commands.FlipItems(self.selectedItems(user_only=True),
|
||||
self.get_selection_center(),
|
||||
vertical=vertical))
|
||||
vertical=vertical)) # 将翻转操作添加到撤销栈中
|
||||
|
||||
def crop_items(self):
|
||||
def crop_items(self): # 对选择的项目进行裁剪
|
||||
"""Crop selected item."""
|
||||
|
||||
if self.crop_item:
|
||||
if self.crop_item:## 如果当前有项目正在裁剪状态
|
||||
return
|
||||
if self.has_single_image_selection():
|
||||
if self.has_single_image_selection():# 如果选择的项目是单个图像
|
||||
item = self.selectedItems(user_only=True)[0]
|
||||
if item.is_image:
|
||||
item.enter_crop_mode()
|
||||
item.enter_crop_mode() # 进入图像裁剪模式
|
||||
|
||||
def sample_color_at(self, position):
|
||||
item_at_pos = self.itemAt(position, self.views()[0].transform())
|
||||
def sample_color_at(self, position): # 采样指定位置的颜色
|
||||
item_at_pos = self.itemAt(position, self.views()[0].transform()) # 获取指定位置上的项目
|
||||
if item_at_pos:
|
||||
return item_at_pos.sample_color_at(position)
|
||||
return item_at_pos.sample_color_at(position) # 如果项目存在,采样该位置的颜色
|
||||
|
||||
def select_all_items(self):
|
||||
self.cancel_active_modes()
|
||||
path = QtGui.QPainterPath()
|
||||
path.addRect(self.itemsBoundingRect())
|
||||
def select_all_items(self): # 选择所有项目
|
||||
self.cancel_active_modes() # 取消所有活动模式,确保没有正在进行的操作干扰
|
||||
path = QtGui.QPainterPath() # 创建一个空的绘图路径
|
||||
path.addRect(self.itemsBoundingRect()) # 创建一个矩形路径,包含所有项目的边界矩形
|
||||
path.addRect(self.itemsBoundingRect())
|
||||
path.addRect(self.itemsBoundingRect())
|
||||
# This is faster than looping through all items and calling setSelected
|
||||
self.setSelectionArea(path)
|
||||
self.setSelectionArea(path)# 设置选择区域为创建的路径,包含所有项目的边界矩形
|
||||
|
||||
def deselect_all_items(self):
|
||||
self.cancel_active_modes()
|
||||
self.clearSelection()
|
||||
def deselect_all_items(self):# 取消所有项目的选择
|
||||
self.cancel_active_modes() # 取消所有活动模式,确保没有正在进行的操作干扰
|
||||
self.clearSelection() # 清除所有项目的选择状态
|
||||
|
||||
def has_selection(self):
|
||||
def has_selection(self):# 检查是否有项目被选择
|
||||
"""Checks whether there are currently items selected."""
|
||||
|
||||
return bool(self.selectedItems(user_only=True))
|
||||
return bool(self.selectedItems(user_only=True)) # 返回当前用户选择的项目是否为空
|
||||
|
||||
def has_single_selection(self):
|
||||
def has_single_selection(self):# 检查是否有单个项目被选择
|
||||
"""Checks whether there's currently exactly one item selected."""
|
||||
|
||||
return len(self.selectedItems(user_only=True)) == 1
|
||||
return len(self.selectedItems(user_only=True)) == 1 # 返回当前用户选择的项目是否只有一个
|
||||
|
||||
def has_multi_selection(self):
|
||||
def has_multi_selection(self):# 检查是否有多个项目被选择
|
||||
"""Checks whether there are currently more than one items selected."""
|
||||
|
||||
return len(self.selectedItems(user_only=True)) > 1
|
||||
return len(self.selectedItems(user_only=True)) > 1 # 返回当前用户选择的项目是否有多个
|
||||
|
||||
def has_single_image_selection(self):
|
||||
def has_single_image_selection(self):# 检查是否有单个图像项目被选择
|
||||
"""Checks whether the current selection is a single image."""
|
||||
|
||||
if self.has_single_selection():
|
||||
return self.selectedItems(user_only=True)[0].is_image
|
||||
return False
|
||||
if self.has_single_selection(): # 如果只有一个项目被选择
|
||||
return self.selectedItems(user_only=True)[0].is_image # 检查该项目是否为图像
|
||||
return False # 如果不是图像或没有项目被选择,返回False
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.MouseButton.RightButton:
|
||||
def mousePressEvent(self, event):# 处理鼠标按下事件
|
||||
if event.button() == Qt.MouseButton.RightButton: # 如果是右键点击
|
||||
# Right-click invokes the context menu on the
|
||||
# GraphicsView. We don't need it here.
|
||||
return
|
||||
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
self.event_start = event.scenePos()
|
||||
if event.button() == Qt.MouseButton.LeftButton: # 如果是左键点击
|
||||
self.event_start = event.scenePos() # 记录鼠标按下时的场景位置
|
||||
item_at_pos = self.itemAt(
|
||||
event.scenePos(), self.views()[0].transform())
|
||||
event.scenePos(), self.views()[0].transform()) # 获取当前鼠标位置上的项目
|
||||
|
||||
if self.edit_item:
|
||||
if item_at_pos != self.edit_item:
|
||||
self.edit_item.exit_edit_mode()
|
||||
else:
|
||||
super().mousePressEvent(event)
|
||||
return
|
||||
if self.crop_item:
|
||||
if item_at_pos != self.crop_item:
|
||||
self.cancel_crop_mode()
|
||||
else:
|
||||
super().mousePressEvent(event)
|
||||
return
|
||||
if item_at_pos:
|
||||
self.active_mode = self.MOVE_MODE
|
||||
elif self.items():
|
||||
self.active_mode = self.RUBBERBAND_MODE
|
||||
if self.edit_item and item_at_pos != self.edit_item: # 如果当前有项目正在编辑状态,且点击的项目不是当前编辑项目
|
||||
self.edit_item.exit_edit_mode() # 退出当前编辑项目的编辑状态
|
||||
elif self.edit_item and item_at_pos == self.edit_item: # 如果当前有项目正在编辑状态,且点击的项目是当前编辑项目
|
||||
super().mousePressEvent(event) # 调用父类的鼠标按下事件处理方法,确保正常编辑操作
|
||||
return # 结束当前方法,避免后续重复处理
|
||||
if self.crop_item and item_at_pos != self.crop_item: # 如果当前有项目正在裁剪状态,且点击的项目不是当前裁剪项目
|
||||
self.cancel_crop_mode() # 取消当前裁剪项目的裁剪状态
|
||||
elif self.crop_item and item_at_pos == self.crop_item: # 如果当前有项目正在裁剪状态,且点击的项目是当前裁剪项目
|
||||
super().mousePressEvent(event) # 调用父类的鼠标按下事件处理方法,确保正常裁剪操作
|
||||
return # 结束当前方法,避免后续重复处理
|
||||
if item_at_pos: # 如果点击的项目存在
|
||||
self.active_mode = self.MOVE_MODE # 切换到移动模式
|
||||
elif self.items(): # 如果场景中存在其他项目
|
||||
self.active_mode = self.RUBBERBAND_MODE # 切换到橡皮筋选择模式
|
||||
|
||||
super().mousePressEvent(event)
|
||||
super().mousePressEvent(event)# 调用父类的鼠标按下事件处理方法,确保正常处理
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
self.cancel_active_modes()
|
||||
item = self.itemAt(event.scenePos(), self.views()[0].transform())
|
||||
if item:
|
||||
if not item.isSelected():
|
||||
item.setSelected(True)
|
||||
if item.is_editable:
|
||||
item.enter_edit_mode()
|
||||
self.mousePressEvent(event)
|
||||
else:
|
||||
def mouseDoubleClickEvent(self, event):# 处理鼠标双击事件
|
||||
self.cancel_active_modes() # 取消所有活动模式,确保没有正在进行的操作干扰
|
||||
item = self.itemAt(event.scenePos(), self.views()[0].transform()) # 获取当前鼠标位置上的项目
|
||||
if item: # 如果点击的项目存在
|
||||
if not item.isSelected(): # 如果项目未被选择
|
||||
item.setSelected(True) # 选择该项目
|
||||
if item.is_editable: # 如果项目可编辑
|
||||
item.enter_edit_mode() # 进入编辑模式
|
||||
self.mousePressEvent(event) # 模拟鼠标按下事件,确保编辑模式正常启动
|
||||
else: # 如果项目不可编辑
|
||||
self.views()[0].fit_rect(
|
||||
self.itemsBoundingRect(items=[item]),
|
||||
toggle_item=item)
|
||||
toggle_item=item) # 调整场景视图,确保点击的项目在可见区域
|
||||
return
|
||||
super().mouseDoubleClickEvent(event)
|
||||
super().mouseDoubleClickEvent(event) # 调用父类的鼠标双击事件处理方法,确保正常处理
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if self.active_mode == self.RUBBERBAND_MODE:
|
||||
if not self.rubberband_item.scene():
|
||||
logger.debug('Activating rubberband selection')
|
||||
self.addItem(self.rubberband_item)
|
||||
self.rubberband_item.bring_to_front()
|
||||
self.rubberband_item.fit(self.event_start, event.scenePos())
|
||||
self.setSelectionArea(self.rubberband_item.shape())
|
||||
self.views()[0].reset_previous_transform()
|
||||
super().mouseMoveEvent(event)
|
||||
def mouseMoveEvent(self, event): # 处理鼠标移动事件
|
||||
if self.active_mode == self.RUBBERBAND_MODE: # 如果当前模式是橡皮筋选择模式
|
||||
if not self.rubberband_item.scene(): # 如果橡皮筋选择项目不在场景中
|
||||
logger.debug('Activating rubberband selection') # 记录调试信息,激活橡皮筋选择模式
|
||||
self.addItem(self.rubberband_item) # 将橡皮筋选择项目添加到场景中
|
||||
self.rubberband_item.bring_to_front() # 将橡皮筋选择项目 bring to front,确保可见
|
||||
self.rubberband_item.fit(self.event_start, event.scenePos()) # 调整橡皮筋选择项目的形状,以适应鼠标移动
|
||||
self.setSelectionArea(self.rubberband_item.shape()) # 设置场景的选择区域为橡皮筋选择项目的形状
|
||||
self.views()[0].reset_previous_transform() # 重置场景视图的前一个变换,确保正常显示
|
||||
super().mouseMoveEvent(event) # 调用父类的鼠标移动事件处理方法,确保正常处理
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if self.active_mode == self.RUBBERBAND_MODE:
|
||||
self.end_rubberband_mode()
|
||||
if (self.active_mode == self.MOVE_MODE
|
||||
and self.has_selection()
|
||||
and self.multi_select_item.active_mode is None
|
||||
and self.selectedItems()[0].active_mode is None):
|
||||
delta = event.scenePos() - self.event_start
|
||||
if not delta.isNull():
|
||||
def mouseReleaseEvent(self, event): # 处理鼠标释放事件
|
||||
if self.active_mode == self.RUBBERBAND_MODE: # 如果当前模式是橡皮筋选择模式
|
||||
self.end_rubberband_mode() # 结束橡皮筋选择模式
|
||||
if (self.active_mode == self.MOVE_MODE # 如果当前模式是移动模式
|
||||
and self.has_selection() # 如果场景中存在选择项目
|
||||
and self.multi_select_item.active_mode is None # 如果多选项目的活动模式为空
|
||||
and self.selectedItems()[0].active_mode is None): # 如果选择项目的活动模式为空
|
||||
delta = event.scenePos() - self.event_start # 计算鼠标移动的距离
|
||||
if not delta.isNull(): # 如果鼠标移动距离不为零
|
||||
self.undo_stack.push(
|
||||
commands.MoveItemsBy(self.selectedItems(),
|
||||
delta,
|
||||
ignore_first_redo=True))
|
||||
self.active_mode = None
|
||||
super().mouseReleaseEvent(event)
|
||||
ignore_first_redo=True)) # 记录移动操作到撤销栈,忽略第一次重做
|
||||
self.active_mode = None # 切换到无活动模式
|
||||
super().mouseReleaseEvent(event) # 调用父类的鼠标释放事件处理方法,确保正常处理
|
||||
|
||||
def selectedItems(self, user_only=False):
|
||||
def selectedItems(self, user_only=False): # 返回场景中当前选择的项目
|
||||
"""If ``user_only`` is set to ``True``, only return items added
|
||||
by the user (i.e. no multi select outlines and other UI items).
|
||||
|
||||
User items are items that have a ``save_id`` attribute.
|
||||
"""
|
||||
|
||||
items = super().selectedItems()
|
||||
items = super().selectedItems() # 获取场景中当前选择的所有项目
|
||||
if user_only:
|
||||
return list(filter(lambda i: hasattr(i, 'save_id'), items))
|
||||
return items
|
||||
return list(filter(lambda i: hasattr(i, 'save_id'), items)) # 如果只返回用户项目,过滤掉没有 save_id 属性的项目
|
||||
return items # 返回所有选择项目
|
||||
|
||||
def items_by_type(self, itype):
|
||||
def items_by_type(self, itype): # 返回场景中所有指定类型的项目
|
||||
"""Returns all items of the given type."""
|
||||
|
||||
return filter(lambda i: getattr(i, 'TYPE', None) == itype,
|
||||
self.items())
|
||||
|
||||
def items_for_save(self):
|
||||
self.items()) # 返回所有类型为 itype 的项目
|
||||
|
||||
def items_for_save(self): # 返回场景中所有可保存的项目
|
||||
"""Returns the items that are to be saved.
|
||||
|
||||
Items to be saved are items that have a save_id attribute.
|
||||
"""
|
||||
|
||||
return filter(lambda i: hasattr(i, 'save_id'),
|
||||
self.items(order=Qt.SortOrder.AscendingOrder))
|
||||
self.items(order=Qt.SortOrder.AscendingOrder)) # 返回所有有 save_id 属性的项目
|
||||
|
||||
def clear_save_ids(self):
|
||||
for item in self.items_for_save():
|
||||
item.save_id = None
|
||||
def clear_save_ids(self): # 清除场景中所有项目的 save_id 属性
|
||||
for item in self.items_for_save():# 遍历所有可保存项目
|
||||
item.save_id = None # 清除项目的 save_id 属性
|
||||
|
||||
def on_view_scale_change(self):
|
||||
for item in self.selectedItems():
|
||||
item.on_view_scale_change()
|
||||
def on_view_scale_change(self): # 处理场景视图缩放变化事件
|
||||
for item in self.selectedItems(): # 遍历当前选择的项目
|
||||
item.on_view_scale_change() # 调用项目的视图缩放变化处理方法,确保正常显示
|
||||
|
||||
def itemsBoundingRect(self, selection_only=False, items=None):
|
||||
def itemsBoundingRect(self, selection_only=False, items=None): # 返回场景中项目的边界矩形
|
||||
"""Returns the bounding rect of the scene's items; either all of them
|
||||
or only selected ones, or the items givin in ``items``.
|
||||
|
||||
Re-implemented to not include the items's selection handles.
|
||||
"""
|
||||
|
||||
def filter_user_items(ilist):
|
||||
return list(filter(lambda i: hasattr(i, 'save_id'), ilist))
|
||||
def filter_user_items(ilist):# 过滤出场景中所有用户项目(有 save_id 属性的项目)
|
||||
return list(filter(lambda i: hasattr(i, 'save_id'), ilist)) # 过滤出场景中所有用户项目(有 save_id 属性的项目)
|
||||
|
||||
if selection_only:
|
||||
base = filter_user_items(self.selectedItems())
|
||||
elif items:
|
||||
base = items
|
||||
else:
|
||||
base = filter_user_items(self.items())
|
||||
|
||||
if not base:
|
||||
return QtCore.QRectF(0, 0, 0, 0)
|
||||
|
||||
x = []
|
||||
y = []
|
||||
if selection_only: # 如果只返回选择项目的边界矩形
|
||||
base = filter_user_items(self.selectedItems()) # 过滤出当前选择的用户项目
|
||||
elif items: # 如果指定了项目列表
|
||||
base = items # 使用指定的项目列表
|
||||
else: # 如果没有指定项目列表
|
||||
base = filter_user_items(self.items()) # 过滤出所有用户项目
|
||||
|
||||
for item in base:
|
||||
for corner in item.corners_scene_coords:
|
||||
x.append(corner.x())
|
||||
y.append(corner.y())
|
||||
if not base: # 如果没有项目可计算边界矩形
|
||||
return QtCore.QRectF(0, 0, 0, 0) # 返回空矩形
|
||||
|
||||
x = [] # 存储所有项目的 x 坐标
|
||||
y = [] # 存储所有项目的 y 坐标
|
||||
|
||||
for item in base: # 遍历所有项目
|
||||
for corner in item.corners_scene_coords: # 遍历项目的所有场景坐标
|
||||
x.append(corner.x()) # 存储项目的 x 坐标
|
||||
y.append(corner.y()) # 存储项目的 y 坐标
|
||||
|
||||
return QtCore.QRectF(
|
||||
QtCore.QPointF(min(x), min(y)),
|
||||
QtCore.QPointF(max(x), max(y)))
|
||||
QtCore.QPointF(min(x), min(y)), # 计算所有项目的最小坐标点
|
||||
QtCore.QPointF(max(x), max(y))) # 计算所有项目的最大坐标点
|
||||
|
||||
def get_selection_center(self):
|
||||
rect = self.itemsBoundingRect(selection_only=True)
|
||||
return (rect.topLeft() + rect.bottomRight()) / 2
|
||||
def get_selection_center(self): # 返回场景中当前选择项目的中心坐标
|
||||
rect = self.itemsBoundingRect(selection_only=True) # 获取当前选择项目的边界矩形
|
||||
return (rect.topLeft() + rect.bottomRight()) / 2 # 返回矩形的中心坐标
|
||||
|
||||
def on_selection_change(self):
|
||||
def on_selection_change(self): # 处理场景选择变化事件
|
||||
if self._clear_ongoing:
|
||||
# Ignore events while clearing the scene since the
|
||||
# multiselect item will get cleared, too
|
||||
return
|
||||
if self.has_multi_selection():
|
||||
self.multi_select_item.fit_selection_area(
|
||||
self.itemsBoundingRect(selection_only=True))
|
||||
if self.has_multi_selection() and not self.multi_select_item.scene():
|
||||
self.addItem(self.multi_select_item)
|
||||
self.multi_select_item.bring_to_front()
|
||||
if not self.has_multi_selection() and self.multi_select_item.scene():
|
||||
self.removeItem(self.multi_select_item)
|
||||
if self.has_multi_selection():# 如果有多个项目被选择
|
||||
self.multi_select_item.fit_selection_area(
|
||||
self.itemsBoundingRect(selection_only=True)) # 调整多选框的大小以适应选择项目的边界矩形
|
||||
if self.has_multi_selection() and not self.multi_select_item.scene(): # 如果有多个项目被选择且多选框不在场景中
|
||||
self.addItem(self.multi_select_item) # 将多选框添加到场景中
|
||||
self.multi_select_item.bring_to_front() # 将多选框 bring_to_front 到最前面
|
||||
if not self.has_multi_selection() and self.multi_select_item.scene(): # 如果没有项目被选择且多选框在场景中
|
||||
self.removeItem(self.multi_select_item) # 从场景中移除多选框
|
||||
|
||||
def on_change(self, region):
|
||||
if self._clear_ongoing:
|
||||
def on_change(self, region): # 处理场景变化事件
|
||||
if self._clear_ongoing: # 如果场景正在清除中
|
||||
# Ignore events while clearing the scene since the
|
||||
# multiselect item will get cleared, too
|
||||
return
|
||||
if (self.multi_select_item.scene()
|
||||
and self.multi_select_item.active_mode is None):
|
||||
if (self.multi_select_item.scene() # 如果多选框在场景中
|
||||
and self.multi_select_item.active_mode is None): # 且多选框未激活任何模式
|
||||
self.multi_select_item.fit_selection_area(
|
||||
self.itemsBoundingRect(selection_only=True))
|
||||
self.itemsBoundingRect(selection_only=True)) # 调整多选框的大小以适应选择项目的边界矩形
|
||||
|
||||
def add_item_later(self, itemdata, selected=False):
|
||||
def add_item_later(self, itemdata, selected=False): # 保持一个项目稍后添加,通过 ``add_queued_items`` 添加
|
||||
"""Keep an item for adding later via ``add_queued_items``
|
||||
|
||||
:param dict itemdata: Defines the item's data
|
||||
:param bool selected: Whether the item is initialised as selected
|
||||
"""
|
||||
|
||||
self.items_to_add.put((itemdata, selected))
|
||||
self.items_to_add.put((itemdata, selected)) # 将项目数据和选择状态添加到稍后添加队列中
|
||||
|
||||
def add_queued_items(self):
|
||||
def add_queued_items(self): # 添加稍后添加队列中的项目
|
||||
"""Adds items added via ``add_item_later``"""
|
||||
|
||||
while not self.items_to_add.empty():
|
||||
data, selected = self.items_to_add.get()
|
||||
typ = data.pop('type')
|
||||
cls = item_registry.get(typ)
|
||||
if not cls:
|
||||
while not self.items_to_add.empty(): # 循环直到稍后添加队列为空
|
||||
data, selected = self.items_to_add.get() # 从稍后添加队列中获取项目数据和选择状态
|
||||
typ = data.pop('type') # 从项目数据中弹出项目类型
|
||||
cls = item_registry.get(typ) # 从项目类型中获取项目类
|
||||
if not cls: # 如果项目类型未知
|
||||
# Just in case we add new item types in future versions
|
||||
logger.warning(f'Encountered item of unknown type: {typ}')
|
||||
cls = BeeErrorItem
|
||||
data['data'] = {'text': f'Item of unknown type: {typ}'}
|
||||
item = cls.create_from_data(**data)
|
||||
logger.warning(f'Encountered item of unknown type: {typ}') # 记录警告日志,提示未知项目类型
|
||||
cls = BeeErrorItem # 默认使用 BeeErrorItem 类
|
||||
data['data'] = {'text': f'Item of unknown type: {typ}'} # 为未知项目类型添加默认文本数据
|
||||
item = cls.create_from_data(**data) # 创建项目实例
|
||||
# Set the values common to all item types:
|
||||
item.update_from_data(**data)
|
||||
self.addItem(item)
|
||||
item.update_from_data(**data) # 更新项目实例的属性值
|
||||
self.addItem(item) # 将项目实例添加到场景中
|
||||
# Force recalculation of min/max z values:
|
||||
item.setZValue(item.zValue())
|
||||
item.setZValue(item.zValue()) # 强制重新计算项目实例的 z 值
|
||||
if selected:
|
||||
item.setSelected(True)
|
||||
item.bring_to_front()
|
||||
item.setSelected(True) # 设置项目实例为选中状态
|
||||
item.bring_to_front() # 将项目实例 bring_to_front 到最前面
|
||||
|
|
|
|||
Loading…
Reference in a new issue