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

添加 `TabBar`

上级 2eb09a7a
# coding:utf-8
import sys
from PyQt5.QtCore import Qt, pyqtSignal, QEasingCurve, QUrl
from PyQt5.QtGui import QIcon, QDesktopServices
from PyQt5.QtWidgets import QLabel, QHBoxLayout, QVBoxLayout, QApplication, QFrame, QWidget
from qfluentwidgets import (NavigationBar, NavigationItemPosition, NavigationWidget, MessageBox,
isDarkTheme, setTheme, Theme, setThemeColor, SearchLineEdit, PopUpAniStackedWidget,
TabBar, TransparentToolButton)
from qfluentwidgets import FluentIcon as FIF
from qframelesswindow import FramelessWindow, TitleBar
class Widget(QWidget):
def __init__(self, text: str, parent=None):
super().__init__(parent=parent)
self.label = QLabel(text, self)
self.label.setAlignment(Qt.AlignCenter)
self.hBoxLayout = QHBoxLayout(self)
self.hBoxLayout.addWidget(self.label, 1, Qt.AlignCenter)
self.setObjectName(text.replace(' ', '-'))
class StackedWidget(QFrame):
""" Stacked widget """
currentChanged = pyqtSignal(int)
def __init__(self, parent=None):
super().__init__(parent=parent)
self.hBoxLayout = QHBoxLayout(self)
self.view = PopUpAniStackedWidget(self)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.addWidget(self.view)
self.view.currentChanged.connect(self.currentChanged)
def addWidget(self, widget):
""" add widget to view """
self.view.addWidget(widget)
def widget(self, index: int):
return self.view.widget(index)
def setCurrentWidget(self, widget, popOut=False):
if not popOut:
self.view.setCurrentWidget(widget, duration=300)
else:
self.view.setCurrentWidget(
widget, True, False, 200, QEasingCurve.InQuad)
def setCurrentIndex(self, index, popOut=False):
self.setCurrentWidget(self.view.widget(index), popOut)
class CustomTitleBar(TitleBar):
""" Title bar with icon and title """
def __init__(self, parent):
super().__init__(parent)
self.setFixedHeight(48)
self.hBoxLayout.removeWidget(self.minBtn)
self.hBoxLayout.removeWidget(self.maxBtn)
self.hBoxLayout.removeWidget(self.closeBtn)
# add window icon
self.iconLabel = QLabel(self)
self.iconLabel.setFixedSize(18, 18)
self.hBoxLayout.insertSpacing(0, 20)
self.hBoxLayout.insertWidget(
1, self.iconLabel, 0, Qt.AlignLeft | Qt.AlignVCenter)
self.window().windowIconChanged.connect(self.setIcon)
# add title label
self.titleLabel = QLabel(self)
self.hBoxLayout.insertWidget(
2, self.titleLabel, 0, Qt.AlignLeft | Qt.AlignVCenter)
self.hBoxLayout.insertSpacing(3, 20)
self.titleLabel.setObjectName('titleLabel')
self.window().windowTitleChanged.connect(self.setTitle)
# add tab bar
self.tabBar = TabBar(self)
self.tabBar.addTab('As long as you love me', 'resource/Heart.png')
self.tabBar.tabAddRequested.connect(self.addTab)
self.tabBar.tabCloseRequested.connect(self.tabBar.removeTab)
self.tabBar.currentChanged.connect(lambda i: print(self.tabBar.tabText(i)))
self.hBoxLayout.insertWidget(4, self.tabBar, 1)
self.hBoxLayout.setStretch(5, 0)
self.vBoxLayout = QVBoxLayout()
self.buttonLayout = QHBoxLayout()
self.buttonLayout.setSpacing(0)
self.buttonLayout.setContentsMargins(0, 0, 0, 0)
self.buttonLayout.setAlignment(Qt.AlignTop)
self.buttonLayout.addWidget(self.minBtn)
self.buttonLayout.addWidget(self.maxBtn)
self.buttonLayout.addWidget(self.closeBtn)
self.vBoxLayout.addLayout(self.buttonLayout)
self.vBoxLayout.addStretch(1)
self.hBoxLayout.addLayout(self.vBoxLayout, 0)
def setTitle(self, title):
self.titleLabel.setText(title)
self.titleLabel.adjustSize()
def setIcon(self, icon):
self.iconLabel.setPixmap(QIcon(icon).pixmap(18, 18))
def addTab(self):
self.tabBar.addTab('你干嘛~', 'resource/Chicken.png')
class Window(FramelessWindow):
def __init__(self):
super().__init__()
self.setTitleBar(CustomTitleBar(self))
# use dark theme mode
# setTheme(Theme.DARK)
# change the theme color
# setThemeColor('#0078d4')
self.hBoxLayout = QHBoxLayout(self)
self.navigationBar = NavigationBar(self)
self.stackWidget = StackedWidget(self)
# create sub interface
self.homeInterface = Widget('Home Interface', self)
self.appInterface = Widget('Application Interface', self)
self.videoInterface = Widget('Video Interface', self)
self.libraryInterface = Widget('library Interface', self)
# initialize layout
self.initLayout()
# add items to navigation interface
self.initNavigation()
self.initWindow()
def initLayout(self):
self.hBoxLayout.setSpacing(0)
self.hBoxLayout.setContentsMargins(0, 48, 0, 0)
self.hBoxLayout.addWidget(self.navigationBar)
self.hBoxLayout.addWidget(self.stackWidget)
self.hBoxLayout.setStretchFactor(self.stackWidget, 1)
def initNavigation(self):
self.addSubInterface(self.homeInterface, FIF.HOME, '主页', selectedIcon=FIF.HOME_FILL)
self.addSubInterface(self.appInterface, FIF.APPLICATION, '应用')
self.addSubInterface(self.videoInterface, FIF.VIDEO, '视频')
self.addSubInterface(self.libraryInterface, FIF.BOOK_SHELF, '库', NavigationItemPosition.BOTTOM, FIF.LIBRARY_FILL)
self.navigationBar.addItem(
routeKey='Help',
icon=FIF.HELP,
text='帮助',
onClick=self.showMessageBox,
selectable=False,
position=NavigationItemPosition.BOTTOM,
)
self.stackWidget.currentChanged.connect(self.onCurrentInterfaceChanged)
self.navigationBar.setCurrentItem(self.homeInterface.objectName())
def initWindow(self):
self.resize(900, 700)
self.setWindowIcon(QIcon(':/qfluentwidgets/images/logo.png'))
self.setWindowTitle('PyQt-Fluent-Widgets')
self.titleBar.setAttribute(Qt.WA_StyledBackground)
desktop = QApplication.desktop().availableGeometry()
w, h = desktop.width(), desktop.height()
self.move(w//2 - self.width()//2, h//2 - self.height()//2)
self.setQss()
def addSubInterface(self, interface, icon, text: str, position=NavigationItemPosition.TOP, selectedIcon=None):
""" add sub interface """
self.stackWidget.addWidget(interface)
self.navigationBar.addItem(
routeKey=interface.objectName(),
icon=icon,
text=text,
onClick=lambda: self.switchTo(interface),
selectedIcon=selectedIcon,
position=position,
)
def setQss(self):
color = 'dark' if isDarkTheme() else 'light'
with open(f'resource/{color}/demo.qss', encoding='utf-8') as f:
self.setStyleSheet(f.read())
def switchTo(self, widget):
self.stackWidget.setCurrentWidget(widget)
def onCurrentInterfaceChanged(self, index):
widget = self.stackWidget.widget(index)
self.navigationBar.setCurrentItem(widget.objectName())
def showMessageBox(self):
w = MessageBox(
'支持作者🥰',
'个人开发不易,如果这个项目帮助到了您,可以考虑请作者喝一瓶快乐水🥤。您的支持就是作者开发和维护项目的动力🚀',
self
)
w.yesButton.setText('来啦老弟')
w.cancelButton.setText('下次一定')
if w.exec():
QDesktopServices.openUrl(QUrl("https://afdian.net/a/zhiyiYo"))
if __name__ == '__main__':
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
app = QApplication(sys.argv)
w = Window()
w.show()
app.exec_()
Widget > QLabel {
font: 24px 'Segoe UI', 'Microsoft YaHei';
}
StackedWidget {
border: 1px solid rgb(29, 29, 29);
border-right: none;
border-bottom: none;
border-top-left-radius: 10px;
background-color: rgb(39, 39, 39);
}
Window {
background-color: rgb(32, 32, 32);
}
Widget > QLabel {
color: white;
}
CustomTitleBar {
background-color: transparent;
}
CustomTitleBar>QLabel#titleLabel {
background: transparent;
font: 13px 'Segoe UI';
padding: 0 10px;
color: white;
}
MinimizeButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: white;
qproperty-hoverBackgroundColor: rgba(255, 255, 255, 26);
qproperty-pressedColor: white;
qproperty-pressedBackgroundColor: rgba(255, 255, 255, 51)
}
MaximizeButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: white;
qproperty-hoverBackgroundColor: rgba(255, 255, 255, 26);
qproperty-pressedColor: white;
qproperty-pressedBackgroundColor: rgba(255, 255, 255, 51)
}
CloseButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
}
\ No newline at end of file
Widget > QLabel {
font: 24px 'Segoe UI', 'Microsoft YaHei';
}
StackedWidget {
border: 1px solid rgb(229, 229, 229);
border-right: none;
border-bottom: none;
border-top-left-radius: 10px;
background-color: rgb(249, 249, 249);
}
Window {
background-color: rgb(243, 243, 243);
}
CustomTitleBar>QLabel#titleLabel {
color: black;
background: transparent;
font: 13px 'Segoe UI';
padding: 0 10px
}
MinimizeButton {
qproperty-normalColor: black;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: black;
qproperty-hoverBackgroundColor: rgba(0, 0, 0, 26);
qproperty-pressedColor: black;
qproperty-pressedBackgroundColor: rgba(0, 0, 0, 51)
}
MaximizeButton {
qproperty-normalColor: black;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: black;
qproperty-hoverBackgroundColor: rgba(0, 0, 0, 26);
qproperty-pressedColor: black;
qproperty-pressedBackgroundColor: rgba(0, 0, 0, 51)
}
CloseButton {
qproperty-normalColor: black;
qproperty-normalBackgroundColor: transparent;
}
\ No newline at end of file
TabBar {
border: none;
background-color: transparent;
}
#view {
background-color: transparent;
}
\ No newline at end of file
TabBar {
border: none;
background-color: transparent;
}
#view {
background-color: transparent;
}
\ No newline at end of file
此差异已折叠。
...@@ -385,6 +385,7 @@ ...@@ -385,6 +385,7 @@
<file>qss/dark/fluent_window.qss</file> <file>qss/dark/fluent_window.qss</file>
<file>qss/dark/teaching_tip.qss</file> <file>qss/dark/teaching_tip.qss</file>
<file>qss/dark/info_badge.qss</file> <file>qss/dark/info_badge.qss</file>
<file>qss/dark/tab_view.qss</file>
<file>qss/light/color_dialog.qss</file> <file>qss/light/color_dialog.qss</file>
<file>qss/light/dialog.qss</file> <file>qss/light/dialog.qss</file>
...@@ -414,6 +415,7 @@ ...@@ -414,6 +415,7 @@
<file>qss/light/fluent_window.qss</file> <file>qss/light/fluent_window.qss</file>
<file>qss/light/teaching_tip.qss</file> <file>qss/light/teaching_tip.qss</file>
<file>qss/light/info_badge.qss</file> <file>qss/light/info_badge.qss</file>
<file>qss/light/tab_view.qss</file>
<file>i18n/qfluentwidgets.zh_CN.qm</file> <file>i18n/qfluentwidgets.zh_CN.qm</file>
<file>i18n/qfluentwidgets.zh_HK.qm</file> <file>i18n/qfluentwidgets.zh_HK.qm</file>
......
...@@ -93,6 +93,7 @@ class FluentStyleSheet(StyleSheetBase, Enum): ...@@ -93,6 +93,7 @@ class FluentStyleSheet(StyleSheetBase, Enum):
SLIDER = "slider" SLIDER = "slider"
INFO_BAR = "info_bar" INFO_BAR = "info_bar"
SPIN_BOX = "spin_box" SPIN_BOX = "spin_box"
TAB_VIEW = "tab_view"
TOOL_TIP = "tool_tip" TOOL_TIP = "tool_tip"
CHECK_BOX = "check_box" CHECK_BOX = "check_box"
COMBO_BOX = "combo_box" COMBO_BOX = "combo_box"
......
...@@ -33,4 +33,5 @@ from .progress_bar import IndeterminateProgressBar, ProgressBar ...@@ -33,4 +33,5 @@ from .progress_bar import IndeterminateProgressBar, ProgressBar
from .progress_ring import ProgressRing, IndeterminateProgressRing from .progress_ring import ProgressRing, IndeterminateProgressRing
from .scroll_bar import ScrollBar, SmoothScrollBar, SmoothScrollDelegate from .scroll_bar import ScrollBar, SmoothScrollBar, SmoothScrollDelegate
from .teaching_tip import TeachingTip, TeachingTipTailPosition, TeachingTipView, PopupTeachingTip from .teaching_tip import TeachingTip, TeachingTipTailPosition, TeachingTipView, PopupTeachingTip
from .flyout import FlyoutView, FlyoutViewBase, Flyout, FlyoutAnimationType, FlyoutAnimationManager from .flyout import FlyoutView, FlyoutViewBase, Flyout, FlyoutAnimationType, FlyoutAnimationManager
\ No newline at end of file from .tab_view import TabBar, TabItem
\ No newline at end of file
# coding:utf-8
from copy import deepcopy
from enum import Enum
from typing import List, Union
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QRectF, QSize
from PyQt5.QtGui import QPixmap, QPainter, QColor, QIcon, QPainterPath, QLinearGradient, QPen, QBrush
from PyQt5.QtWidgets import QWidget, QGraphicsDropShadowEffect, QHBoxLayout, QSizePolicy
from ...common.icon import FluentIcon, FluentIconBase, drawIcon
from ...common.style_sheet import isDarkTheme, FluentStyleSheet
from ...common.font import setFont
from .button import TransparentToolButton, PushButton
from .scroll_area import SingleDirectionScrollArea
class TabCloseButtonDisplayMode(Enum):
""" Tab close button display mode """
ALWAYS = 0
ON_HOVER = 1
NEVER = 2
def checkIndex(*default):
""" decorator for index checking
Parameters
----------
*default:
the default value returned when an index overflow
"""
def outer(func):
def inner(tabBar, index: int, *args, **kwargs):
if 0 <= index < len(tabBar.items):
return func(tabBar, index, *args, **kwargs)
value = deepcopy(default)
if len(value) == 0:
return None
elif len(value) == 1:
return value[0]
return value
return inner
return outer
class TabItem(PushButton):
""" Tab item """
closed = pyqtSignal()
def _postInit(self):
super()._postInit()
self.borderRadius = 6
self.isSelected = False
self.textColor = None
self.closeButtonDisplayMode = TabCloseButtonDisplayMode.ALWAYS
self.closeButton = TransparentToolButton(FluentIcon.CLOSE, self)
self.shadowEffect = QGraphicsDropShadowEffect(self)
self.__initWidget()
def __initWidget(self):
setFont(self, 12)
self.setFixedSize(240, 36)
self.closeButton.setFixedSize(32, 24)
self.closeButton.setIconSize(QSize(10, 10))
self.shadowEffect.setBlurRadius(12)
self.shadowEffect.setOffset(0, 0)
self.setGraphicsEffect(self.shadowEffect)
self.setSelected(False)
self.closeButton.clicked.connect(self.closed)
def setBorderRadius(self, radius: int):
self.borderRadius = radius
self.update()
def setSelected(self, isSelected: bool):
self.isSelected = isSelected
self.shadowEffect.setColor(QColor(0, 0, 0, 50*isSelected))
self.update()
if self.closeButtonDisplayMode == TabCloseButtonDisplayMode.ON_HOVER:
self.closeButton.setVisible(isSelected)
def setCloseButtonDisplayMode(self, mode: TabCloseButtonDisplayMode):
""" set close button display mode """
if mode == self.closeButtonDisplayMode:
return
self.closeButtonDisplayMode = mode
if mode == TabCloseButtonDisplayMode.NEVER:
self.closeButton.hide()
elif mode == TabCloseButtonDisplayMode.ALWAYS:
self.closeButton.show()
else:
self.closeButton.setVisible(self.isHover or self.isSelected)
def setTextColor(self, color: QColor):
self.textColor = color
self.update()
def resizeEvent(self, e):
self.closeButton.move(
self.width()-6-self.closeButton.width(), int(self.height()/2-self.closeButton.height()/2))
def enterEvent(self, e):
super().enterEvent(e)
if self.closeButtonDisplayMode == TabCloseButtonDisplayMode.ON_HOVER:
self.closeButton.show()
def leaveEvent(self, e):
super().leaveEvent(e)
if self.closeButtonDisplayMode == TabCloseButtonDisplayMode.ON_HOVER and not self.isSelected:
self.closeButton.hide()
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing)
if self.isSelected:
self._drawSelectedBackground(painter)
else:
self._drawNotSelectedBackground(painter)
# draw icon
if not self.isSelected:
painter.setOpacity(0.79 if isDarkTheme() else 0.61)
drawIcon(self._icon, painter, QRectF(10, 10, 16, 16))
# draw text
self._drawText(painter)
def _drawSelectedBackground(self, painter: QPainter):
w, h = self.width(), self.height()
r = self.borderRadius
d = 2 * r
isDark = isDarkTheme()
# draw top border
path = QPainterPath()
path.arcMoveTo(1, h - d - 1, d, d, 225)
path.arcTo(1, h - d - 1, d, d, 225, -45)
path.lineTo(1, r)
path.arcTo(1, 1, d, d, -180, -90)
path.lineTo(w - r, 1)
path.arcTo(w - d - 1, 1, d, d, 90, -90)
path.lineTo(w - 1, h - r)
path.arcTo(w - d - 1, h - d - 1, d, d, 0, -45)
topBorderColor = QColor(0, 0, 0, 20)
if isDark:
if self.isPressed:
topBorderColor = QColor(255, 255, 255, 18)
elif self.isHover:
topBorderColor = QColor(255, 255, 255, 13)
else:
topBorderColor = QColor(0, 0, 0, 16)
painter.strokePath(path, topBorderColor)
# draw bottom border
path = QPainterPath()
path.arcMoveTo(1, h - d - 1, d, d, 225)
path.arcTo(1, h - d - 1, d, d, 225, 45)
path.lineTo(w - r - 1, h - 1)
path.arcTo(w - d - 1, h - d - 1, d, d, 270, 45)
bottomBorderColor = topBorderColor
if not isDark:
bottomBorderColor = QColor(0, 0, 0, 63)
painter.strokePath(path, bottomBorderColor)
# draw background
painter.setPen(Qt.NoPen)
rect = self.rect().adjusted(1, 1, -1, -1)
if isDark:
color = QColor(40, 40, 40)
else:
color = QColor(246, 246, 246)
painter.setBrush(color)
painter.drawRoundedRect(rect, r, r)
def _drawNotSelectedBackground(self, painter: QPainter):
if not (self.isPressed or self.isHover):
return
isDark = isDarkTheme()
if self.isPressed:
color = QColor(255, 255, 255, 12) if isDark else QColor(0, 0, 0, 7)
else:
color = QColor(255, 255, 255, 15) if isDark else QColor(
0, 0, 0, 10)
painter.setBrush(color)
painter.setPen(Qt.NoPen)
painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), self.borderRadius, self.borderRadius)
def _drawText(self, painter: QPainter):
tw = self.fontMetrics().width(self.text())
if self.icon().isNull():
dw = 55 if self.closeButton.isVisible() else 18
rect = QRectF(18, 0, self.width() - dw, self.height())
else:
dw = 40 if self.closeButton.isVisible() else 12
rect = QRectF(35, 0, self.width() - dw, self.height())
pen = QPen()
color = Qt.white if isDarkTheme() else Qt.black
color = self.textColor or color
if tw > rect.width():
gradient = QLinearGradient(0, 0, rect.width(), 0)
gradient.setColorAt(0, color)
gradient.setColorAt(0.95, color)
gradient.setColorAt(1, Qt.transparent)
pen.setBrush(QBrush(gradient))
else:
pen.setColor(color)
painter.setPen(pen)
painter.setFont(self.font())
painter.drawText(rect, Qt.AlignVCenter | Qt.AlignLeft, self.text())
class TabBar(SingleDirectionScrollArea):
""" Tab bar """
currentChanged = pyqtSignal(int)
tabBarClicked = pyqtSignal(int)
tabCloseRequested = pyqtSignal(int)
tabAddRequested = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent=parent, orient=Qt.Horizontal)
self.items = [] # type: List[TabItem]
self._currentIndex = -1
self.closeButtonDisplayMode = TabCloseButtonDisplayMode.ALWAYS
self.view = QWidget(self)
self.hBoxLayout = QHBoxLayout(self.view)
self.itemLayout = QHBoxLayout()
self.widgetLayout = QHBoxLayout()
self.addButton = TransparentToolButton(FluentIcon.ADD, self)
self.__initWidget()
def __initWidget(self):
self.setFixedHeight(46)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.addButton.setFixedSize(32, 24)
self.addButton.setIconSize(QSize(12, 12))
self.addButton.clicked.connect(self.tabAddRequested)
self.view.setObjectName('view')
FluentStyleSheet.TAB_VIEW.apply(self)
FluentStyleSheet.TAB_VIEW.apply(self.view)
self.hBoxLayout.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
self.itemLayout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
self.widgetLayout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
self.itemLayout.setContentsMargins(5, 5, 5, 5)
self.widgetLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.setSpacing(0)
self.itemLayout.setSpacing(0)
self.hBoxLayout.addLayout(self.itemLayout)
self.hBoxLayout.addSpacing(3)
self.widgetLayout.addWidget(self.addButton, 0, Qt.AlignLeft)
self.hBoxLayout.addLayout(self.widgetLayout)
self.hBoxLayout.addStretch(1)
def setAddButtonVisible(self, isVisible: bool):
self.addButton.setVisible(isVisible)
def addTab(self, text: str, icon: Union[QIcon, str, FluentIconBase] = None):
""" add tab
Parameters
----------
text: str
the text of tab item
text: str
the icon of tab item
"""
self.insertTab(-1, text, icon)
def insertTab(self, index: int, text: str, icon: Union[QIcon, str, FluentIconBase] = None):
""" insert tab
Parameters
----------
index: int
the insert position of tab item
text: str
the text of tab item
text: str
the icon of tab item
"""
if index == -1:
index = len(self.items)
# adjust current index
if index <= self.currentIndex() and self.currentIndex() >= 0:
self._currentIndex += 1
item = TabItem(text, self.view, icon)
item.setCloseButtonDisplayMode(self.closeButtonDisplayMode)
item.clicked.connect(self._onItemClicked)
item.closed.connect(lambda: self.tabCloseRequested.emit(
self.items.index(item)))
self.itemLayout.insertWidget(index, item, 1)
self.items.insert(index, item)
if len(self.items) == 1:
self.setCurrentIndex(0)
def removeTab(self, index: int):
if not 0 <= index < len(self.items):
return
# adjust current index
if index < self.currentIndex():
self._currentIndex -= 1
elif index == self.currentIndex():
if self.currentIndex() > 0:
self.setCurrentIndex(self.currentIndex() - 1)
elif len(self.items) == 0:
self._currentIndex = -1
else:
self.setCurrentIndex(1)
self._currentIndex = 0
item = self.items.pop(index)
self.hBoxLayout.removeWidget(item)
item.deleteLater()
def setCurrentIndex(self, index: int):
""" set current index """
if index == self._currentIndex:
return
if self.currentIndex() >= 0:
self.items[self.currentIndex()].setSelected(False)
self._currentIndex = index
self.items[index].setSelected(True)
def currentIndex(self):
return self._currentIndex
def _onItemClicked(self):
for item in self.items:
item.setSelected(item is self.sender())
index = self.items.index(self.sender())
self.tabBarClicked.emit(index)
if index != self.currentIndex():
self.setCurrentIndex(index)
self.currentChanged.emit(index)
def setCloseButtonDisplayMode(self, mode: TabCloseButtonDisplayMode):
""" set close button display mode """
if mode == self.closeButtonDisplayMode:
return
self.closeButtonDisplayMode = mode
for item in self.items:
item.setCloseButtonDisplayMode(mode)
@checkIndex()
def tabItem(self, index: int):
return self.items[index]
@checkIndex('')
def tabText(self, index: int):
return self.tabItem(index).text()
@checkIndex()
def tabIcon(self, index: int):
return self.tabItem(index).icon()
@checkIndex('')
def tabToolTip(self, index: int):
return self.tabItem(index).toolTip()
def setTabsClosable(self, isClosable: bool):
if isClosable:
self.setCloseButtonDisplayMode(TabCloseButtonDisplayMode.ALWAYS)
else:
self.setCloseButtonDisplayMode(TabCloseButtonDisplayMode.NEVER)
def tabsClosable(self):
return self.closeButtonDisplayMode != TabCloseButtonDisplayMode.NEVER
@checkIndex()
def setTabIcon(self, index: int, icon: Union[QIcon, FluentIconBase, str]):
""" set tab icon """
self.tabItem(index).setIcon(icon)
@checkIndex()
def setTabText(self, index: int, text: str):
""" set tab text """
self.tabItem(index).setText(text)
@checkIndex()
def setTabVisible(self, index: int, isVisible: bool):
self.tabItem(index).setVisible(isVisible)
if isVisible and self.currentIndex() < 0:
self.setCurrentIndex(0)
elif not isVisible:
if self.currentIndex() > 0:
self.setCurrentIndex(self.currentIndex() - 1)
elif len(self.items) == 1:
self._currentIndex = -1
else:
self.setCurrentIndex(1)
self._currentIndex = 0
def paintEvent(self, e):
painter = QPainter(self.viewport())
painter.setRenderHints(QPainter.Antialiasing)
# draw separators
if isDarkTheme():
color = QColor(255, 255, 255, 21)
else:
color = QColor(0, 0, 0, 15)
painter.setPen(color)
for i, item in enumerate(self.items):
canDraw = not (item.isHover or item.isSelected)
if i < len(self.items) - 1:
nextItem = self.items[i + 1]
if nextItem.isHover or nextItem.isSelected:
canDraw = False
if canDraw:
x = item.geometry().right()
y = self.height() / 2 - 8
painter.drawLine(x, y, x, y + 16)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册