QGraphicsItemGroup 内的 QLineEdit 未获得焦点

问题描述 投票:0回答:1

我正在创建一个自定义 PySide6 应用程序,其中包含各种自定义项的 QGraphicsView,包括 QGraphicsProxyWidget 内的 QLineEdit,它是 QGraphicsItemGroup 的一部分。但是,我无法在 QLineEdit 中输入内容,并且单击时似乎没有获得焦点。

这是说明该问题的最小代码示例:

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 运行。

我正在尝试设置 QLineEdit,以便它获得焦点并允许在单击时输入文本。整个小组应该仍然可以移动。

问题

  • QLineEdit 无法接收焦点或不允许输入。

我尝试在 QLineEdit 和 QGraphicsProxyWidget 上设置焦点策略,并且还在 QGraphicsProxyWidget 上设置 ItemIsFocusable 标志。但是,单击 QLineEdit 不会启用键入或触发焦点,尽管我在悬停 QLineEdit 时看到光标发生了变化。

问题

  • 如何确保 QGraphicsProxyWidget 内的 QLineEdit 获得焦点?
  • 允许在 QGraphicsItemGroup 内的 QLineEdit 中输入文本是否需要额外的步骤?
python qgraphicsview pyside6 pyqt6
1个回答
0
投票

文档建议如下:

如果您只想将项目存储在其他项目中,则可以通过将合适的父级传递给 setParentItem() 来直接使用任何 QGraphicsItem。

这是使用此建议实现的具有可聚焦和可编辑线条编辑的可移动矩形项目的示例:

import sys
from PySide6.QtCore import Qt
from PySide6.QtGui import QBrush, QPen, QColor
from PySide6.QtWidgets import (
    QApplication, QGraphicsItem, QGraphicsRectItem,
    QGraphicsScene, QGraphicsView, QVBoxLayout, QWidget,
    QLineEdit, QGraphicsProxyWidget
)

app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout(window)
canvas = QGraphicsView()
scene = QGraphicsScene(0, 0, 600, 400)
canvas.setScene(scene)

rect = QGraphicsRectItem(0, 0, 100, 50)
rect.setBrush(QBrush(QColor(255, 0, 0, 100)))
rect.setPen(QPen(Qt.GlobalColor.black, 2))
rect.setPos(100, 100)
rect.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable)

line_edit = QLineEdit("Edit me")
line_edit.setFixedWidth(100)

line_edit_proxy = QGraphicsProxyWidget()
line_edit_proxy.setWidget(line_edit)
line_edit_proxy.setPos(0, 55)
line_edit_proxy.setParentItem(rect)

scene.addItem(rect)

layout.addWidget(canvas)
window.setLayout(layout)
window.show()
sys.exit(app.exec())

如果您坚持使用

QGraphicsItemGroup
,您可以通过将事件转发到子项目来解决问题,如下所示:

import sys
from PySide6.QtCore import Qt, QPointF, QTimer
from PySide6.QtGui import QBrush, QPen, QPainter, QColor
from PySide6.QtWidgets import (
    QApplication, QGraphicsItem, QGraphicsRectItem,
    QGraphicsScene, QGraphicsSceneMouseEvent, QGraphicsView, QVBoxLayout, QWidget, QGraphicsTextItem, QGraphicsLineItem, QGraphicsItemGroup,
    QLineEdit, QGraphicsProxyWidget
)

class CompositeItem(QGraphicsItemGroup):
    def __init__(self, x=0, y=0):
        super().__init__()

        self.setPos(x, y)

        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsFocusable)
        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable)
        self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable)

        rect = QGraphicsRectItem(0, 0, 100, 50, self)
        rect.setBrush(QBrush(QColor(255, 0, 0, 100)))
        rect.setPen(QPen(Qt.GlobalColor.black, 2))
        self.addToGroup(rect)

        self.line_edit = QLineEdit("Edit me")
        self.line_edit.setFixedWidth(100)
        
        self.line_edit_proxy = QGraphicsProxyWidget(self)
        self.line_edit_proxy.setWidget(self.line_edit)
        self.line_edit_proxy.setPos(0, 55)
        self.addToGroup(self.line_edit_proxy)

        self._mouse_in_line_edit = False

    def mousePressEvent(self, event):
        rect = self.line_edit_proxy.sceneBoundingRect()
        self._mouse_in_line_edit = rect.contains(event.scenePos())
        if self._mouse_in_line_edit:
            self.line_edit_proxy.mousePressEvent(event)
            self.line_edit.setFocus()
        else:
            super().mousePressEvent(event)

    def mouseMoveEvent(self, event) -> None:
        if self._mouse_in_line_edit:
            self.line_edit_proxy.mouseMoveEvent(event)
        else:
            super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event) -> None:
        if self._mouse_in_line_edit:
            self.line_edit_proxy.mouseReleaseEvent(event)
        else:
            super().mouseMoveEvent(event)

    def keyPressEvent(self, event) -> None:
        if self.line_edit.hasFocus():
            self.line_edit_proxy.keyPressEvent(event)
        else:
            super().keyPressEvent(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.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())

这种方法存在问题,例如有时鼠标按下时项目会跳转。

© www.soinside.com 2019 - 2024. All rights reserved.