본문 바로가기
코딩취미/Python

QGraphicsLineItem, QGraphicsTextItem 인터렉티브 강화 코드 (mouse over/hover/click event 처리)

by 브링블링 2024. 5. 3.
반응형

QGraphicsLineItem 인터렉티브 강화 코드 (mouse over/hover/click event 처리)

사용자 반응을 더 적절하게 만들기 위해서 인터렉티브 코드를 추가합니다. 테스트코드는 GraphicsLineItem 위로 마우스가 올라가면, line의 색상을 파란색으로 변경하는 코드와 QGraphicsLineItem 을 마우스로 클릭하면, line의 색상이 빨간색으로 변경되는 코드 입니다.

 

코드에서 추가되는 사항은 아래와 같습니다.

  • Initialization (__init__): 줄 항목은 기본적으로 검은색 펜으로 초기화됩니다. 마우스가 줄 위에 있을 때를 감지하기 위해 호버 이벤트가 활성화됩니다. 
  • Hover Events (hoverEnterEvent and hoverLeaveEvent): 마우스가 호버링을 하고 라인을 떠날 때 이 이벤트들은 색상 변화를 처리합니다. 호버링을 하면 색상이 파란색으로 바뀌고 마우스가 떠날 때 검은색으로 바뀝니다.
  • Mouse Click Event (mousePressEvent): 선을 클릭하면 선의 색상이 빨간색으로 바뀝니다. 선이 클릭된 위치를 보여주는 메시지 상자도 나타납니다.
from PyQt5.QtWidgets import QGraphicsLineItem, QMessageBox
from PyQt5.QtGui import QPen
from PyQt5.QtCore import Qt

class InteractiveLineItem(QGraphicsLineItem):
    def __init__(self, line, parent=None):
        super().__init__(line, parent)
        self.setToolTip(f"Line : ({line.x1()}, {line.y1()}) -> ({line.x2()}, {line.y2()})")
        
        # Set the default pen color and width
        self.setPen(QPen(Qt.black, 2))
        
        # Enable hover events
        self.setAcceptHoverEvents(True)
    
    def hoverEnterEvent(self, event):
        # Change the color to blue when the mouse hovers over
        self.setPen(QPen(Qt.blue, 2))
        super().hoverEnterEvent(event)
    
    def hoverLeaveEvent(self, event):
        # Revert the color to black when the mouse leaves
        self.setPen(QPen(Qt.black, 2))
        super().hoverLeaveEvent(event)

    def mousePressEvent(self, event):
        # Change the color to red when the line is clicked
        self.setPen(QPen(Qt.red, 2))
        QMessageBox.information(None, "Line Clicked", f"line from ({self.line().x1()}, {self.line().y1()}) to ({self.line().x2()}, {self.line().y2()})")
        super().mousePressEvent(event)

 

여기에서 마우스를 클릭해서 색상을 변경했을 때, hoverLevaveEvent가 색상을 다시 변경시켜. 마우스가 클릭됐을 때 색상이 변경되는 코드로 수정하려면,  QPen의 색상을 변경할 때마다 추적하고 업데이트하기 위해 현재 펜의 색상을 저장하는 속성을 추가해야합니다. 그러면 색상 정보가 변경될 때마다 확인하고 업데이트할 수 있습니다. 

  • Added currentPenColor attribute현재 펜의 색상을 저장합니다. updatePenColor 메서드를 통해 펜 색상이 변경될 때마다 업데이트됩니다.
  • Created updatePenColor method: 이 메서드는 새 색상이 현재 색상과 다른지 확인합니다. 해당하는 경우 펜과 현재 PenColor 속성을 업데이트합니다. 또한 색상 업데이트가 발생하는 시기를 추적하기 위한 디버그 출력을 제공하므로 개발 및 디버깅 중에 특히 유용할 수 있습니다.
from PyQt5.QtWidgets import QGraphicsLineItem, QMessageBox
from PyQt5.QtGui import QPen
from PyQt5.QtCore import Qt

