You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:26:21