Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Inconsistent borders when drawing a custom translucent widget using QPainterPath
Forum Updated to NodeBB v4.3 + New Features

Inconsistent borders when drawing a custom translucent widget using QPainterPath

Scheduled Pinned Locked Moved Unsolved General and Desktop
1 Posts 1 Posters 106 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    ParikshitT.
    wrote on last edited by
    #1

    Hi,
    I am trying to draw a widget with a triangular tip at the bottom with the help of this guide. The shape is drawn as expected but trying to add a border to it makes it sag from the bottom:

    Arrow pointing at a red border which is wider than the other sides of the window

    This is my first attempt at making a custom shaped widget and would appreciate if someone could help me in figuring this out :)
    Please note that the code is in python but I do not mind looking at C++ sources and documentation.

    import typing as _t
    
    from Qt import (
        QtCore as _QtCore,
        QtGui as _QtGui,
        QtWidgets as _QtWidgets,
    )
    
    
    class _TipTriangleDimensions(_t.NamedTuple):
        height: float = 15.0
        base: float = 20.0
    
    
    class _TipTriangleCords(_t.NamedTuple):
        origin: _QtCore.QPointF
        tip: _QtCore.QPointF
        base: _QtCore.QPointF
    
    
    class QBalloonTip(_QtWidgets.QWidget):
        def __init__(
            self, message: str, parent: _t.Optional[_QtWidgets.QWidget] = None
        ) -> None:
            super().__init__(
                parent=parent,
                f=_QtCore.Qt.FramelessWindowHint,
            )
            self.setAttribute(_QtCore.Qt.WA_TranslucentBackground)
            main_layout = _QtWidgets.QVBoxLayout()
            self._setup_ui(main_layout)
            self._message_label.setText(message)
            self._mask_path: _QtGui.QPainterPath = self._get_mask_shape_path(
                _TipTriangleDimensions()
            )
    
        def paintEvent(self, event):
            painter = _QtGui.QPainter(self)
            painter.setRenderHint(_QtGui.QPainter.RenderHint.Antialiasing)
            painter.setBrush(_QtGui.QBrush(_QtCore.Qt.white))
            border_pen = _QtGui.QPen()
            border_pen.setWidthF(6.0)
            border_pen.setColor(_QtCore.Qt.red)
            painter.setPen(border_pen)
            painter.drawPath(self._mask_path)
    
        def _get_mask_shape_path(self, triangle_d: _TipTriangleDimensions) -> _QtGui.QPainterPath:
            self.setContentsMargins(0, 0, 0, int(triangle_d.height))
            self.updateGeometry()
            self_sz = _QtCore.QSizeF(self.sizeHint())
    
            triangle_cords = self._get_triangle_shape_points(self_sz, triangle_d)
    
            origin = _QtCore.QPointF(0.0, 0.0)
            right = _QtCore.QPointF(self_sz.width(), triangle_cords.base.y())
            top = _QtCore.QPointF(self_sz.width(), origin.y())
    
            path = _QtGui.QPainterPath()
            path.moveTo(origin)
            path.lineTo(triangle_cords.tip)
            path.lineTo(triangle_cords.base)
            path.lineTo(right)
            path.lineTo(top)
            path.lineTo(origin)
            return path
    
        @staticmethod
        def _get_triangle_shape_points(
            total_size: _QtCore.QSizeF, dimensions: _TipTriangleDimensions
        ) -> _TipTriangleCords:
            origin = _QtCore.QPointF(0.5, total_size.height() - dimensions.height)
            tip = _QtCore.QPointF(0.0, total_size.height())
            base = _QtCore.QPointF(dimensions.base, origin.y())
            return _TipTriangleCords(origin, tip, base)
    
        def _setup_ui(self, main_layout: _QtWidgets.QVBoxLayout):
            self._message_label = _QtWidgets.QLabel(parent=self)
            self._message_label.setFixedWidth(200)
            self._message_label.setFixedHeight(100)
            self._message_label.setWordWrap(True)
    
            main_layout.addWidget(self._message_label)
            main_layout.addWidget(_QtWidgets.QPushButton("Test"))
            self.setLayout(main_layout)
    
    
    if __name__ == "__main__":
        app = _QtWidgets.QApplication([])
        widget = QBalloonTip("test message")
        widget.show()
        app.exec_()
    
    
    1 Reply Last reply
    0

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved