需上篇,用标签改了下拉菜单后,应需求,不能将标签栏的标签拉到菜单按钮后,且菜单按钮不能被移动,新增页面后跳转至该新页面,以及点击下拉菜单被隐藏标签会跳转至该标签的页面,做了以下修改及主要代码有下。
1、修改之前的标签改为按钮,按钮的位置实时变化
#创建标签菜单按钮
self.btn_menu = QPushButton(self)
self.btn_menu.hide()
self.btn_menu_state = 0
def tabMenuState(self):
self.btn_menu.setText('<<'+str(self.l+self.r))
self.btn_menu.move(self.barWidth-self.tabbar.tabSizeHint(0).height()*2-2, 0)
self.btn_menu.resize(self.tabbar.tabSizeHint(0).height()*2, self.tabbar.tabSizeHint(0).height())
if self.btn_menu_state == 0 and self.l+self.r > 0:
self.btn_menu_state = 1
self.btn_menu.show()
self.barWidth += self.tabbar.tabSizeHint(0).height()*2
print('添加菜单')
elif self.btn_menu_state == 1 and self.l+self.r == 0:
self.btn_menu_state = 0
self.btn_menu.hide()
self.barWidth -= self.tabbar.tabSizeHint(0).height()*2
print('移除菜单')
2、新增添加页面的按钮,可输入页面名称
def addTabs(self):
hide_tab = mw.tabs.tabs_text.index(mw.tabs.tabText(mw.tabs.page))
print(mw.tabs.tabs_text.index(mw.tabs.tabText(mw.tabs.page)))
print(len(mw.tabs.tabs_show_status))
if mw.tabs.barWidth + 130 > mw.w :
mw.tabs.tabs_show_status[hide_tab] = 0
mw.tabs.r += 1
#显示或隐藏tab菜单
mw.tabs.tabMenuState()
#根据calcutab()展示tab
mw.tabs.updatetab()
#根据calcutab()隐藏tab至tabMenu
mw.tabs.updatetabMenu()
print('有隐藏添加')
if len(self.cb.displayText()) == 0 :
mw.tabs.addTabs(len(mw.tabs.tabs_show_status), '空白页面'+str(len(mw.tabs.tabs_show_status)))
print('无名添加')
print(mw.tabs.tabs_text)
else:
if len(self.cb.displayText()) > 13 :
tabtext = self.cb.displayText()
mw.tabs.addTabs(len(mw.tabs.tabs_show_status), tabtext[0:13])
else :
mw.tabs.addTabs(len(mw.tabs.tabs_show_status), self.cb.displayText())
print('有名添加')
print(mw.tabs.tabs_show_status)
""" print(mw.tabs.tabs_show_status)
print(self.cb.displayText()) """
#显示或隐藏tab菜单
mw.tabs.tabMenuState()
#根据calcutab()展示tab
mw.tabs.updatetab()
#根据calcutab()隐藏tab至tabMenu
mw.tabs.updatetabMenu()
#跳转至新页面
jump = mw.tabs.indexOf(mw.tabs.tabs_page[len(mw.tabs.tabs_page)-1])
mw.tabs.setCurrentIndex(jump)
mw.tabs.update()
self.reject()
3、页面可删除
def delTabs(self,index):
""" self.tabs_show_status = {}
self.tabs_text = []
self.tabs_page = {}
self.tabs_width = {}
self.tabs_menu_item = {} """
print('----------------------------------------')
print(self.tabs_show_status)
print(self.tabs_text)
print(self.tabs_page)
print(self.tabs_width)
print(self.tabs_menu_item)
print('----------------------------------------------')
del_tab = mw.tabs.tabs_text.index(mw.tabs.tabText(index))
self.barWidth -= self.tabs_width[del_tab]
self.menu.removeAction(self.tabs_menu_item[del_tab])
self.tabs_text.pop(del_tab)
for i in range(0,len(self.tabs_show_status)-del_tab-1):
#将被删除标签后的标签数据前移
self.tabs_show_status[del_tab+i] = self.tabs_show_status[del_tab+i+1]
self.tabs_page[del_tab+i] = self.tabs_page[del_tab+i+1]
self.tabs_width[del_tab+i] = self.tabs_width[del_tab+i+1]
self.tabs_menu_item[del_tab+i] = self.tabs_menu_item[del_tab+i+1]
#移除最后一个数据
self.tabs_show_status.pop(len(self.tabs_show_status)-1)
self.tabs_page.pop(len(self.tabs_page)-1)
self.tabs_width.pop(len(self.tabs_width)-1)
self.tabs_menu_item.pop(len(self.tabs_menu_item)-1)
#更新数据
self.page -= 1
#移除页面
self.removeTab(index)
self.update()
print(self.tabs_show_status)
print(self.tabs_text)
print(self.tabs_page)
print(self.tabs_width)
print(self.tabs_menu_item)
print('-----------------------------------------------')
以上为主要修改部分,该代码仅供参考,为本人学习,练习所作,非专业教学。
完整代码:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtTest import QTest
import sys
from functools import partial
class Singleton(object):
def __init__(self, cls):
self._cls = cls
self._instance = {}
def __call__(self):
if self._cls not in self._instance:
self._instance[self._cls] = self._cls()
return self._instance[self._cls]
class riLog(QDialog):
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.FramelessWindowHint |
Qt.WindowMinimizeButtonHint)
self.resize(700, 50)
self.cb = QLineEdit(self)
self.cb.setObjectName("cb")
self.cb.resize(550, 30)
self.cb.move(10, 10)
self.cb.setPlaceholderText("输入标签名称")
self.btn = QPushButton(self)
self.btn.setText('添加页面')
self.btn.resize(120, 40)
self.btn.move(570, 5)
self.btn.setObjectName("btn1")
self.btn.clicked.connect(self.addTabs)
Qss2 = '''
QPushButton#btn1
{
border-radius: 4px;
border:1px solid rgb(0,0,0);
font-size:20px;
background-color:#ffffff;
}
QComboBox#cb
{
}
'''
self.setStyleSheet(Qss2)
def openDialog(self):
self.setWindowTitle("Dialog")
self.setWindowModality(Qt.ApplicationModal)
self.exec_()
#自定义添加页面
def addTabs(self):
hide_tab = mw.tabs.tabs_text.index(mw.tabs.tabText(mw.tabs.page))
print(mw.tabs.tabs_text.index(mw.tabs.tabText(mw.tabs.page)))
print(len(mw.tabs.tabs_show_status))
if mw.tabs.barWidth + 130 > mw.w :
mw.tabs.tabs_show_status[hide_tab] = 0
mw.tabs.r += 1
#显示或隐藏tab菜单
mw.tabs.tabMenuState()
#根据calcutab()展示tab
mw.tabs.updatetab()
#根据calcutab()隐藏tab至tabMenu
mw.tabs.updatetabMenu()
print('有隐藏添加')
if len(self.cb.displayText()) == 0 :
mw.tabs.addTabs(len(mw.tabs.tabs_show_status), '空白页面'+str(len(mw.tabs.tabs_show_status)))
print('无名添加')
print(mw.tabs.tabs_text)
else:
if len(self.cb.displayText()) > 13 :
tabtext = self.cb.displayText()
mw.tabs.addTabs(len(mw.tabs.tabs_show_status), tabtext[0:13])
else :
mw.tabs.addTabs(len(mw.tabs.tabs_show_status), self.cb.displayText())
print('有名添加')
print(mw.tabs.tabs_show_status)
""" print(mw.tabs.tabs_show_status)
print(self.cb.displayText()) """
#显示或隐藏tab菜单
mw.tabs.tabMenuState()
#根据calcutab()展示tab
mw.tabs.updatetab()
#根据calcutab()隐藏tab至tabMenu
mw.tabs.updatetabMenu()
#跳转至新页面
jump = mw.tabs.indexOf(mw.tabs.tabs_page[len(mw.tabs.tabs_page)-1])
mw.tabs.setCurrentIndex(jump)
mw.tabs.update()
self.reject()
#重写QtabWidget
class TabWidget(QTabWidget):
def __init__(self):
super(TabWidget,self).__init__()
self.tabbar = TabBar(self)
self.setTabBar(self.tabbar)
self.setTabsClosable(True)
#self.setUsesScrollButtons(False)
#工具数据
self.tabs_show_status = {}
self.tabs_text = []
self.tabs_page = {}
self.tabs_width = {}
self.tabs_menu_item = {}
self.r=0
self.l=0
self.barWidth=0
self.page=-1
#创建标签菜单按钮
self.btn_menu = QPushButton(self)
self.btn_menu.hide()
self.btn_menu_state = 0
self.menu = QMenu(self)
self.menu_tab = QAction('菜单',self)
self.menu.addAction(self.menu_tab)
#self.btn_menu = QPushButton(self)
""" self.btn_menu.resize(30, 30)
self.btn_menu.setText('菜单')
self.btn_menu.move(0, 0) """
self.btn_menu.clicked.connect(self.onClicked)
self.tabCloseRequested.connect(self.delTabs)
def onClicked(self):
self.menu.exec_(QCursor.pos())
def delTabs(self,index):
""" self.tabs_show_status = {}
self.tabs_text = []
self.tabs_page = {}
self.tabs_width = {}
self.tabs_menu_item = {} """
print('----------------------------------------')
print(self.tabs_show_status)
print(self.tabs_text)
print(self.tabs_page)
print(self.tabs_width)
print(self.tabs_menu_item)
print('----------------------------------------------')
del_tab = mw.tabs.tabs_text.index(mw.tabs.tabText(index))
self.barWidth -= self.tabs_width[del_tab]
self.menu.removeAction(self.tabs_menu_item[del_tab])
self.tabs_text.pop(del_tab)
for i in range(0,len(self.tabs_show_status)-del_tab-1):
#将被删除标签后的标签数据前移
self.tabs_show_status[del_tab+i] = self.tabs_show_status[del_tab+i+1]
self.tabs_page[del_tab+i] = self.tabs_page[del_tab+i+1]
self.tabs_width[del_tab+i] = self.tabs_width[del_tab+i+1]
self.tabs_menu_item[del_tab+i] = self.tabs_menu_item[del_tab+i+1]
#移除最后一个数据
self.tabs_show_status.pop(len(self.tabs_show_status)-1)
self.tabs_page.pop(len(self.tabs_page)-1)
self.tabs_width.pop(len(self.tabs_width)-1)
self.tabs_menu_item.pop(len(self.tabs_menu_item)-1)
#更新数据
self.page -= 1
#移除页面
self.removeTab(index)
self.update()
print(self.tabs_show_status)
print(self.tabs_text)
print(self.tabs_page)
print(self.tabs_width)
print(self.tabs_menu_item)
print('-----------------------------------------------')
#添加页面方法
def addTabs(self,index,text):
self.tabs_page[index] = QWidget()
self.addTab(self.tabs_page[index], text)
self.tabs_text.append(text)
self.tabs_width[index] = self.tabbar.tabSizeHint(self.page+1).width()
self.tabs_show_status[index] = 1
#删除按钮
#self.tabbar.setTabButton(index, self.tabbar.RightSide, self.tabs_page[index])
#创建菜单
self.tabs_menu_item[index] = QAction(text,self)
self.menu.addAction(self.tabs_menu_item[index])
self.tabs_menu_item[index].triggered.connect(partial(self.menuJump,index))
self.btn_menu.resize(25, 30)
#窗口宽度
self.barWidth += self.tabs_width[index]
self.page += 1
#最右与最左tab的宽度
self.tab_Rwidth = self.tabbar.tabSizeHint(self.page).width()
self.tab_Lwidth = self.tabbar.tabSizeHint(0).width()
self.tabMenuState()
print(self.tabs_width)
print(self.tabs_show_status)
def update(self):
i=0
while self.barWidth != mw.w and i <= self.r+self.l:
i += 1
#计算展示的tab
self.calcutab()
#显示或隐藏tab菜单
self.tabMenuState()
#根据calcutab()展示tab
self.updatetab()
#根据calcutab()隐藏tab至tabMenu
self.updatetabMenu()
def tabMenuState(self):
self.btn_menu.setText('<<'+str(self.l+self.r))
self.btn_menu.move(self.barWidth-self.tabbar.tabSizeHint(0).height()*2-2, 0)
self.btn_menu.resize(self.tabbar.tabSizeHint(0).height()*2, self.tabbar.tabSizeHint(0).height())
if self.btn_menu_state == 0 and self.l+self.r > 0:
self.btn_menu_state = 1
self.btn_menu.show()
self.barWidth += self.tabbar.tabSizeHint(0).height()*2
print('添加菜单')
elif self.btn_menu_state == 1 and self.l+self.r == 0:
self.btn_menu_state = 0
self.btn_menu.hide()
self.barWidth -= self.tabbar.tabSizeHint(0).height()*2
print('移除菜单')
#计算需要展示的页面
def calcutab(self):
#当tab宽度大于窗口宽度时
if self.barWidth > mw.w:
self.tab_index = self.currentIndex()
#当前页面的右边tab比左边多
if (self.page-self.tab_index) >= self.tab_index:
""" index = 0
while self.tabs_show_status[len(self.tabs_show_status)-self.r-1+index] == 0 :
index += 1
self.tabs_show_status[len(self.tabs_show_status)-self.r-1+index] = 0 """
hide_tab = self.tabs_text.index(mw.tabs.tabText(self.page))
self.tabs_show_status[hide_tab] = 0
#更新数据
self.r += 1
self.tab_Rwidth = self.tabbar.tabSizeHint(self.page).width()
print('调用删右边')
print(self.tabs_show_status)
#当前页面的右边tab比左边少
else :
""" index = 0
while self.tabs_show_status[self.l-index] == 0 :
index += 1
self.tabs_show_status[self.l-index] = 0 """
hide_tab = self.tabs_text.index(mw.tabs.tabText(0))
self.tabs_show_status[hide_tab] = 0
#更新数据
self.l += 1
print('调用删左边')
print(self.tabs_show_status)
#当tab宽度小于窗口宽度时
elif self.barWidth+130 < mw.w and len(self.tabs_show_status)-self.r-self.l < len(self.tabs_show_status):
self.tab_index = self.currentIndex()
#当前页面的右边tab比左边多
if (self.page-self.tab_index) >= self.tab_index :
if self.l > 0 :
index = 0
while self.tabs_show_status[self.l-1+1-index] == 1 and self.l-1+1-index < len(self.tabs_show_status)-1:
index += 1
self.tabs_show_status[self.l-1+1-index] = 1
#更新数据
self.l -= 1
print('调用1左添加' )
print(self.tabs_show_status)
elif self.l == 0 :
index = 0
while self.tabs_show_status[len(self.tabs_page)-self.r-1+index] == 1 and len(self.tabs_page)-self.r-1+index < len(self.tabs_show_status)-1:
index += 1
self.tabs_show_status[len(self.tabs_page)-self.r-1+index] = 1
#更新数据
self.r -= 1
print('调用1右添加' )
print(self.tabs_show_status)
#当前页面的右边tab比左边少
elif (self.page-self.tab_index) < self.tab_index:
if self.r > 0 :
index = 0
while self.tabs_show_status[len(self.tabs_page)-self.r-1+index] == 1 and len(self.tabs_page)-self.r-1+index < len(self.tabs_page)-1:
index += 1
self.tabs_show_status[len(self.tabs_page)-self.r-1+index] = 1
#更新数据
self.r -= 1
print('调用2右添加' )
print(self.tabs_show_status)
elif self.r == 0 :
index = 0
while self.tabs_show_status[self.l-1+1-index] == 1 and self.l-1+1-index < len(self.tabs_show_status)-1:
index += 1
self.tabs_show_status[self.l-1+1-index] = 1
#更新数据
self.l -= 1
print('调用2左添加' )
print(self.tabs_show_status)
def updatetab(self):
for i in range(0,(len(self.tabs_page))):
#需添加页面
if self.indexOf(self.tabs_page[i]) == -1 and self.tabs_show_status[i] == 1:
x = 0
while self.indexOf(self.tabs_page[i+x]) == -1 and i+x < len(self.tabs_show_status)-1:
x += 1
if x > 0 and i+x != len(self.tabs_show_status)-1:
self.insertTab(self.indexOf(self.tabs_page[i+x]),self.tabs_page[i], str(self.tabs_text[i]))
else :
self.addTab(self.tabs_page[i], str(self.tabs_text[i]))
#更新数据
self.barWidth += self.tabs_width[i]
self.page += 1
print('调用3')
#需隐藏页面
if self.indexOf(self.tabs_page[i]) > -1 and self.tabs_show_status[i] == 0:
self.removeTab(self.indexOf(self.tabs_page[i]))
#更新数据
self.barWidth -= self.tabs_width[i]
self.page -= 1
self.tabMenuState()
def updatetabMenu(self):
for i in range(0,(len(self.tabs_page))):
#菜单需隐藏页面
if self.tabs_show_status[i] == 1:
self.tabs_menu_item[i].setVisible(False)
#菜单需显示页面
if self.tabs_show_status[i] == 0:
self.tabs_menu_item[i].setVisible(True)
def menuJump(self,sri):
print(self.tabs_show_status)
#所点tab右边
if sri > self.l :
self.tabs_show_status[sri] = 1
hide_tab = self.tabs_text.index(mw.tabs.tabText(0))
""" index=0
while self.tabs_show_status[index] == 0 :
index += 1 """
self.tabs_show_status[hide_tab] = 0
self.l += 1
self.r -= 1
elif sri < self.l :
self.tabs_show_status[sri] = 1
""" index=len(self.tabs_show_status)-1
while self.tabs_show_status[index] == 0 :
index -= 1 """
hide_tab = self.tabs_text.index(mw.tabs.tabText(self.page))
self.tabs_show_status[hide_tab] = 0
self.l -= 1
self.r += 1
self.update()
jump = self.indexOf(self.tabs_page[sri])
#跳转至新页面
self.setCurrentIndex(jump)
print('----------')
print(sri)
print('----------')
""" #根据calcutab()展示tab
self.updatetab()
#根据calcutab()隐藏tab至tabMenu
self.updatetabMenu() """
print('调用跳转')
print(self.tabs_show_status)
class TabBar(QTabBar):
def __init__(self,parent,*args,**kwargs):
QTabBar.__init__(self,parent,*args,**kwargs)
#self.setTabsClosable(True)
self.tabMoved.connect(self.tabMovedCode)
self.btn_menu_state=1
qss = '''
QTabBar::tab{
max-width:130;
min-width:50
}
'''
self.setStyleSheet(qss)
def tabMovedCode(self,x,y,):
""" self.tabs_show_status = {}
self.tabs_text = []
self.tabs_page = {}
self.tabs_width = {}
self.tabs_menu_item = {} """
""" print(move)
print(moved) """
print('--------------------------------')
print(mw.tabs.tabs_show_status)
print(mw.tabs.tabs_text)
print(mw.tabs.tabs_page)
print(mw.tabs.tabs_width)
print(mw.tabs.tabs_menu_item)
#获取被移动的tab在本地数组的位置
move = mw.tabs.tabs_text.index(mw.tabs.tabText(x)) #选择的tab
moved = mw.tabs.tabs_text.index(mw.tabs.tabText(y)) #被移动的副tab
#修改其数据
mw.tabs.tabs_show_status[999] = mw.tabs.tabs_show_status[move]
mw.tabs.tabs_show_status[move] = mw.tabs.tabs_show_status[moved]
mw.tabs.tabs_show_status[moved] = mw.tabs.tabs_show_status[999]
del mw.tabs.tabs_show_status[999]
char = mw.tabs.tabs_text[moved]
mw.tabs.tabs_text[moved] = mw.tabs.tabs_text[move]
mw.tabs.tabs_text[move] = char
mw.tabs.tabs_page[999] = mw.tabs.tabs_page[move]
mw.tabs.tabs_page[move] = mw.tabs.tabs_page[moved]
mw.tabs.tabs_page[moved] = mw.tabs.tabs_page[999]
del mw.tabs.tabs_page[999]
mw.tabs.tabs_width[999] = mw.tabs.tabs_width[move]
mw.tabs.tabs_width[move] = mw.tabs.tabs_width[moved]
mw.tabs.tabs_width[moved] = mw.tabs.tabs_width[999]
del mw.tabs.tabs_width[999]
mw.tabs.tabs_menu_item[999] = mw.tabs.tabs_menu_item[move]
mw.tabs.tabs_menu_item[move] = mw.tabs.tabs_menu_item[moved]
mw.tabs.tabs_menu_item[moved] = mw.tabs.tabs_menu_item[999]
""" mw.tabs.tabs_menu_item[move].triggered.connect(partial(mw.tabs.menuJump,move))
mw.tabs.tabs_menu_item[moved].triggered.connect(partial(mw.tabs.menuJump,moved)) """
del mw.tabs.tabs_menu_item[999]
for i in range (0,len(mw.tabs.tabs_menu_item)):
mw.tabs.tabs_menu_item[i].triggered.connect(partial(mw.tabs.menuJump,i))
print(move)
print(moved)
print('--------------------------------')
print(mw.tabs.tabs_show_status)
print(mw.tabs.tabs_text)
print(mw.tabs.tabs_page)
print(mw.tabs.tabs_width)
print(mw.tabs.tabs_menu_item)
def btnMenu(self):
self.btn_menu[0] = QPushButton(self)
self.btn_menu.setText('菜单')
self.btn_menu.resize(30, 30)
#self.btn_menu.move(500, 500)
print('菜单创建')
class MainWindow(QMainWindow):
_instance = None
def __new__(cls, *args, **kw):
""" if cls._instance is None:
cls._instance = QMainWindow.__new__(cls, *args, **kw)
return cls._instance """
if not hasattr(cls,'mw'):
orig = super(MainWindow,cls)
cls.mw = orig.__new__(cls,*args, **kw)
return cls.mw
def __init__(self,parent=None, *args, **kwargs):
QMainWindow.__init__(self, parent, *args,**kwargs)
#新
self.x = str(0)
AllWidget = QWidget()
Alllayout = QVBoxLayout()
# 设置控件无边界 无边框
Alllayout.setSpacing(0)
Alllayout.setContentsMargins(0, 0, 0, 0)
AllWidget.setLayout(Alllayout)
self.tabs = TabWidget()
self.tabs.setMovable(True)
self.tb = self.addToolBar("File")
self.addtabs = QAction("添加页面",self)
self.tb.addAction(self.addtabs)
self.dialog = riLog()
self.addtabs.triggered.connect(self.dialog.openDialog)
for i in range(0,10):
self.x += str(i)
self.tabs.addTabs(i, "Tab"+self.x)
self.setCentralWidget(self.tabs)
self.resize(2000, 1000)
self.tabs.move(100,100)
""" self.btn = QPushButton(self)
self.btn.move(0,0) """
#Alllayout.addWidget(self.tabs.tabbar)
Alllayout.addWidget(self.tabs)
#Alllayout.addWidget(self.btn_menu)
self.setCentralWidget(AllWidget)
def resizeEvent(self, event):
self.w = event.size().width()
self.h = event.size().height()
#print('刷新')
self.tabs.update()
def changeEvent(self, event):
self.tabs.update()
#print('最大化')
print(self.w)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
效果如下:

本文档详细描述了一个带有动态下拉菜单和按钮的标签管理系统的实现,用户可以添加新页面,页面名称受输入限制,且支持删除功能。系统能根据窗口大小自动调整标签显示和隐藏,点击菜单项可快速跳转至对应标签页。
5427

被折叠的 条评论
为什么被折叠?



