提交 d2448e5a 编写于 作者: 之一Yo's avatar 之一Yo

添加浮出控件 `Flyout`

上级 fdcb2dcd
# coding:utf-8
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
from qfluentwidgets import (PushButton, Flyout, InfoBarIcon, setTheme, Theme, FlyoutView, FlyoutViewBase,
BodyLabel, setFont, PrimaryPushButton)
class CustomFlyoutView(FlyoutViewBase):
def __init__(self, parent=None):
super().__init__(parent)
self.vBoxLayout = QVBoxLayout(self)
self.label = BodyLabel(
'这是一场「试炼」,我认为这就是一场为了战胜过去的「试炼」,\n只有战胜了那些幼稚的过去,人才能有所成长。')
self.button = PrimaryPushButton('Action')
self.button.setFixedWidth(140)
self.vBoxLayout.setSpacing(12)
self.vBoxLayout.setContentsMargins(20, 16, 20, 16)
self.vBoxLayout.addWidget(self.label)
self.vBoxLayout.addWidget(self.button)
class Demo(QWidget):
def __init__(self):
super().__init__()
# setTheme(Theme.DARK)
# self.setStyleSheet("Demo{background: rgb(32, 32, 32)}")
self.vBoxLayout = QHBoxLayout(self)
self.button1 = PushButton('Click Me', self)
self.button2 = PushButton('Click Me', self)
self.button3 = PushButton('Click Me', self)
self.resize(750, 550)
self.button1.setFixedWidth(150)
self.button2.setFixedWidth(150)
self.button3.setFixedWidth(150)
self.vBoxLayout.addWidget(self.button1, 0, Qt.AlignBottom)
self.vBoxLayout.addWidget(self.button2, 0, Qt.AlignBottom)
self.vBoxLayout.addWidget(self.button3, 0, Qt.AlignBottom)
self.vBoxLayout.setContentsMargins(30, 50, 30, 50)
self.button1.clicked.connect(self.showFlyout1)
self.button2.clicked.connect(self.showFlyout2)
self.button3.clicked.connect(self.showFlyout3)
def showFlyout1(self):
Flyout.create(
icon=InfoBarIcon.SUCCESS,
title='Lesson 4',
content="表达敬意吧,表达出敬意,然后迈向回旋的另一个全新阶段!",
target=self.button1,
parent=self
)
def showFlyout2(self):
view = FlyoutView(
title='杰洛·齐贝林',
content="触网而起的网球会落到哪一侧,谁也无法知晓。\n如果那种时刻到来,我希望「女神」是存在的。\n这样的话,不管网球落到哪一边,我都会坦然接受的吧。",
image='resource/SBR.jpg',
)
# add button to view
button = PushButton('Action')
button.setFixedWidth(120)
view.addWidget(button, align=Qt.AlignRight)
# adjust layout (optional)
view.widgetLayout.insertSpacing(1, 5)
view.widgetLayout.insertSpacing(0, 5)
view.widgetLayout.addSpacing(5)
# show view
Flyout.make(view, self.button2, self)
def showFlyout3(self):
Flyout.make(CustomFlyoutView(), self.button3, self)
if __name__ == '__main__':
# enable dpi scale
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
app = QApplication(sys.argv)
w = Demo()
w.show()
app.exec_()
......@@ -290,70 +290,104 @@
<context>
<name>DialogInterface</name>
<message>
<location filename="../../view/dialog_interface.py" line="37"/>
<location filename="../../view/dialog_interface.py" line="38"/>
<source>Show dialog</source>
<translation>显示对话框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="23"/>
<location filename="../../view/dialog_interface.py" line="24"/>
<source>A frameless message box</source>
<translation>无边框对话框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="31"/>
<location filename="../../view/dialog_interface.py" line="32"/>
<source>A message box with mask</source>
<translation>带遮罩的对话框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="39"/>
<location filename="../../view/dialog_interface.py" line="40"/>
<source>A color dialog</source>
<translation>颜色对话框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="62"/>
<location filename="../../view/dialog_interface.py" line="80"/>
<source>This is a frameless message dialog</source>
<translation>这是一个无边框对话框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="73"/>
<location filename="../../view/dialog_interface.py" line="91"/>
<source>If the content of the message box is veeeeeeeeeeeeeeeeeeeeeeeeeery long, it will automatically wrap like this.</source>
<translation>一生消えない傷でいいな絆創膏の様にいつも包んでよ貴方のそばでわがまま言いたいな一分一秒刻み貴方を知りあたしをあげる~</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="82"/>
<location filename="../../view/dialog_interface.py" line="100"/>
<source>Choose color</source>
<translation>选择颜色</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="72"/>
<location filename="../../view/dialog_interface.py" line="90"/>
<source>This is a message dialog with mask</source>
<translation>这是一个带遮罩的对话框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="53"/>
<location filename="../../view/dialog_interface.py" line="54"/>
<source>Show teaching tip</source>
<translation>显示气泡弹窗</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="47"/>
<location filename="../../view/dialog_interface.py" line="48"/>
<source>A teaching tip</source>
<translation>气泡弹窗</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="87"/>
<location filename="../../view/dialog_interface.py" line="105"/>
<source>With respect, let&apos;s advance towards a new stage of the spin.</source>
<translation>表达敬意吧表达出敬意然后迈向回旋的另一个全新阶段</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="99"/>
<location filename="../../view/dialog_interface.py" line="117"/>
<source>The shortest shortcut is to take a detour.</source>
<translation>最短的捷径就是绕远路绕远路才是我的最短捷径</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="55"/>
<location filename="../../view/dialog_interface.py" line="56"/>
<source>A teaching tip with image and button</source>
<translation>带图片和按钮的气泡弹窗</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="70"/>
<source>Show flyout</source>
<translation>显示浮出控件</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="64"/>
<source>A simple flyout</source>
<translation>简单的浮出控件</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="72"/>
<source>A flyout with image and button</source>
<translation>带图片和按钮的浮出控件</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="134"/>
<source>Believe in the spin, just keep believing!</source>
<translation>相信回旋吧只管相信就是了</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="143"/>
<source>Julius·Zeppeli</source>
<translation>杰洛·齐贝林</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="143"/>
<source>Where the tennis ball will land when it touches the net, no one can predict.
If that moment comes, I hope the &apos;goddess&apos; exists.
In that case, I would accept it no matter which side the ball falls on.</source>
<translation>触网而起的网球会落到哪一侧谁也无法知晓
如果那种时刻到来我希望女神是存在的
这样的话不管网球落到哪一边我都会坦然接受的吧</translation>
</message>
</context>
<context>
<name>ExampleCard</name>
......
......@@ -290,70 +290,104 @@
<context>
<name>DialogInterface</name>
<message>
<location filename="../../view/dialog_interface.py" line="37"/>
<location filename="../../view/dialog_interface.py" line="38"/>
<source>Show dialog</source>
<translation>顯示對話框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="23"/>
<location filename="../../view/dialog_interface.py" line="24"/>
<source>A frameless message box</source>
<translation>無邊框對話框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="31"/>
<location filename="../../view/dialog_interface.py" line="32"/>
<source>A message box with mask</source>
<translation>帶遮罩的對話框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="39"/>
<location filename="../../view/dialog_interface.py" line="40"/>
<source>A color dialog</source>
<translation>顏色對話框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="62"/>
<location filename="../../view/dialog_interface.py" line="80"/>
<source>This is a frameless message dialog</source>
<translation>這是一個無邊框對話框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="73"/>
<location filename="../../view/dialog_interface.py" line="91"/>
<source>If the content of the message box is veeeeeeeeeeeeeeeeeeeeeeeeeery long, it will automatically wrap like this.</source>
<translation>一生消えない傷でいいな絆創膏の様にいつも包んでよ貴方のそばでわがまま言いたいな一分一秒刻み貴方を知りあたしをあげる~</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="82"/>
<location filename="../../view/dialog_interface.py" line="100"/>
<source>Choose color</source>
<translation>選擇顏色</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="72"/>
<location filename="../../view/dialog_interface.py" line="90"/>
<source>This is a message dialog with mask</source>
<translation>這是一個帶遮罩的對話框</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="53"/>
<location filename="../../view/dialog_interface.py" line="54"/>
<source>Show teaching tip</source>
<translation>顯示氣泡彈窗</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="47"/>
<location filename="../../view/dialog_interface.py" line="48"/>
<source>A teaching tip</source>
<translation>氣泡彈窗</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="87"/>
<location filename="../../view/dialog_interface.py" line="105"/>
<source>With respect, let&apos;s advance towards a new stage of the spin.</source>
<translation>表達敬意吧表達出敬意然後邁向回旋的另一個全新階段</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="99"/>
<location filename="../../view/dialog_interface.py" line="117"/>
<source>The shortest shortcut is to take a detour.</source>
<translation>最短的捷徑就是繞遠路繞遠路才是我的最短捷徑</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="55"/>
<location filename="../../view/dialog_interface.py" line="56"/>
<source>A teaching tip with image and button</source>
<translation>帶圖片和按鈕的氣泡彈窗</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="70"/>
<source>Show flyout</source>
<translation>顯示浮出控件</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="64"/>
<source>A simple flyout</source>
<translation>簡單的浮出控件</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="72"/>
<source>A flyout with image and button</source>
<translation>帶圖片和按鈕的浮出控件</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="134"/>
<source>Believe in the spin, just keep believing!</source>
<translation>相信回旋吧隻管相信就是了</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="143"/>
<source>Julius·Zeppeli</source>
<translation>傑洛·齊貝林</translation>
</message>
<message>
<location filename="../../view/dialog_interface.py" line="143"/>
<source>Where the tennis ball will land when it touches the net, no one can predict.
If that moment comes, I hope the &apos;goddess&apos; exists.
In that case, I would accept it no matter which side the ball falls on.</source>
<translation>觸網而起的網球會落到哪一側誰也無法知曉
如果那種時刻到來我希望女神是存在的
這樣的話不管網球落到哪一邊我都會坦然接受的吧</translation>
</message>
</context>
<context>
<name>ExampleCard</name>
......
......@@ -116,6 +116,7 @@
<file>images/logo.png</file>
<file>images/shoko.png</file>
<file>images/Gyro.jpg</file>
<file>images/SBR.jpg</file>
<file>qss/dark/gallery_interface.qss</file>
<file>qss/dark/home_interface.qss</file>
......
# coding:utf-8
from PyQt5.QtCore import Qt
from qfluentwidgets import PushButton, Dialog, MessageBox, ColorDialog, TeachingTip, TeachingTipTailPosition, InfoBarIcon
from qfluentwidgets import (PushButton, Dialog, MessageBox, ColorDialog, TeachingTip, TeachingTipTailPosition,
InfoBarIcon, Flyout, FlyoutView)
from ..common.translator import Translator
from .gallery_interface import GalleryInterface
......@@ -58,6 +59,23 @@ class DialogInterface(GalleryInterface):
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/teaching_tip/demo.py'
)
self.simpleFlyoutButton = PushButton(self.tr('Show flyout'))
self.simpleFlyoutButton.clicked.connect(self.showSimpleFlyout)
self.addExampleCard(
self.tr('A simple flyout'),
self.simpleFlyoutButton,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/flyout/demo.py'
)
self.complexFlyoutButton = PushButton(self.tr('Show flyout'))
self.complexFlyoutButton.clicked.connect(self.showComplexFlyout)
self.addExampleCard(
self.tr('A flyout with image and button'),
self.complexFlyoutButton,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/flyout/demo.py'
)
def showDialog(self):
title = self.tr('This is a frameless message dialog')
content = self.tr(
......@@ -110,4 +128,33 @@ class DialogInterface(GalleryInterface):
button = PushButton('Action')
button.setFixedWidth(120)
t.addWidget(button, align=Qt.AlignRight)
t.show()
\ No newline at end of file
t.show()
def showSimpleFlyout(self):
Flyout.create(
icon=InfoBarIcon.SUCCESS,
title='Lesson 3',
content=self.tr('Believe in the spin, just keep believing!'),
target=self.simpleFlyoutButton,
parent=self.window()
)
def showComplexFlyout(self):
view = FlyoutView(
title=self.tr('Julius·Zeppeli'),
content=self.tr("Where the tennis ball will land when it touches the net, no one can predict. \nIf that moment comes, I hope the 'goddess' exists. \nIn that case, I would accept it no matter which side the ball falls on."),
image=':/gallery/images/SBR.jpg',
)
# add button to view
button = PushButton('Action')
button.setFixedWidth(120)
view.addWidget(button, align=Qt.AlignRight)
# adjust layout (optional)
view.widgetLayout.insertSpacing(1, 5)
view.widgetLayout.insertSpacing(0, 5)
view.widgetLayout.addSpacing(5)
# show view
Flyout.make(view, self.complexFlyoutButton, self.window())
......@@ -12,7 +12,7 @@ Examples are available at https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/ma
:license: GPLv3, see LICENSE for more details.
"""
__version__ = "0.9.8"
__version__ = "0.9.9"
from .components import *
from .common import *
......
......@@ -29,7 +29,7 @@ class TextWrap:
return 1
@classmethod
def wrap(cls, text, width, once=True):
def wrap(cls, text: str, width: int, once=True):
""" Wrap according to string length
Parameters
......@@ -51,6 +51,22 @@ class TextWrap:
is_wrapped: bool
whether a line break occurs in the text
"""
texts = text.strip().split('\n')
result = []
is_wrapped = False
for text in texts:
text_wrapped, wrapped = cls._wrap_line(text, width, once)
is_wrapped |= wrapped
result.append(text_wrapped)
if once:
result.extend(texts[1:])
break
return '\n'.join(result), is_wrapped
@classmethod
def _wrap_line(cls, text: str, width: int, once=True):
count = 0
last_count = 0
chars = []
......@@ -60,7 +76,6 @@ class TextWrap:
n_inside_break = 0
i = 0
text = text.strip()
while i < len(text):
c = text[i]
length = cls.get_width(c)
......
......@@ -28,4 +28,5 @@ from .cycle_list_widget import CycleListWidget
from .progress_bar import IndeterminateProgressBar, ProgressBar
from .progress_ring import ProgressRing
from .scroll_bar import ScrollBar, SmoothScrollBar, SmoothScrollDelegate
from .teaching_tip import TeachingTip, TeachingTipTailPosition
\ No newline at end of file
from .teaching_tip import TeachingTip, TeachingTipTailPosition
from .flyout import FlyoutView, FlyoutViewBase, Flyout
\ No newline at end of file
# coding:utf-8
from typing import Union
from PyQt5.QtCore import Qt, QPropertyAnimation, QPoint, QParallelAnimationGroup, QEasingCurve, QMargins, QRectF
from PyQt5.QtGui import QPixmap, QPainter, QColor, QCursor, QIcon, QImage, QPainterPath, QBrush
from PyQt5.QtWidgets import QWidget, QGraphicsDropShadowEffect, QLabel, QHBoxLayout, QVBoxLayout, QApplication
from ...common.auto_wrap import TextWrap
from ...common.style_sheet import isDarkTheme, FluentStyleSheet
from ...common.icon import FluentIconBase
from .teaching_tip import IconWidget
class FlyoutViewBase(QWidget):
""" Flyout view base class """
def __init__(self, parent=None):
super().__init__(parent=parent)
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing)
painter.setBrush(
QColor(40, 40, 40) if isDarkTheme() else QColor(248, 248, 248))
painter.setPen(
QColor(23, 23, 23) if isDarkTheme() else QColor(195, 195, 195))
rect = self.rect().adjusted(1, 1, -1, -1)
painter.drawRoundedRect(rect, 8, 8)
class FlyoutView(FlyoutViewBase):
""" Flyout view """
def __init__(self, title: str, content: str, icon: Union[FluentIconBase, QIcon, str] = None,
image: Union[str, QPixmap, QImage] = None, parent=None):
super().__init__(parent=parent)
"""
Parameters
----------
title: str
the title of teaching tip
content: str
the content of teaching tip
icon: InfoBarIcon | FluentIconBase | QIcon | str
the icon of teaching tip
image: str | QPixmap | QImage
the image of teaching tip
parent: QWidget
parent widget
"""
self.icon = icon
self.title = title
self.content = content
self.image = image
if isinstance(image, str):
self.image = QImage(image)
elif isinstance(image, QPixmap):
self.image = image.toImage()
elif not self.image:
self.image = QImage()
self.originImage = QImage(self.image)
self.viewLayout = QHBoxLayout(self)
self.widgetLayout = QVBoxLayout()
self.titleLabel = QLabel(title, self)
self.contentLabel = QLabel(content, self)
self.iconWidget = IconWidget(icon, self)
self.__initWidgets()
def __initWidgets(self):
self.titleLabel.setVisible(bool(self.title))
self.contentLabel.setVisible(bool(self.content))
self.iconWidget.setHidden(self.icon is None)
self.titleLabel.setObjectName('titleLabel')
self.contentLabel.setObjectName('contentLabel')
FluentStyleSheet.TEACHING_TIP.apply(self)
self.__initLayout()
def __initLayout(self):
self.widgetLayout.setContentsMargins(0, 8, 0, 8)
self.viewLayout.setSpacing(4)
self.widgetLayout.setSpacing(0)
# add icon widget
if not self.title or not self.content:
self.iconWidget.setFixedHeight(36)
self.viewLayout.addWidget(self.iconWidget, 0, Qt.AlignTop)
# add text
self._adjustText()
self.widgetLayout.addWidget(self.titleLabel)
self.widgetLayout.addWidget(self.contentLabel)
self.viewLayout.addLayout(self.widgetLayout)
# adjust content margins
margins = QMargins(6, 5, 20, 5)
margins.setLeft(20 if not self.icon else 5)
self.viewLayout.setContentsMargins(margins)
self._adjustImage()
def addWidget(self, widget: QWidget, stretch=0, align=Qt.AlignLeft):
""" add widget to view """
self.widgetLayout.addSpacing(8)
self.widgetLayout.addWidget(widget, stretch, align)
def _adjustText(self):
w = min(900, QApplication.screenAt(
QCursor.pos()).geometry().width() - 200)
# adjust title
chars = max(min(w / 10, 120), 30)
self.titleLabel.setText(TextWrap.wrap(self.title, chars, False)[0])
# adjust content
chars = max(min(w / 9, 120), 30)
self.contentLabel.setText(TextWrap.wrap(self.content, chars, False)[0])
def _adjustImage(self):
if self.image.isNull():
return
w = self.viewLayout.sizeHint().width() - 2
self.image = self.originImage.scaledToWidth(w, Qt.SmoothTransformation)
margins = self.viewLayout.contentsMargins()
margins.setTop(self.image.height())
self.viewLayout.setContentsMargins(margins)
def showEvent(self, e):
super().showEvent(e)
self._adjustImage()
self.adjustSize()
def paintEvent(self, e):
super().paintEvent(e)
if self.image.isNull():
return
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing |
QPainter.SmoothPixmapTransform)
path = QPainterPath()
path.setFillRule(Qt.WindingFill)
w, h = self.image.width(), self.image.height()
rect = QRectF(1, 1, w, h)
path.addRoundedRect(rect, 8, 8)
path.addRect(QRectF(1, h - 9, w, 10))
painter.setPen(Qt.NoPen)
painter.fillPath(path.simplified(), QBrush(self.image))
class Flyout(QWidget):
""" Flyout """
def __init__(self, view: FlyoutViewBase, parent=None):
super().__init__(parent=parent)
self.view = view
self.hBoxLayout = QHBoxLayout(self)
self.opacityAni = QPropertyAnimation(self, b'windowOpacity', self)
self.slideAni = QPropertyAnimation(self, b'pos', self)
self.aniGroup = QParallelAnimationGroup(self)
self.aniGroup.addAnimation(self.opacityAni)
self.aniGroup.addAnimation(self.slideAni)
self.hBoxLayout.setContentsMargins(15, 8, 15, 20)
self.hBoxLayout.addWidget(self.view)
self.setShadowEffect()
self.setAttribute(Qt.WA_TranslucentBackground)
self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint | Qt.NoDropShadowWindowHint)
def setShadowEffect(self, blurRadius=35, offset=(0, 8)):
""" add shadow to dialog """
color = QColor(0, 0, 0, 80 if isDarkTheme() else 30)
self.shadowEffect = QGraphicsDropShadowEffect(self.view)
self.shadowEffect.setBlurRadius(blurRadius)
self.shadowEffect.setOffset(*offset)
self.shadowEffect.setColor(color)
self.view.setGraphicsEffect(None)
self.view.setGraphicsEffect(self.shadowEffect)
def exec(self, pos: QPoint, ani=True):
""" show calendar view """
rect = QApplication.screenAt(QCursor.pos()).availableGeometry()
w, h = self.sizeHint().width() + 5, self.sizeHint().height()
pos.setX(max(rect.left(), min(pos.x(), rect.right() - w)))
pos.setY(max(rect.top(), min(pos.y() - 4, rect.bottom() - h + 5)))
self.move(pos)
if not ani:
return self.show()
self.opacityAni.setStartValue(0)
self.opacityAni.setEndValue(1)
self.opacityAni.setDuration(187)
self.opacityAni.setEasingCurve(QEasingCurve.OutQuad)
self.slideAni.setStartValue(pos+QPoint(0, 8))
self.slideAni.setEndValue(pos)
self.slideAni.setDuration(187)
self.slideAni.setEasingCurve(QEasingCurve.OutQuad)
self.aniGroup.start()
self.show()
@classmethod
def make(cls, view: FlyoutViewBase, target: Union[QWidget, QPoint] = None, parent=None):
""" create and show a flyout
Parameters
----------
view: FlyoutViewBase
flyout view
target: QWidget | QPoint
the target widget or position to show flyout
parent: QWidget
parent window
"""
w = Flyout(view, parent)
if target is None:
return w
# show flyout first so that we can get the correct size
w.show()
# move flyout to the top of target
if isinstance(target, QWidget):
pos = target.mapToGlobal(QPoint())
x = pos.x() + target.width()//2 - w.sizeHint().width()//2
y = pos.y() - w.sizeHint().height() + w.layout().contentsMargins().bottom()
target = QPoint(x, y)
w.exec(target)
return w
@classmethod
def create(cls, title: str, content: str, icon: Union[FluentIconBase, QIcon, str] = None,
image: Union[str, QPixmap, QImage] = None, target: Union[QWidget, QPoint] = None, parent=None):
""" create and show a flyout using the default view
Parameters
----------
title: str
the title of teaching tip
content: str
the content of teaching tip
icon: InfoBarIcon | FluentIconBase | QIcon | str
the icon of teaching tip
image: str | QPixmap | QImage
the image of teaching tip
view: FlyoutViewBase
flyout view
target: QWidget | QPoint
the target widget or position to show flyout
parent: QWidget
parent window
"""
view = FlyoutView(title, content, icon, image)
return cls.make(view, target, parent)
\ No newline at end of file
......@@ -167,7 +167,7 @@ class TeachingTipView(QFrame):
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing)
painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
painter.setBrush(
QColor(40, 40, 40) if isDarkTheme() else QColor(249, 249, 249))
......@@ -349,7 +349,7 @@ class TeachingTipManager(QObject):
def _drawImage(self, tip: TeachingTipView, painter: QPainter):
""" draw the header image of tip """
if not tip.image:
if tip.image.isNull():
return
path = QPainterPath()
......@@ -416,7 +416,7 @@ class TopTailTeachingTipManager(TeachingTipManager):
def _drawImage(self, tip: TeachingTipView, painter: QPainter):
""" draw the header image of tip """
if not tip.image:
if tip.image.isNull():
return
path = QPainterPath()
......
......@@ -6,7 +6,7 @@ with open('README.md', encoding='utf-8') as f:
setuptools.setup(
name="PyQt-Fluent-Widgets",
version="0.9.8",
version="0.9.9",
keywords="pyqt fluent widgets",
author="zhiyiYo",
author_email="shokokawaii@outlook.com",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册