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

添加 SplitButton,修复菜单图标显示不全的问题,#151

上级 a795b571
......@@ -3,8 +3,9 @@ import sys
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QAction
from qfluentwidgets import (DropDownPushButton, DropDownToolButton, PushButton, PrimaryPushButton,
HyperlinkButton, setTheme, Theme, ToolButton, ToggleButton, RoundMenu)
from qfluentwidgets import (Action, DropDownPushButton, DropDownToolButton, PushButton, PrimaryPushButton,
HyperlinkButton, setTheme, Theme, ToolButton, ToggleButton, RoundMenu,
SplitPushButton, SplitToolButton)
from qfluentwidgets import FluentIcon as FIF
......@@ -14,20 +15,25 @@ class Demo(QWidget):
super().__init__()
# setTheme(Theme.DARK)
# tool button
self.toolButton = ToolButton(FIF.SETTING, self)
# change the size of tool button
# self.toolButton.resize(50, 50)
# self.toolButton.setIconSize(QSize(30, 30))
# push button
self.pushButton1 = PushButton('Standard push button')
self.pushButton2 = PushButton('Standard push button with icon', self, FIF.FOLDER)
# primary color button
self.primaryButton1 = PrimaryPushButton('Accent style button', self)
self.primaryButton2 = PrimaryPushButton('Accent style button with icon', self, FIF.UPDATE)
# toggle button
self.toggleButton = ToggleButton('Toggle Button', self, FIF.SEND)
# drop down button
self.dropDownPushButton = DropDownPushButton('Email', self, FIF.MAIL)
self.dropDownToolButton = DropDownToolButton(FIF.MAIL, self)
self.menu = RoundMenu(parent=self)
......@@ -36,6 +42,17 @@ class Demo(QWidget):
self.dropDownPushButton.setMenu(self.menu)
self.dropDownToolButton.setMenu(self.menu)
# split button
self.splitPushButton = SplitPushButton('Split push button', self, FIF.GITHUB)
self.splitToolButton = SplitToolButton(FIF.GITHUB, self)
self.splitMenu = RoundMenu(parent=self)
self.splitMenu.addAction(Action(FIF.BASKETBALL, 'Basketball'))
self.splitMenu.addAction(Action(FIF.ALBUM, 'Sing'))
self.splitMenu.addAction(Action(FIF.MUSIC, 'Music'))
self.splitPushButton.setFlyout(self.splitMenu)
self.splitToolButton.setFlyout(self.splitMenu)
# hyperlink button
self.hyperlinkButton = HyperlinkButton(
url='https://github.com/zhiyiYo/PyQt-Fluent-Widgets',
text='Hyper link button',
......@@ -51,6 +68,8 @@ class Demo(QWidget):
self.vBoxLayout.addWidget(self.toggleButton, 0, Qt.AlignCenter)
self.vBoxLayout.addWidget(self.dropDownPushButton, 0, Qt.AlignCenter)
self.vBoxLayout.addWidget(self.dropDownToolButton, 0, Qt.AlignCenter)
self.vBoxLayout.addWidget(self.splitPushButton, 0, Qt.AlignCenter)
self.vBoxLayout.addWidget(self.splitToolButton, 0, Qt.AlignCenter)
self.vBoxLayout.addWidget(self.hyperlinkButton, 0, Qt.AlignCenter)
self.vBoxLayout.setSizeConstraint(QVBoxLayout.SetMinAndMaxSize)
......
......@@ -4,7 +4,7 @@ from enum import Enum
from PyQt5.QtCore import QLocale
from qfluentwidgets import (qconfig, QConfig, ConfigItem, OptionsConfigItem, BoolValidator,
OptionsValidator, RangeConfigItem, RangeValidator,
FolderListValidator, EnumSerializer, FolderValidator, ConfigSerializer)
FolderListValidator, EnumSerializer, FolderValidator, ConfigSerializer, __version__)
class Language(Enum):
......@@ -50,7 +50,7 @@ class Config(QConfig):
YEAR = 2023
AUTHOR = "zhiyiYo"
VERSION = "v0.7.0"
VERSION = __version__
HELP_URL = "https://pyqt-fluent-widgets.readthedocs.io/zh_CN/latest"
REPO_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets"
EXAMPLE_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/master/examples"
......
......@@ -49,17 +49,17 @@
<translation>水平滑动条</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="153"/>
<location filename="../../view/basic_input_interface.py" line="184"/>
<source>A simple switch button</source>
<translation>开关按钮</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="170"/>
<location filename="../../view/basic_input_interface.py" line="201"/>
<source>Off</source>
<translation></translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<location filename="../../view/basic_input_interface.py" line="199"/>
<source>On</source>
<translation></translation>
</message>
......@@ -89,12 +89,12 @@
<translation>GItHub 主页</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="122"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Star Platinum</source>
<translation>白金之星</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="123"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Crazy Diamond</source>
<translation>疯狂钻石</translation>
</message>
......@@ -104,17 +104,17 @@
<translation>软又湿</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="83"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Gold Experience</source>
<translation>黄金体验</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="83"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Sticky Fingers</source>
<translation>钢链手指</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="89"/>
<location filename="../../view/basic_input_interface.py" line="151"/>
<source>Choose your stand</source>
<translation>选择你的替身</translation>
</message>
......@@ -149,15 +149,45 @@
<translation>带下拉菜单的工具按钮</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="160"/>
<location filename="../../view/basic_input_interface.py" line="191"/>
<source>A simple ToggleButton with text content</source>
<translation>带文本的状态开关按钮</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="160"/>
<location filename="../../view/basic_input_interface.py" line="191"/>
<source>Start practicing</source>
<translation>开始练习</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="160"/>
<source>A split push button with drop down menu</source>
<translation>带下拉菜单的拆分按钮</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Sing</source>
<translation></translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Jump</source>
<translation></translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Rap</source>
<translation>Rap</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Music</source>
<translation>Music</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="175"/>
<source>A split tool button with drop down menu</source>
<translation>带下拉菜单的工具按钮</translation>
</message>
</context>
<context>
<name>DateTimeInterface</name>
......
......@@ -49,17 +49,17 @@
<translation>水平滑動條</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="153"/>
<location filename="../../view/basic_input_interface.py" line="184"/>
<source>A simple switch button</source>
<translation>開關按鈕</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="170"/>
<location filename="../../view/basic_input_interface.py" line="201"/>
<source>Off</source>
<translation></translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<location filename="../../view/basic_input_interface.py" line="199"/>
<source>On</source>
<translation></translation>
</message>
......@@ -89,12 +89,12 @@
<translation>GItHub 主頁</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="122"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Star Platinum</source>
<translation>白金之星</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="123"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Crazy Diamond</source>
<translation>瘋狂鑽石</translation>
</message>
......@@ -104,17 +104,17 @@
<translation>軟又溼</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="83"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Gold Experience</source>
<translation>黃金體驗</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="83"/>
<location filename="../../view/basic_input_interface.py" line="153"/>
<source>Sticky Fingers</source>
<translation>鋼鏈手指</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="89"/>
<location filename="../../view/basic_input_interface.py" line="151"/>
<source>Choose your stand</source>
<translation>選擇你的替身</translation>
</message>
......@@ -149,15 +149,45 @@
<translation>帶下拉菜單的工具按鈕</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="160"/>
<location filename="../../view/basic_input_interface.py" line="191"/>
<source>A simple ToggleButton with text content</source>
<translation>帶文本的狀態開關按鈕</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="160"/>
<location filename="../../view/basic_input_interface.py" line="191"/>
<source>Start practicing</source>
<translation>開始練習</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="160"/>
<source>A split push button with drop down menu</source>
<translation>帶下拉菜單的拆分按鈕</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Sing</source>
<translation></translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Jump</source>
<translation></translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Rap</source>
<translation>Rap</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="168"/>
<source>Music</source>
<translation>Music</translation>
</message>
<message>
<location filename="../../view/basic_input_interface.py" line="175"/>
<source>A split tool button with drop down menu</source>
<translation>帶下拉菜單的工具按鈕</translation>
</message>
</context>
<context>
<name>DateTimeInterface</name>
......
......@@ -3,7 +3,7 @@ from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import QAction, QWidget, QVBoxLayout, QButtonGroup
from qfluentwidgets import (Action, DropDownPushButton, DropDownToolButton, PushButton, ToolButton, PrimaryPushButton,
HyperlinkButton, ComboBox, RadioButton, CheckBox, Slider, SwitchButton, EditableComboBox,
ToggleButton, RoundMenu, FluentIcon)
ToggleButton, RoundMenu, FluentIcon, SplitPushButton, SplitToolButton)
from .gallery_interface import GalleryInterface
from ..common.translator import Translator
......@@ -147,6 +147,37 @@ class BasicInputInterface(GalleryInterface):
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/slider/demo.py'
)
# split button
button = SplitPushButton(self.tr('Choose your stand'), self, FluentIcon.BASKETBALL)
menu = RoundMenu(parent=self)
menu.addActions([
Action(self.tr('Star Platinum'), triggered=lambda c, b=button: b.setText(self.tr('Star Platinum'))),
Action(self.tr('Crazy Diamond'), triggered=lambda c, b=button: b.setText(self.tr('Crazy Diamond'))),
Action(self.tr("Gold Experience"), triggered=lambda c, b=button: b.setText(self.tr("Gold Experience"))),
Action(self.tr('Sticky Fingers'), triggered=lambda c, b=button: b.setText(self.tr('Sticky Fingers'))),
])
button.setFlyout(menu)
self.addExampleCard(
self.tr('A split push button with drop down menu'),
button,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/button/demo.py'
)
button = SplitToolButton(":/gallery/images/kunkun.png", self)
menu = RoundMenu(parent=self)
menu.addActions([
Action(self.tr('Sing')),
Action(self.tr('Jump')),
Action(self.tr("Rap")),
Action(self.tr('Music')),
])
button.setFlyout(menu)
self.addExampleCard(
self.tr('A split tool button with drop down menu'),
button,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/button/demo.py'
)
# switch button
self.switchButton = SwitchButton(self.tr('Off'))
self.switchButton.checkedChanged.connect(self.onSwitchCheckedChanged)
......
......@@ -163,13 +163,21 @@ class HomeInterface(ScrollArea):
routeKey="basicInputInterface",
index=11
)
basicInputView.addSampleCard(
icon=":/gallery/images/controls/SplitButton.png",
title="SplitButton",
content=self.tr(
"A two-part button that displays a flyout when its secondary part is clicked."),
routeKey="basicInputInterface",
index=12
)
basicInputView.addSampleCard(
icon=":/gallery/images/controls/ToggleSwitch.png",
title="SwitchButton",
content=self.tr(
"A switch that can be toggled between 2 states."),
routeKey="basicInputInterface",
index=12
index=14
)
basicInputView.addSampleCard(
icon=":/gallery/images/controls/ToggleButton.png",
......@@ -177,7 +185,7 @@ class HomeInterface(ScrollArea):
content=self.tr(
"A button that can be switched between two states like a CheckBox."),
routeKey="basicInputInterface",
index=13
index=15
)
self.vBoxLayout.addWidget(basicInputView)
......
......@@ -136,7 +136,7 @@ class SettingInterface(ScrollArea):
FIF.INFO,
self.tr('About'),
'© ' + self.tr('Copyright') + f" {YEAR}, {AUTHOR}. " +
self.tr('Version') + f" {VERSION[1:]}",
self.tr('Version') + " " + VERSION,
self.aboutGroup
)
......
......@@ -18,7 +18,7 @@ class Demo(QWidget):
self.setStyleSheet('Demo{background: white} QLabel{font-size: 20px}')
setTheme(Theme.DARK)
# setTheme(Theme.DARK)
def contextMenuEvent(self, e):
menu = RoundMenu(parent=self)
......
......@@ -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.8.2"
__version__ = "0.8.3"
from .components import *
from .common import *
......
......@@ -50,6 +50,25 @@ PushButton:disabled, ToolButton:disabled, ToggleButton:disabled {
border-top: 1px solid rgba(255, 255, 255, 0.053);
}
#splitPushButton,
#splitToolButton {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right-color: rgba(255, 255, 255, 0.08);
}
SplitDropButton {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
#splitPushButton:pressed,
#splitToolButton:pressed,
SplitDropButton:pressed {
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
PrimaryPushButton, ToggleButton:checked {
color: black;
......
......@@ -50,6 +50,21 @@ PushButton:disabled, ToolButton:disabled, ToggleButton:disabled {
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
#splitPushButton, #splitToolButton {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
SplitDropButton {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
#splitPushButton:pressed, #splitToolButton:pressed, SplitDropButton:pressed {
border-bottom: 1px solid rgba(0, 0, 0, 0.183);
}
PrimaryPushButton,
ToggleButton:checked {
......
此差异已折叠。
# coding: utf-8
from PyQt5.QtCore import QEasingCurve, QEvent, QObject, QPropertyAnimation, pyqtProperty, pyqtSignal
from PyQt5.QtGui import QMouseEvent, QEnterEvent
from PyQt5.QtWidgets import QWidget
class AnimationBase(QObject):
""" Animation base class """
def __init__(self, parent: QWidget):
super().__init__(parent=parent)
parent.installEventFilter(self)
def _onHover(self, e: QEnterEvent):
pass
def _onLeave(self, e: QEvent):
pass
def _onPress(self, e: QMouseEvent):
pass
def _onRelease(self, e: QMouseEvent):
pass
def eventFilter(self, obj, e: QEvent):
if obj is self.parent():
if e.type() == QEvent.MouseButtonPress:
self._onPress(e)
elif e.type() == QEvent.MouseButtonRelease:
self._onRelease(e)
elif e.type() == QEvent.Enter:
self._onHover(e)
elif e.type() == QEvent.Leave:
self._onLeave(e)
return super().eventFilter(obj, e)
class TranslateYAnimation(AnimationBase):
valueChanged = pyqtSignal(float)
def __init__(self, parent: QWidget, offset=2):
super().__init__(parent)
self._y = 0
self.maxOffset = offset
self.ani = QPropertyAnimation(self, b'y', self)
@pyqtProperty(float)
def y(self):
return self._y
@y.setter
def y(self, y):
self._y = y
self.parent().update()
self.valueChanged.emit(y)
def _onPress(self, e):
""" arrow down """
self.ani.setEndValue(self.maxOffset)
self.ani.setEasingCurve(QEasingCurve.OutQuad)
self.ani.setDuration(150)
self.ani.start()
def _onRelease(self, e):
""" arrow up """
self.ani.setEndValue(0)
self.ani.setDuration(500)
self.ani.setEasingCurve(QEasingCurve.OutElastic)
self.ani.start()
......@@ -28,10 +28,14 @@ class MenuIconEngine(QIconEngine):
elif mode == QIcon.Selected:
painter.setOpacity(0.7)
# change icon color according to the theme
icon = self.icon
if isinstance(self.icon, Icon):
icon = self.icon.fluentIcon.icon()
# prevent the left side of the icon from being cropped
rect.adjust(-1, 0, 0, 0)
icon.paint(painter, rect, Qt.AlignHCenter, QIcon.Normal, state)
painter.restore()
......
from .button import (DropDownPushButton, DropDownToolButton, PrimaryPushButton, PushButton, RadioButton,
HyperlinkButton, ToolButton, TransparentToolButton, ToggleButton)
HyperlinkButton, ToolButton, TransparentToolButton, ToggleButton, SplitWidgetBase,
SplitPushButton, SplitToolButton)
from .check_box import CheckBox
from .combo_box import ComboBox, EditableComboBox
from .line_edit import LineEdit, TextEdit, PlainTextEdit, LineEditButton, SearchLineEdit
......
# coding:utf-8
from typing import Union
from PyQt5.QtCore import QEvent, QUrl, Qt, QRectF, QSize, QPoint
from PyQt5.QtCore import pyqtSignal, QUrl, Qt, QRectF, QSize, QPoint
from PyQt5.QtGui import QDesktopServices, QIcon, QPainter
from PyQt5.QtWidgets import QMenu, QPushButton, QRadioButton, QToolButton, QApplication, QWidget
from PyQt5.QtWidgets import QHBoxLayout, QPushButton, QRadioButton, QToolButton, QApplication, QWidget, QSizePolicy
from ...common.animation import TranslateYAnimation
from ...common.icon import FluentIconBase, drawIcon, isDarkTheme, Theme
from ...common.icon import FluentIcon as FIF
from ...common.style_sheet import FluentStyleSheet
......@@ -23,6 +24,7 @@ class PushButton(QPushButton):
self.isHover = False
self.setIconSize(QSize(16, 16))
self.setIcon(None)
self._postInit()
@__init__.register
def _(self, text: str, parent: QWidget = None, icon: Union[QIcon, str, FluentIconBase] = None):
......@@ -30,6 +32,9 @@ class PushButton(QPushButton):
self.setText(text)
self.setIcon(icon)
def _postInit(self):
pass
def setIcon(self, icon: Union[QIcon, str, FluentIconBase]):
self.setProperty('hasIcon', icon is not None)
self.setStyle(QApplication.style())
......@@ -70,7 +75,8 @@ class PushButton(QPushButton):
return
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
painter.setRenderHints(QPainter.Antialiasing |
QPainter.SmoothPixmapTransform)
if not self.isEnabled():
painter.setOpacity(0.3628)
......@@ -81,7 +87,8 @@ class PushButton(QPushButton):
y = (self.height() - h) / 2
mw = self.minimumSizeHint().width()
if mw > 0:
self._drawIcon(self._icon, painter, QRectF(12+(self.width()-mw)//2, y, w, h))
self._drawIcon(self._icon, painter, QRectF(
12+(self.width()-mw)//2, y, w, h))
else:
self._drawIcon(self._icon, painter, QRectF(12, y, w, h))
......@@ -103,17 +110,9 @@ class PrimaryPushButton(PushButton):
class ToggleButton(PushButton):
@singledispatchmethod
def __init__(self, parent: QWidget = None):
super().__init__(parent)
def _postInit(self):
self.setCheckable(True)
super().setChecked(False)
@__init__.register
def _(self, text: str, parent: QWidget = None, icon: Union[QIcon, str, FluentIconBase] = None):
self.__init__(parent=parent)
self.setText(text)
self.setIcon(icon)
self.setChecked(False)
def _drawIcon(self, icon, painter, rect):
if not self.isChecked():
......@@ -166,7 +165,9 @@ class ToolButton(QToolButton):
FluentStyleSheet.BUTTON.apply(self)
self.isPressed = False
self.isHover = False
self.setIconSize(QSize(16, 16))
self.setIcon(QIcon())
self._postInit()
@__init__.register
def _(self, icon: FluentIconBase, parent: QWidget = None):
......@@ -183,6 +184,9 @@ class ToolButton(QToolButton):
self.__init__(parent)
self.setIcon(icon)
def _postInit(self):
pass
def setIcon(self, icon: Union[QIcon, str, FluentIconBase]):
self._icon = icon
self.update()
......@@ -211,7 +215,7 @@ class ToolButton(QToolButton):
self.isHover = False
self.update()
def _drawIcon(self, icon, painter, rect):
def _drawIcon(self, icon, painter: QPainter, rect: QRectF):
""" draw icon """
drawIcon(icon, painter, rect)
......@@ -243,7 +247,9 @@ class DropDownButtonBase:
""" Drop down button base class """
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._menu = None
self.arrowAni = TranslateYAnimation(self)
def setMenu(self, menu: RoundMenu):
self._menu = menu
......@@ -257,6 +263,10 @@ class DropDownButtonBase:
menu = self.menu()
if menu.view.width() < self.width():
menu.view.setMinimumWidth(self.width())
menu.adjustSize()
# show menu
x = -menu.width()//2 + menu.layout().contentsMargins().left() + self.width()//2
y = self.height()
......@@ -274,48 +284,181 @@ class DropDownButtonBase:
elif self.isPressed:
painter.setOpacity(0.7)
rect = QRectF(self.width()-22, self.height()/2-5, 10, 10)
rect = QRectF(self.width()-22, self.height()/2-5+self.arrowAni.y, 10, 10)
if isDarkTheme():
FIF.ARROW_DOWN.render(painter, rect)
else:
FIF.ARROW_DOWN.render(painter, rect, fill="#646464")
class DropDownPushButton(PushButton, DropDownButtonBase):
class DropDownPushButton(DropDownButtonBase, PushButton):
""" Drop down push button """
def setMenu(self, menu: RoundMenu):
DropDownButtonBase.setMenu(self, menu)
def mouseReleaseEvent(self, e):
super().mouseReleaseEvent(e)
PushButton.mouseReleaseEvent(self, e)
self._showMenu()
def menu(self):
return DropDownButtonBase.menu(self)
def paintEvent(self, e):
PushButton.paintEvent(self, e)
DropDownButtonBase.paintEvent(self, e)
class DropDownToolButton(ToolButton, DropDownButtonBase):
class DropDownToolButton(DropDownButtonBase, ToolButton):
""" Drop down tool button """
def setMenu(self, menu: RoundMenu):
DropDownButtonBase.setMenu(self, menu)
def mouseReleaseEvent(self, e):
super().mouseReleaseEvent(e)
ToolButton.mouseReleaseEvent(self, e)
self._showMenu()
def menu(self):
return DropDownButtonBase.menu(self)
def _drawIcon(self, icon, painter, rect: QRectF):
rect.moveLeft(12)
return super()._drawIcon(icon, painter, rect)
def paintEvent(self, e):
ToolButton.paintEvent(self, e)
DropDownButtonBase.paintEvent(self, e)
\ No newline at end of file
DropDownButtonBase.paintEvent(self, e)
class SplitDropButton(ToolButton):
def _postInit(self):
self.arrowAni = TranslateYAnimation(self)
def _drawIcon(self, icon, painter, rect):
rect.translate(0, self.arrowAni.y)
if self.isPressed:
painter.setOpacity(0.5)
elif self.isHover:
painter.setOpacity(1)
else:
painter.setOpacity(0.63)
super()._drawIcon(FIF.ARROW_DOWN, painter, rect)
class SplitWidgetBase(QWidget):
""" Split widget base class """
dropDownClicked = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent=parent)
self.flyout = None # type: QWidget
self.dropButton = SplitDropButton(self)
self.hBoxLayout = QHBoxLayout(self)
self.hBoxLayout.setSpacing(0)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.addWidget(self.dropButton)
self.dropButton.setIconSize(QSize(10, 10))
self.dropButton.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
self.dropButton.clicked.connect(self.dropDownClicked)
self.dropButton.clicked.connect(self.showFlyout)
self.setAttribute(Qt.WA_TranslucentBackground)
def setWidget(self, widget: QWidget):
""" set the widget on left side """
self.hBoxLayout.insertWidget(0, widget, 1, Qt.AlignLeft)
def setFlyout(self, flyout):
""" set the widget pops up when drop down button is clicked
Parameters
----------
flyout: QWidget
the widget pops up when drop down button is clicked.
It should contain the `exec` method, whose first parameter type is `QPoint`
"""
self.flyout = flyout
def showFlyout(self):
""" show flyout """
if not self.flyout:
return
w = self.flyout
if isinstance(w, RoundMenu) and w.view.width() < self.width():
w.view.setMinimumWidth(self.width())
w.adjustSize()
dx = w.layout().contentsMargins().left() if isinstance(w, RoundMenu) else 0
x = -w.width()//2 + dx + self.width()//2
y = self.height()
w.exec(self.mapToGlobal(QPoint(x, y)))
class SplitPushButton(SplitWidgetBase):
""" Split push button """
clicked = pyqtSignal()
@singledispatchmethod
def __init__(self, parent: QWidget = None):
super().__init__(parent=parent)
self.button = PushButton(self)
self.button.setObjectName('splitPushButton')
self.button.clicked.connect(self.clicked)
self.setWidget(self.button)
@__init__.register
def _(self, text: str, parent: QWidget = None, icon: Union[QIcon, str, FluentIconBase] = None):
self.__init__(parent)
self.setText(text)
self.setIcon(icon)
def text(self):
return self.button.text()
def setText(self, text: str):
self.button.setText(text)
def icon(self):
return self.button.icon()
def setIcon(self, icon: Union[QIcon, FluentIconBase, str]):
self.button.setIcon(icon)
class SplitToolButton(SplitWidgetBase):
""" Split tool button """
clicked = pyqtSignal()
@singledispatchmethod
def __init__(self, parent: QWidget = None):
super().__init__(parent=parent)
self.button = ToolButton(self)
self.button.setObjectName('splitToolButton')
self.button.clicked.connect(self.clicked)
self.setWidget(self.button)
@__init__.register
def _(self, icon: FluentIconBase, parent: QWidget = None):
self.__init__(parent)
self.setIcon(icon)
@__init__.register
def _(self, icon: QIcon, parent: QWidget = None):
self.__init__(parent)
self.setIcon(icon)
@__init__.register
def _(self, icon: str, parent: QWidget = None):
self.__init__(parent)
self.setIcon(icon)
def text(self):
return self.button.text()
def setText(self, text: str):
self.button.setText(text)
def icon(self):
return self.button.icon()
def setIcon(self, icon: Union[QIcon, FluentIconBase, str]):
self.button.setIcon(icon)
\ No newline at end of file
......@@ -7,6 +7,7 @@ from PyQt5.QtWidgets import QAction, QPushButton, QStyledItemDelegate, QStyle
from .menu import RoundMenu, MenuItemDelegate
from .line_edit import LineEdit, LineEditButton
from ...common.animation import TranslateYAnimation
from ...common.icon import FluentIconBase, isDarkTheme
from ...common.icon import FluentIcon as FIF
from ...common.style_sheet import FluentStyleSheet, themeColor
......@@ -326,6 +327,7 @@ class ComboBox(QPushButton, ComboBoxBase):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.arrowAni = TranslateYAnimation(self)
def setPlaceholderText(self, text: str):
self.setText(text)
......@@ -343,7 +345,7 @@ class ComboBox(QPushButton, ComboBoxBase):
elif self.isPressed:
painter.setOpacity(0.7)
rect = QRectF(self.width()-22, self.height()/2-5, 10, 10)
rect = QRectF(self.width()-22, self.height()/2-5+self.arrowAni.y, 10, 10)
if isDarkTheme():
FIF.ARROW_DOWN.render(painter, rect)
else:
......
......@@ -293,7 +293,7 @@ class RoundMenu(QWidget):
item = QListWidgetItem(self._createItemIcon(action), action.text())
if not self._hasItemIcon():
w = 28 + self.view.fontMetrics().width(action.text())
w = 40 + self.view.fontMetrics().width(action.text())
else:
# add a blank character to increase space between icon and text
item.setText(" " + item.text())
......
......@@ -6,7 +6,7 @@ with open('README.md', encoding='utf-8') as f:
setuptools.setup(
name="PyQt-Fluent-Widgets",
version="0.8.2",
version="0.8.3",
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.
先完成此消息的编辑!
想要评论请 注册