PyQt6文本粗体切换异常:全选加粗文本无法取消格式
问题:PyQt6文本编辑器无法正确切换选中文本的粗体格式
我正在用Python和PyQt6开发自定义文字处理器作为个人项目,编写了如下代码,意图实现选中文本按Ctrl-B切换粗体:若选中文本全为粗体则取消,否则添加粗体格式。
class OvidFont: def __init__(self, ovid) -> None: self.textEditor = ovid.textEditor def setBoldText(self) -> None: fmt = QTextCharFormat() if self.textEditor.currentCharFormat().fontWeight() != QFont.Weight.Bold: print(" setting bold") # for debugging fmt.setFontWeight(QFont.Weight.Bold) else: print(" setting normal") # for debugging fmt.setFontWeight(QFont.Weight.Normal) self.textEditor.textCursor().mergeCharFormat(fmt)
实际运行时无法取消粗体:如选中“this is a test”里的“is a”设为粗体后,保持选中按Ctrl-B,粗体仍存在;但取消选中首尾任一字符时,切换功能正常。反转if/else逻辑也无效。
已添加可运行最小测试案例。
解决方案
问题出在currentCharFormat()的使用上:这个方法仅返回光标当前所在位置的字符格式,而非选中范围内所有字符的统一格式。当你选中一段混合格式的文本(比如部分粗体、部分正常)时,它只会取光标停留位置的格式来判断,导致逻辑判断错误。
比如你选中已加粗的“is a”后,光标可能停留在粗体字符上,此时currentCharFormat()会返回粗体格式,代码会执行取消粗体的逻辑,但mergeCharFormat()是合并格式——对于已经是粗体的字符,合并正常格式不会改变它的粗体属性,所以粗体依然存在。
要解决这个问题,需要遍历选中范围内的所有字符,检查它们的格式是否全部为粗体,再执行对应的切换逻辑:
from PyQt6.QtGui import QTextCharFormat, QFont, QTextCursor class OvidFont: def __init__(self, ovid) -> None: self.textEditor = ovid.textEditor def setBoldText(self) -> None: cursor = self.textEditor.textCursor() # 处理无选中内容的情况:切换光标所在位置的格式 if not cursor.hasSelection(): current_weight = cursor.charFormat().fontWeight() fmt = QTextCharFormat() fmt.setFontWeight(QFont.Weight.Bold if current_weight != QFont.Weight.Bold else QFont.Weight.Normal) cursor.mergeCharFormat(fmt) self.textEditor.setTextCursor(cursor) return # 处理有选中内容的情况:检查所有选中字符是否全为粗体 start_pos = cursor.selectionStart() end_pos = cursor.selectionEnd() all_bold = True # 遍历选中范围内的每个字符 temp_cursor = QTextCursor(self.textEditor.document()) temp_cursor.setPosition(start_pos) while temp_cursor.position() < end_pos: if temp_cursor.charFormat().fontWeight() != QFont.Weight.Bold: all_bold = False break temp_cursor.movePosition(QTextCursor.MoveOperation.NextCharacter) # 重置光标到原选中范围,应用格式 cursor.setPosition(start_pos) cursor.setPosition(end_pos, QTextCursor.MoveMode.KeepAnchor) fmt = QTextCharFormat() fmt.setFontWeight(QFont.Weight.Normal if all_bold else QFont.Weight.Bold) cursor.mergeCharFormat(fmt) self.textEditor.setTextCursor(cursor)
代码说明
- 区分无选中和有选中两种场景:无选中时直接切换光标处的格式;
- 有选中时,创建临时光标遍历选中范围的所有字符,判断是否全部为粗体;
- 根据判断结果设置对应的格式,再应用到选中范围,确保所有字符统一切换粗体状态。
内容的提问来源于stack exchange,提问作者Ovid
相关产品推荐
相关产品推荐

