最近在学习使用pyqt5制作窗口界面,实习正好有一个实习项目是做一个类似eclipse和火狐累
的tabMenu,来保存被隐藏的tabs,如下?
? ? ??
?????????尝试制作了一下,之前是用我自己的方法做了,后面被大佬指点了一下,完全改版了重新制作。目前效果如下:? ? ? ?
? ? ? ? ?
????????基本完成了tabs的宽度因窗口宽度的变化而显示tabs页面,并且被隐藏的页面与当前所显示的页面索引相关,意思是当前显示页面必定会在标签栏中间如下:
? ? ? ? 显示菜单的tab也是在有页面被隐藏的情况下才会显示,如下:
? ? ? ? 并且当tabMenu中的tab被点击时会在标签栏中插入该tab并将离它最远的tab隐藏至tabMenu中,如下:
?????????点击后:
? ? ? ? 被点击的tab为Tab0012,故将其添加回标签栏,并将Tab00234567隐藏于tabMenu中,并且拉伸窗口后其顺序不变.
? ? ? ? 本人只是初学,代码仍有许多待优化,进步的地方,仅供分享,非技术性展示.
主要代码结构:
def update(self):
#计算展示的tab
self.calcutab()
#显示或隐藏tab菜单
self.tabMenuState()
#根据calcutab()展示tab
self.updatetab()
#根据calcutab()隐藏tab至tabMenu
self.updatetabMenu()
主要代码部分:
1、计算显示的tab
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
#更新数据
self.r += 1
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
#更新数据
self.l += 1
print('调用删左边')
print(self.tabs_show_status)
#当tab宽度小于窗口宽度时
elif self.barWidth+mw.tab_Rwidth < 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 :
if self.tabs_show_status[self.l-1] == 0 :
self.tabs_show_status[self.l-1] = 1
elif self.tabs_show_status[self.l-1] == 1 :
self.tabs_show_status[self.l] = 1
#更新数据
self.l -= 1
print('调用1左添加' )
print(self.tabs_show_status)
elif self.l == 0 :
print('当前')
if self.tabs_show_status[len(self.tabs_page)-self.r] == 0 :
self.tabs_show_status[len(self.tabs_page)-self.r] = 1
elif self.tabs_show_status[len(self.tabs_page)-self.r] == 1 :
self.tabs_show_status[len(self.tabs_page)-self.r-1] = 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 :
if self.tabs_show_status[len(self.tabs_page)-self.r] == 0 :
self.tabs_show_status[len(self.tabs_page)-self.r] = 1
elif self.tabs_show_status[len(self.tabs_page)-self.r] == 1 :
self.tabs_show_status[len(self.tabs_page)-self.r-1] = 1
#更新数据
self.r -= 1
print('调用2右添加' )
print(self.tabs_show_status)
elif self.r == 0 :
if self.tabs_show_status[self.l-1] == 0 :
self.tabs_show_status[self.l-1] = 1
elif self.tabs_show_status[self.l-1] == 1 :
self.tabs_show_status[self.l] = 1
#更新数据
self.l -= 1
print('调用2左添加' )
print(self.tabs_show_status)
2、标签页更新
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.insertTab(self.indexOf(self.tab_menu),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
3、更新被隐藏tab菜单
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)
? ? ? ? 其他部位为使代码能运行的补充与部分方法,完整代码如下,代码并非绝对还原eclipse,还有很多改善的地方,仅个人学习记录与分享.
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]
#重写QtabWidget
class TabWidget(QTabWidget):
def __init__(self):
super(TabWidget,self).__init__()
self.tabbar = TabBar(self)
self.setTabBar(self.tabbar)
#工具数据
self.tabs_show_status = {0:1,1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1}
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.tab_menu = QWidget()
self.menu = QMenu(self)
self.menu_tab = QAction('菜单',self)
self.menu.addAction(self.menu_tab)
self.tabBarClicked.connect(self.onClicked)
def onClicked(self, index):
if self.indexOf(self.tab_menu) > -1 and mw.tabs.count()-1 == index:
self.menu.exec_(QCursor.pos())
def update(self):
#计算展示的tab
self.calcutab()
#显示或隐藏tab菜单
self.tabMenuState()
#根据calcutab()展示tab
self.updatetab()
#根据calcutab()隐藏tab至tabMenu
self.updatetabMenu()
def tabMenuState(self):
if self.indexOf(self.tab_menu) == -1 and self.l+self.r > 0:
self.addTab(self.tab_menu, "<<")
self.barWidth += self.tabbar.tabSizeHint(self.indexOf(self.tab_menu)).width()
print('调用menu1')
print(self.l)
print(self.r)
elif self.indexOf(self.tab_menu) > -1 and self.l+self.r == 0:
self.barWidth -= self.tabbar.tabSizeHint(self.indexOf(self.tab_menu)).width()
self.removeTab(self.indexOf(self.tab_menu))
#self.page -= 1
print('调用menu2')
#计算需要展示的页面
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
#更新数据
self.r += 1
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
#更新数据
self.l += 1
print('调用删左边')
print(self.tabs_show_status)
#当tab宽度小于窗口宽度时
elif self.barWidth+mw.tab_Rwidth < 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 :
if self.tabs_show_status[self.l-1] == 0 :
self.tabs_show_status[self.l-1] = 1
elif self.tabs_show_status[self.l-1] == 1 :
self.tabs_show_status[self.l] = 1
#更新数据
self.l -= 1
print('调用1左添加' )
print(self.tabs_show_status)
elif self.l == 0 :
print('当前')
if self.tabs_show_status[len(self.tabs_page)-self.r] == 0 :
self.tabs_show_status[len(self.tabs_page)-self.r] = 1
elif self.tabs_show_status[len(self.tabs_page)-self.r] == 1 :
self.tabs_show_status[len(self.tabs_page)-self.r-1] = 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 :
if self.tabs_show_status[len(self.tabs_page)-self.r] == 0 :
self.tabs_show_status[len(self.tabs_page)-self.r] = 1
elif self.tabs_show_status[len(self.tabs_page)-self.r] == 1 :
self.tabs_show_status[len(self.tabs_page)-self.r-1] = 1
#更新数据
self.r -= 1
print('调用2右添加' )
print(self.tabs_show_status)
elif self.r == 0 :
if self.tabs_show_status[self.l-1] == 0 :
self.tabs_show_status[self.l-1] = 1
elif self.tabs_show_status[self.l-1] == 1 :
self.tabs_show_status[self.l] = 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.insertTab(self.indexOf(self.tab_menu),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
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
index=0
while self.tabs_show_status[index] == 0 :
index += 1
self.tabs_show_status[index] = 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
self.tabs_show_status[index] = 0
self.l -= 1
self.r += 1
#根据calcutab()展示tab
self.updatetab()
#根据calcutab()隐藏tab至tabMenu
self.updatetabMenu()
print(self.tabs_show_status)
class TabBar(QTabBar):
def __init__(self,parent,*args,**kwargs):
QTabBar.__init__(self,parent,*args,**kwargs)
self.tabMoved.connect(self.tabMovedCode)
def tabMovedCode(self,x,y,):
mw.tabs.tabs_page[999] = mw.tabs.tabs_page[y]
mw.tabs.tabs_page[y] = mw.tabs.tabs_page[x]
mw.tabs.tabs_page[x] = mw.tabs.tabs_page[999]
del mw.tabs.tabs_page[999]
char = mw.tabs.tabs_text[x]
mw.tabs.tabs_text[x] = mw.tabs.tabs_text[y]
mw.tabs.tabs_text[y] = char
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()
self.btn = QPushButton()
# Alllayout = QHBoxLayout()
Alllayout = QVBoxLayout()
# 设置控件无边界 无边框
Alllayout.setSpacing(0)
Alllayout.setContentsMargins(0, 0, 0, 0)
AllWidget.setLayout(Alllayout)
self.tabs = TabWidget()
self.tabs.setMovable(True)
self.tab_menu = QWidget()
for i in range(0,10):
self.tabs.tabs_page[i] = QWidget()
self.x += str(i)
self.tabs.addTab(self.tabs.tabs_page[i], "Tab"+self.x)
self.tabs.tabs_text.append(self.tabs.tabText(i))
self.tabs.tabs_width[i] = self.tabs.tabbar.tabSizeHint(i).width()
#创建菜单
self.tabs.tabs_menu_item[i] = QAction(self.tabs.tabText(i),self)
self.tabs.menu.addAction(self.tabs.tabs_menu_item[i])
self.tabs.tabs_menu_item[i].triggered.connect(partial(self.tabs.menuJump,i))
#窗口宽度
self.tabs.barWidth += self.tabs.tabs_width[i]
self.tabs.page += 1
#最右与最左tab的宽度
self.tab_Rwidth = self.tabs.tabbar.tabSizeHint(self.tabs.page).width()
self.tab_Lwidth = self.tabs.tabbar.tabSizeHint(0).width()
print(self.tabs.tabs_width)
self.setCentralWidget(self.tabs)
self.resize(2000, 1000)
Alllayout.addWidget(self.tabs)
self.setCentralWidget(AllWidget)
def resizeEvent(self, event):
self.w = event.size().width()
self.h = event.size().height()
self.tabs.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
|