是否可以拖动 QTabWidget 并打开一个新窗口,其中包含 pyqt5 中此选项卡中的内容? [英] Is it possible to drag a QTabWidget and open a new window containing what's in this Tab in pyqt5?
问题描述
我想知道是否可以通过单击并拖动选项卡来打开一个包含该选项卡中内容的新窗口.如果可能的话,我也想做相反的事情:将新窗口拖到选项卡内(它最初所在的位置).
I'm wondering if it is possible by clicking and dragging a Tab to open a new window with what was in that Tab. If it's possible, I would like to also do the reverse: dragging the new window inside the Tabs (where it was in the first place).
我不知道该怎么开始.我在一些论坛上读到所有都必须编码,但我不知道 Qt 是否允许某些工具这样做?
I don't know how should I start. I read in some forums that all must be coded but I don't know if Qt allows some facilities to do that?
这里以代码为起点:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.centralTabs= QTabWidget()
self.setCentralWidget(self.centralTabs)
self.setFixedWidth(200)
self.setFixedHeight(200)
#tab 1
self.tab_1 = QWidget()
self.centralTabs.addTab(self.tab_1,"Label")
vbox = QVBoxLayout()
Label = QLabel('Tab1')
Label.setFixedWidth(180)
LineEdit = QLineEdit('Tab1')
LineEdit.setFixedWidth(180)
vbox.addWidget(Label)
vbox.addWidget(LineEdit)
vbox.setAlignment(Qt.AlignTop)
self.tab_1.setLayout(vbox)
#tab 2
self.tab_2 = QWidget()
self.centralTabs.addTab(self.tab_2,"Label")
vbox = QVBoxLayout()
Label = QLabel('Tab2')
Label.setFixedWidth(180)
LineEdit = QLineEdit('Tab2')
LineEdit.setFixedWidth(180)
vbox.addWidget(Label)
vbox.addWidget(LineEdit)
vbox.setAlignment(Qt.AlignTop)
self.tab_2.setLayout(vbox)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
这离我的 Qt 水平还很远,所以我在寻求帮助.如果我很好理解,我需要重新实现 QTabWidget
的 mousePressEvent()
和 dragMoveEvent()
吗?他们是这个话题:在PyQt4中,是不是可以从 QTabWidget 中分离选项卡吗? 但它与 PYQT4 一起使用,而我使用的是 PYQT5.
This is far from my Qt level, so I'm asking some help.
If I well understood, I need to reimplement the mousePressEvent()
and the dragMoveEvent()
of the QTabWidget
?
Their is this topic: In PyQt4, is it possible to detach tabs from a QTabWidget? but it is with PYQT4 and I'm using PYQT5.
因此,根据 在 PyQt4 中,是否可以从 QTabWidget 中分离标签? 并在转换为 pyqt5 后
So, according to In PyQt4, is it possible to detach tabs from a QTabWidget? and after conversion toward pyqt5
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class DetachableTabWidget(QTabWidget):
def __init__(self, parent=None):
QTabWidget.__init__(self, parent)
self.tabBar = self.TabBar(self)
self.tabBar.onDetachTabSignal.connect(self.detachTab)
self.tabBar.onMoveTabSignal.connect(self.moveTab)
self.setTabBar(self.tabBar)
##
# The default movable functionality of QTabWidget must remain disabled
# so as not to conflict with the added features
def setMovable(self, movable):
pass
##
# Move a tab from one position (index) to another
#
# @param fromIndex the original index location of the tab
# @param toIndex the new index location of the tab
@pyqtSlot(int, int)
def moveTab(self, fromIndex, toIndex):
widget = self.widget(fromIndex)
icon = self.tabIcon(fromIndex)
text = self.tabText(fromIndex)
self.removeTab(fromIndex)
self.insertTab(toIndex, widget, icon, text)
self.setCurrentIndex(toIndex)
##
# Detach the tab by removing it's contents and placing them in
# a DetachedTab dialog
#
# @param index the index location of the tab to be detached
# @param point the screen position for creating the new DetachedTab dialog
@pyqtSlot(int, QPoint)
def detachTab(self, index, point):
# Get the tab content
name = self.tabText(index)
icon = self.tabIcon(index)
if icon.isNull():
icon = self.window().windowIcon()
contentWidget = self.widget(index)
contentWidgetRect = contentWidget.frameGeometry()
# Create a new detached tab window
detachedTab = self.DetachedTab(contentWidget, self.parentWidget())
detachedTab.setWindowModality(Qt.NonModal)
detachedTab.setWindowTitle(name)
detachedTab.setWindowIcon(icon)
detachedTab.setObjectName(name)
detachedTab.setGeometry(contentWidgetRect)
detachedTab.onCloseSignal.connect(self.attachTab)
detachedTab.move(point)
detachedTab.show()
##
# Re-attach the tab by removing the content from the DetachedTab dialog,
# closing it, and placing the content back into the DetachableTabWidget
#
# @param contentWidget the content widget from the DetachedTab dialog
# @param name the name of the detached tab
# @param icon the window icon for the detached tab
@pyqtSlot(QWidget, type(''), QIcon)
def attachTab(self, contentWidget, name, icon):
# Make the content widget a child of this widget
contentWidget.setParent(self)
# Create an image from the given icon
if not icon.isNull():
tabIconPixmap = icon.pixmap(icon.availableSizes()[0])
tabIconImage = tabIconPixmap.toImage()
else:
tabIconImage = None
# Create an image of the main window icon
if not icon.isNull():
windowIconPixmap = self.window().windowIcon().pixmap(icon.availableSizes()[0])
windowIconImage = windowIconPixmap.toImage()
else:
windowIconImage = None
# Determine if the given image and the main window icon are the same.
# If they are, then do not add the icon to the tab
if tabIconImage == windowIconImage:
index = self.addTab(contentWidget, name)
else:
index = self.addTab(contentWidget, icon, name)
# Make this tab the current tab
if index > -1:
self.setCurrentIndex(index)
##
# When a tab is detached, the contents are placed into this QDialog. The tab
# can be re-attached by closing the dialog or by double clicking on its
# window frame.
class DetachedTab(QDialog):
onCloseSignal = pyqtSignal(QWidget,type(''), QIcon)
def __init__(self, contentWidget, parent=None):
QDialog.__init__(self, parent)
layout = QVBoxLayout(self)
self.contentWidget = contentWidget
layout.addWidget(self.contentWidget)
self.contentWidget.show()
self.setWindowFlags(Qt.Window)
##
# Capture a double click event on the dialog's window frame
#
# @param event an event
#
# @return true if the event was recognized
def event(self, event):
# If the event type is QEvent.NonClientAreaMouseButtonDblClick then
# close the dialog
if event.type() == 176:
event.accept()
self.close()
return QDialog.event(self, event)
##
# If the dialog is closed, emit the onCloseSignal and give the
# content widget back to the DetachableTabWidget
#
# @param event a close event
def closeEvent(self, event):
self.onCloseSignal.emit(self.contentWidget, self.objectName(), self.windowIcon())
##
# The TabBar class re-implements some of the functionality of the QTabBar widget
class TabBar(QTabBar):
onDetachTabSignal = pyqtSignal(int, QPoint)
onMoveTabSignal = pyqtSignal(int, int)
def __init__(self, parent=None):
QTabBar.__init__(self, parent)
self.setAcceptDrops(True)
self.setElideMode(Qt.ElideRight)
self.setSelectionBehaviorOnRemove(QTabBar.SelectLeftTab)
self.dragStartPos = QPoint()
self.dragDropedPos = QPoint()
self.mouseCursor = QCursor()
self.dragInitiated = False
##
# Send the onDetachTabSignal when a tab is double clicked
#
# @param event a mouse double click event
def mouseDoubleClickEvent(self, event):
event.accept()
self.onDetachTabSignal.emit(self.tabAt(event.pos()), self.mouseCursor.pos())
##
# Set the starting position for a drag event when the mouse button is pressed
#
# @param event a mouse press event
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.dragStartPos = event.pos()
self.dragDropedPos.setX(0)
self.dragDropedPos.setY(0)
self.dragInitiated = False
QTabBar.mousePressEvent(self, event)
##
# Determine if the current movement is a drag. If it is, convert it into a QDrag. If the
# drag ends inside the tab bar, emit an onMoveTabSignal. If the drag ends outside the tab
# bar, emit an onDetachTabSignal.
#
# @param event a mouse move event
def mouseMoveEvent(self, event):
# Determine if the current movement is detected as a drag
if not self.dragStartPos.isNull() and ((event.pos() - self.dragStartPos).manhattanLength() < QApplication.startDragDistance()):
self.dragInitiated = True
# If the current movement is a drag initiated by the left button
if (((event.buttons() & Qt.LeftButton)) and self.dragInitiated):
# Stop the move event
finishMoveEvent = QMouseEvent(QEvent.MouseMove, event.pos(), Qt.NoButton, Qt.NoButton, Qt.NoModifier)
QTabBar.mouseMoveEvent(self, finishMoveEvent)
# Convert the move event into a drag
drag = QDrag(self)
mimeData = QMimeData()
mimeData.setData('action', b'application/tab-detach')
drag.setMimeData(mimeData)
#Create the appearance of dragging the tab content
pixmap = self.parentWidget().grab()
targetPixmap = QPixmap(pixmap.size())
targetPixmap.fill(Qt.transparent)
painter = QPainter(targetPixmap)
painter.setOpacity(0.85)
painter.drawPixmap(0, 0, pixmap)
painter.end()
drag.setPixmap(targetPixmap)
# Initiate the drag
dropAction = drag.exec_(Qt.MoveAction | Qt.CopyAction)
# If the drag completed outside of the tab bar, detach the tab and move
# the content to the current cursor position
if dropAction == Qt.IgnoreAction:
event.accept()
self.onDetachTabSignal.emit(self.tabAt(self.dragStartPos), self.mouseCursor.pos())
# Else if the drag completed inside the tab bar, move the selected tab to the new position
elif dropAction == Qt.MoveAction:
if not self.dragDropedPos.isNull():
event.accept()
self.onMoveTabSignal.emit(self.tabAt(self.dragStartPos), self.tabAt(self.dragDropedPos))
else:
QTabBar.mouseMoveEvent(self, event)
##
# Determine if the drag has entered a tab position from another tab position
#
# @param event a drag enter event
def dragEnterEvent(self, event):
mimeData = event.mimeData()
formats = mimeData.formats()
if 'action' in formats and mimeData.data('action') == 'application/tab-detach':
event.acceptProposedAction()
QTabBar.dragMoveEvent(self, event)
##
# Get the position of the end of the drag
#
# @param event a drop event
def dropEvent(self, event):
self.dragDropedPos = event.pos()
QTabBar.dropEvent(self, event)
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.centralTabs= DetachableTabWidget()
self.setCentralWidget(self.centralTabs)
self.setFixedWidth(200)
self.setFixedHeight(200)
#tab 1
self.tab_1 = QWidget()
self.centralTabs.addTab(self.tab_1,"Label")
vbox = QVBoxLayout()
Label = QLabel('Tab1')
Label.setFixedWidth(180)
LineEdit = QLineEdit('Tab1')
LineEdit.setFixedWidth(180)
vbox.addWidget(Label)
vbox.addWidget(LineEdit)
vbox.setAlignment(Qt.AlignTop)
self.tab_1.setLayout(vbox)
#tab 2
self.tab_2 = QWidget()
self.centralTabs.addTab(self.tab_2,"Label")
vbox = QVBoxLayout()
Label = QLabel('Tab2')
Label.setFixedWidth(180)
LineEdit = QLineEdit('Tab2')
LineEdit.setFixedWidth(180)
vbox.addWidget(Label)
vbox.addWidget(LineEdit)
vbox.setAlignment(Qt.AlignTop)
self.tab_2.setLayout(vbox)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
该代码仍然存在一个问题.当几个标签被分离并且当我以错误的顺序关闭它们时,标签在主窗口中的顺序错误.我希望它们的顺序与原来相同
It stil have one issue with that code. When several Tabs are detatched and when I close them in the wrong order, the Tabs are going in the wrong order in the main window. I would like to have them in the same order as originally
所以我重写了 attachTab
函数,以便将 Tab 放回分离前的位置:
So I rewrite the attachTab
function in order to put back the Tab where they were before detachment:
def attachTab(self, contentWidget, name, icon):
# Make the content widget a child of this widget
contentWidget.setParent(self)
# Create an image from the given icon
if not icon.isNull():
tabIconPixmap = icon.pixmap(icon.availableSizes()[0])
tabIconImage = tabIconPixmap.toImage()
else:
tabIconImage = None
# Create an image of the main window icon
if not icon.isNull():
windowIconPixmap = self.window().windowIcon().pixmap(icon.availableSizes()[0])
windowIconImage = windowIconPixmap.toImage()
else:
windowIconImage = None
# Determine if the given image and the main window icon are the same.
# If they are, then do not add the icon to the tab
if name == 'Model Selection':
index = 0
elif name == "Model' Parameters":
index = 1
elif name == 'Stim settings':
index = 2
elif name == 'Parameter evolution settings':
index = 3
elif name == 'LambdaE':
index = 4
elif name == 'Simulation settings':
index = 5
elif name == 'LFP + PPS + Pulse Results':
index = 6
if tabIconImage == windowIconImage:
index = self.insertTab(index,contentWidget, name)
# index = self.addTab(contentWidget, name)
else:
# index = self.addTab(contentWidget, icon, name)
index = self.insertTab(index,contentWidget, icon, name)
# Make this tab the current tab
if index > -1:
self.setCurrentIndex(index)
所以每一个Tab都是按照起始位置插入的,但是一切都是手工完成的.也许它存在一种自动的方法来做到这一点.
So every Tab is insert according to the starting position, but everything is done by hand. Maybe it exists an automatic way to do that.
我还增加了阻力最小距离,因为我觉得它太短了ni mouseMoveEvent
函数:
I also increase the drag minimal distance because it seems too short too me
ni the mouseMoveEvent
function :
if not self.dragStartPos.isNull() and ((event.pos() - self.dragStartPos).manhattanLength() > QApplication.startDragDistance()*2):
我也修改了 <to > 仅在距离大于 startDragDistance()
Ialso modify the < to > to initiate the drag only if the distance is greater than startDragDistance()
推荐答案
这是在 PyQt4 上开发的代码,用于 PyQt 中的可拆卸选项卡小部件.希望这对您有所帮助.
This is code developed on PyQt4 for detachable tab widget in PyQt. Hope this will help you.
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import pyqtSignal, pyqtSlot
##
# The DetachableTabWidget adds additional functionality to Qt's QTabWidget that allows it
# to detach and re-attach tabs.
#
# Additional Features:
# Detach tabs by
# dragging the tabs away from the tab bar
# double clicking the tab
# Re-attach tabs by
# closing the detached tab's window
# double clicking the detached tab's window frame
#
# Modified Features:
# Re-ordering (moving) tabs by dragging was re-implemented
#
class DetachableTabWidget(QtGui.QTabWidget):
def __init__(self, parent=None):
QtGui.QTabWidget.__init__(self, parent)
self.tabBar = self.TabBar(self)
self.tabBar.onDetachTabSignal.connect(self.detachTab)
self.tabBar.onMoveTabSignal.connect(self.moveTab)
self.setTabBar(self.tabBar)
##
# The default movable functionality of QTabWidget must remain disabled
# so as not to conflict with the added features
def setMovable(self, movable):
pass
##
# Move a tab from one position (index) to another
#
# @param fromIndex the original index location of the tab
# @param toIndex the new index location of the tab
@pyqtSlot(int, int)
def moveTab(self, fromIndex, toIndex):
widget = self.widget(fromIndex)
icon = self.tabIcon(fromIndex)
text = self.tabText(fromIndex)
self.removeTab(fromIndex)
self.insertTab(toIndex, widget, icon, text)
self.setCurrentIndex(toIndex)
##
# Detach the tab by removing it's contents and placing them in
# a DetachedTab dialog
#
# @param index the index location of the tab to be detached
# @param point the screen position for creating the new DetachedTab dialog
@pyqtSlot(int, QtCore.QPoint)
def detachTab(self, index, point):
# Get the tab content
name = self.tabText(index)
icon = self.tabIcon(index)
if icon.isNull():
icon = self.window().windowIcon()
contentWidget = self.widget(index)
contentWidgetRect = contentWidget.frameGeometry()
# Create a new detached tab window
detachedTab = self.DetachedTab(contentWidget, self.parentWidget())
detachedTab.setWindowModality(QtCore.Qt.NonModal)
detachedTab.setWindowTitle(name)
detachedTab.setWindowIcon(icon)
detachedTab.setObjectName(name)
detachedTab.setGeometry(contentWidgetRect)
detachedTab.onCloseSignal.connect(self.attachTab)
detachedTab.move(point)
detachedTab.show()
##
# Re-attach the tab by removing the content from the DetachedTab dialog,
# closing it, and placing the content back into the DetachableTabWidget
#
# @param contentWidget the content widget from the DetachedTab dialog
# @param name the name of the detached tab
# @param icon the window icon for the detached tab
@pyqtSlot(QtGui.QWidget, QtCore.QString, QtGui.QIcon)
def attachTab(self, contentWidget, name, icon):
# Make the content widget a child of this widget
contentWidget.setParent(self)
# Create an image from the given icon
if not icon.isNull():
tabIconPixmap = icon.pixmap(icon.availableSizes()[0])
tabIconImage = tabIconPixmap.toImage()
else:
tabIconImage = None
# Create an image of the main window icon
if not icon.isNull():
windowIconPixmap = self.window().windowIcon().pixmap(icon.availableSizes()[0])
windowIconImage = windowIconPixmap.toImage()
else:
windowIconImage = None
# Determine if the given image and the main window icon are the same.
# If they are, then do not add the icon to the tab
if tabIconImage == windowIconImage:
index = self.addTab(contentWidget, name)
else:
index = self.addTab(contentWidget, icon, name)
# Make this tab the current tab
if index > -1:
self.setCurrentIndex(index)
##
# When a tab is detached, the contents are placed into this QDialog. The tab
# can be re-attached by closing the dialog or by double clicking on its
# window frame.
class DetachedTab(QtGui.QDialog):
onCloseSignal = pyqtSignal(QtGui.QWidget, QtCore.QString, QtGui.QIcon)
def __init__(self, contentWidget, parent=None):
QtGui.QDialog.__init__(self, parent)
layout = QtGui.QVBoxLayout(self)
self.contentWidget = contentWidget
layout.addWidget(self.contentWidget)
self.contentWidget.show()
##
# Capture a double click event on the dialog's window frame
#
# @param event an event
#
# @return true if the event was recognized
def event(self, event):
# If the event type is QEvent.NonClientAreaMouseButtonDblClick then
# close the dialog
if event.type() == 176:
event.accept()
self.close()
return QtGui.QDialog.event(self, event)
##
# If the dialog is closed, emit the onCloseSignal and give the
# content widget back to the DetachableTabWidget
#
# @param event a close event
def closeEvent(self, event):
self.onCloseSignal.emit(self.contentWidget, self.objectName(), self.windowIcon())
##
# The TabBar class re-implements some of the functionality of the QTabBar widget
class TabBar(QtGui.QTabBar):
onDetachTabSignal = pyqtSignal(int, QtCore.QPoint)
onMoveTabSignal = pyqtSignal(int, int)
def __init__(self, parent=None):
QtGui.QTabBar.__init__(self, parent)
self.setAcceptDrops(True)
self.setElideMode(QtCore.Qt.ElideRight)
self.setSelectionBehaviorOnRemove(QtGui.QTabBar.SelectLeftTab)
self.dragStartPos = QtCore.QPoint()
self.dragDropedPos = QtCore.QPoint()
self.mouseCursor = QtGui.QCursor()
self.dragInitiated = False
##
# Send the onDetachTabSignal when a tab is double clicked
#
# @param event a mouse double click event
def mouseDoubleClickEvent(self, event):
event.accept()
self.onDetachTabSignal.emit(self.tabAt(event.pos()), self.mouseCursor.pos())
##
# Set the starting position for a drag event when the mouse button is pressed
#
# @param event a mouse press event
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.dragStartPos = event.pos()
self.dragDropedPos.setX(0)
self.dragDropedPos.setY(0)
self.dragInitiated = False
QtGui.QTabBar.mousePressEvent(self, event)
##
# Determine if the current movement is a drag. If it is, convert it into a QDrag. If the
# drag ends inside the tab bar, emit an onMoveTabSignal. If the drag ends outside the tab
# bar, emit an onDetachTabSignal.
#
# @param event a mouse move event
def mouseMoveEvent(self, event):
# Determine if the current movement is detected as a drag
if not self.dragStartPos.isNull() and ((event.pos() - self.dragStartPos).manhattanLength() < QtGui.QApplication.startDragDistance()):
self.dragInitiated = True
# If the current movement is a drag initiated by the left button
if (((event.buttons() & QtCore.Qt.LeftButton)) and self.dragInitiated):
# Stop the move event
finishMoveEvent = QtGui.QMouseEvent(QtCore.QEvent.MouseMove, event.pos(), QtCore.Qt.NoButton, QtCore.Qt.NoButton, QtCore.Qt.NoModifier)
QtGui.QTabBar.mouseMoveEvent(self, finishMoveEvent)
# Convert the move event into a drag
drag = QtGui.QDrag(self)
mimeData = QtCore.QMimeData()
mimeData.setData('action', 'application/tab-detach')
drag.setMimeData(mimeData)
# Create the appearance of dragging the tab content
pixmap = QtGui.QPixmap.grabWindow(self.parentWidget().currentWidget().winId())
targetPixmap = QtGui.QPixmap(pixmap.size())
targetPixmap.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(targetPixmap)
painter.setOpacity(0.85)
painter.drawPixmap(0, 0, pixmap)
painter.end()
drag.setPixmap(targetPixmap)
# Initiate the drag
dropAction = drag.exec_(QtCore.Qt.MoveAction | QtCore.Qt.CopyAction)
# If the drag completed outside of the tab bar, detach the tab and move
# the content to the current cursor position
if dropAction == QtCore.Qt.IgnoreAction:
event.accept()
self.onDetachTabSignal.emit(self.tabAt(self.dragStartPos), self.mouseCursor.pos())
# Else if the drag completed inside the tab bar, move the selected tab to the new position
elif dropAction == QtCore.Qt.MoveAction:
if not self.dragDropedPos.isNull():
event.accept()
self.onMoveTabSignal.emit(self.tabAt(self.dragStartPos), self.tabAt(self.dragDropedPos))
else:
QtGui.QTabBar.mouseMoveEvent(self, event)
##
# Determine if the drag has entered a tab position from another tab position
#
# @param event a drag enter event
def dragEnterEvent(self, event):
mimeData = event.mimeData()
formats = mimeData.formats()
if formats.contains('action') and mimeData.data('action') == 'application/tab-detach':
event.acceptProposedAction()
QtGui.QTabBar.dragMoveEvent(self, event)
##
# Get the position of the end of the drag
#
# @param event a drop event
def dropEvent(self, event):
self.dragDropedPos = event.pos()
QtGui.QTabBar.dropEvent(self, event)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
mainWindow = QtGui.QMainWindow()
tabWidget = DetachableTabWidget(mainWindow)
tab1 = QtGui.QLabel('Test Widget 1')
tabWidget.addTab(tab1, 'Tab1')
tab2 = QtGui.QLabel('Test Widget 2')
tabWidget.addTab(tab2, 'Tab2')
tab3 = QtGui.QLabel('Test Widget 3')
tabWidget.addTab(tab3, 'Tab3')
tabWidget.show()
mainWindow.setCentralWidget(tabWidget)
mainWindow.show()
try:
exitStatus = app.exec_()
print 'Done...'
sys.exit(exitStatus)
except:
pass
这篇关于是否可以拖动 QTabWidget 并打开一个新窗口,其中包含 pyqt5 中此选项卡中的内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!