QGraphicsItemGroup中的QLineEdit无法获取焦点的技术求助
问题:QGraphicsItemGroup内嵌套的QLineEdit无法获取焦点输入
我正在开发自定义PySide6应用,QGraphicsView中包含各类自定义项,其中QLineEdit嵌套在QGraphicsProxyWidget内,且该代理部件隶属于QGraphicsItemGroup。但点击QLineEdit时,它无法获取焦点,也无法输入文本。
已尝试为QLineEdit和QGraphicsProxyWidget设置焦点策略,也为QGraphicsProxyWidget设置了ItemIsFocusable标志,但点击QLineEdit仍无法触发焦点或输入,仅鼠标悬停时光标会变化。
希望实现点击QLineEdit时它能获取焦点并允许文本输入,同时整个QGraphicsItemGroup仍可移动。
复现问题的最小代码示例
import sys from PySide6.QtCore import Qt, QPointF from PySide6.QtGui import QBrush, QPen, QPainter, QColor from PySide6.QtWidgets import ( QApplication, QGraphicsItem, QGraphicsRectItem, QGraphicsScene, QGraphicsView, QVBoxLayout, QWidget, QGraphicsTextItem, QGraphicsLineItem, QGraphicsItemGroup, QLineEdit, QGraphicsProxyWidget ) class CompositeItem(QGraphicsItemGroup): def __init__(self, x=0, y=0): super().__init__() self.setPos(x, y) rect = QGraphicsRectItem(0, 0, 100, 50, self) rect.setBrush(QBrush(QColor(255, 0, 0, 100))) # Semi-transparent red rect.setPen(QPen(Qt.GlobalColor.black, 2)) self.addToGroup(rect) line = QGraphicsLineItem(0, 0, 100, 100, self) line.setPen(QPen(Qt.GlobalColor.green, 2, Qt.PenStyle.DashLine)) self.addToGroup(line) text = QGraphicsTextItem("Test Item", self) text.setDefaultTextColor(Qt.GlobalColor.darkMagenta) text.setPos(10, -30) # Position above the other components self.addToGroup(text) self.line_edit = QLineEdit("Edit me") self.line_edit.setFixedWidth(100) self.line_edit.setFocusPolicy(Qt.FocusPolicy.ClickFocus) self.line_edit_proxy = QGraphicsProxyWidget(self) self.line_edit_proxy.setWidget(self.line_edit) self.line_edit_proxy.setPos(0, 55) self.line_edit_proxy.setFocusPolicy(Qt.FocusPolicy.ClickFocus) self.line_edit_proxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsFocusable) self.addToGroup(self.line_edit_proxy) self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable) self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable) def mousePressEvent(self, event): self.line_edit_proxy.setFocus() # Set focus when the item is clicked super().mousePressEvent(event) class CustomCanvas(QGraphicsView): def __init__(self): super().__init__() self.scene = QGraphicsScene(0, 0, 600, 400) self.setScene(self.scene) self.setRenderHint(QPainter.RenderHint.Antialiasing) self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.setInteractive(True) self.add_items() def add_items(self): comp = CompositeItem(100, 100) self.scene.addItem(comp) app = QApplication(sys.argv) window = QWidget() layout = QVBoxLayout(window) canvas = CustomCanvas() layout.addWidget(canvas) window.setLayout(layout) window.show() sys.exit(app.exec())
原代码还包含平移、缩放和对齐网格功能,为简化示例已移除,该代码也可在PyQt6或PyQt5中运行。
解决方案
1. 重写CompositeItem的mousePressEvent,区分点击区域
QGraphicsItemGroup会拦截子项事件,所以需要在组的鼠标事件中判断点击位置是否属于代理部件,针对性处理焦点和事件传递:
def mousePressEvent(self, event): # 将场景坐标转换为代理部件的局部坐标 proxy_local_pos = self.line_edit_proxy.mapFromScene(event.scenePos()) if self.line_edit_proxy.boundingRect().contains(proxy_local_pos): # 点击的是代理内的QLineEdit,直接让输入框获取焦点 self.line_edit.setFocus() # 阻止事件传递,避免组触发移动逻辑 return # 点击组内其他区域,正常执行移动逻辑 super().mousePressEvent(event)
2. 优化焦点策略设置
将QLineEdit和代理部件的焦点策略改为StrongFocus,确保焦点获取更可靠:
self.line_edit.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.line_edit_proxy.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
修改后的完整CompositeItem类
class CompositeItem(QGraphicsItemGroup): def __init__(self, x=0, y=0): super().__init__() self.setPos(x, y) rect = QGraphicsRectItem(0, 0, 100, 50, self) rect.setBrush(QBrush(QColor(255, 0, 0, 100))) # Semi-transparent red rect.setPen(QPen(Qt.GlobalColor.black, 2)) self.addToGroup(rect) line = QGraphicsLineItem(0, 0, 100, 100, self) line.setPen(QPen(Qt.GlobalColor.green, 2, Qt.PenStyle.DashLine)) self.addToGroup(line) text = QGraphicsTextItem("Test Item", self) text.setDefaultTextColor(Qt.GlobalColor.darkMagenta) text.setPos(10, -30) # Position above the other components self.addToGroup(text) self.line_edit = QLineEdit("Edit me") self.line_edit.setFixedWidth(100) self.line_edit.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.line_edit_proxy = QGraphicsProxyWidget(self) self.line_edit_proxy.setWidget(self.line_edit) self.line_edit_proxy.setPos(0, 55) self.line_edit_proxy.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.line_edit_proxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsFocusable) self.addToGroup(self.line_edit_proxy) self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable) self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable) def mousePressEvent(self, event): proxy_local_pos = self.line_edit_proxy.mapFromScene(event.scenePos()) if self.line_edit_proxy.boundingRect().contains(proxy_local_pos): self.line_edit.setFocus() return super().mousePressEvent(event)
修改后,点击QLineEdit时会直接获取焦点并允许输入,点击组内其他区域则可以正常移动整个ItemGroup。
内容的提问来源于stack exchange,提问作者Drimer
相关产品推荐
相关产品推荐