class InteractiveLineItem(QGraphicsLineItem):
    def __init__(self, line, parent=None):
        super().__init__(line, parent)
        self.setToolTip(f"Line : ({line.x1()}, {line.y1()}) -> ({line.x2()}, {line.y2()})")
        
        # Set the default pen color and width
        self.defaultPen = QPen(Qt.black, 2)
        self.setPen(self.defaultPen)
        
        # Store the current pen color for tracking changes
        self.currentPenColor = self.pen().color()
        
        # Enable hover events
        self.setAcceptHoverEvents(True)

        # Initialize clicked state
        self.clicked = False
    
    def updatePenColor(self, color):
        """ Update the pen color and track the change """
        if self.currentPenColor != color:
            self.setPen(QPen(color, 2))
            self.currentPenColor = color
            print(f"Pen color updated to: {color.name()}")  # Debug output to track color updates
    
    def hoverEnterEvent(self, event):
        # Change the color to blue when the mouse hovers over, if not clicked
        if not self.clicked:
            self.updatePenColor(Qt.blue)
        super().hoverEnterEvent(event)
    
    def hoverLeaveEvent(self, event):
        # Revert the color to black only if the line has not been clicked
        if not self.clicked:
            self.updatePenColor(Qt.black)
        super().hoverLeaveEvent(event)

    def mousePressEvent(self, event):
        # Change the color to red when the line is clicked and update the clicked state
        self.updatePenColor(Qt.red)
        self.clicked = True  # Set the clicked state to True to retain the red color
        QMessageBox.information(None, "Line Clicked", f"line from ({self.line().x1()}, {self.line().y1()}) to ({self.line().x2()}, {self.line().y2()})")
        super().mousePressEvent(event)

 

추가로 QGraphicsTextItem 아이템으로 생성한 객체에 대해서도 사용자 인터렉티브를 강화하는 코드는 다음과 같습니다.

아래코드는 선언된 텍스트 위에 마우스가 올라가면 색상이 변경됐다가, 마우스로 클릭하면 굵은 글씨체로 변경하는 코드입니다.

반응형
from PyQt5.QtWidgets import QGraphicsTextItem, QMessageBox
from PyQt5.QtGui import QPen, QFont, QColor
from PyQt5.QtCore import Qt

class InteractiveTextItem(QGraphicsTextItem):
    def __init__(self, text, msg, font_size, parent=None):
        super().__init__(text, parent)
        self.setToolTip(f"{msg}")
        self.msgText = msg
        self.font_size = font_size

        self.setDefaultTextColor(Qt.black)
        self.setFont(QFont("Arial", 10))
        self.setAcceptHoverEvents(True)
        self.clicked = False
        self.currentTextColor = Qt.black

    def updateMsg(self, msg):
        self.msgText = msg
        self.setToolTip(self.msgText)

    def updateTextColor(self, color):
        if self.currentTextColor != color:
            self.setDefaultTextColor(color)
            self.currentTextColor = color

    def hoverEnterEvent(self, event):
        if not self.clicked:
            #self.setDefaultTextColor(Qt.magenta)
            self.updateTextColor(Qt.magenta)
        super().hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        if not self.clicked:
            #self.setDefaultTextColor(Qt.black)
            self.updateTextColor(Qt.black)
        super().hoverLeaveEvent(event)

    def mousePressEvent(self, event):
        if not self.clicked:
            self.clicked = True
            self.setFont(QFont("Arial", 10, weight=QFont.Weight.Bold))
            #self.setDefaultTextColor(Qt.red)
            self.updateTextColor(Qt.red)
        else:
            self.clicked = False
            self.setFont(QFont("Arial", self.font_size))
            #self.setDefaultTextColor(Qt.black)

        QMessageBox.information(None, "Text Clicked", f"{self.msgText}")
        super().mousePressEvent(event)

반응형