我正在尝试从选项卡小部件中拖动选项卡并拆分查看区域(-如Eclipse一样,然后将选项卡标题拖至编辑区域中-类似于PyCharm中选项卡上的“垂直拆分”功能)。
我尝试使用拖放,但是无法获取选项卡的主要区域(例如,文本区域)来注册来自QTabBar的拖动。然后,我尝试仅跟随鼠标的移动进行操作,但走得更远,但分离器代码工作不佳,并且代码很丑陋。
注意,我没有使用可停靠的小部件,因为此代码将用于应用程序的中央小部件。我更喜欢使用拖放操作-任何人有任何想法吗?
from PyQt4.QtGui import QWidget, QDrag, QTabBar, QTabWidget, QPainter, QPalette,\ QBrush, QColor, QPen, QVBoxLayout, QHBoxLayout, QTextEdit, QCheckBox from PyQt4.QtCore import QByteArray, QMimeData, QPoint from PyQt4 import QtCore, QtGui class CentralTabWidget(QTabWidget): def __init__(self, parent=None): QTabWidget.__init__(self, parent) self.parent = parent tabBar = CentralTabBar(self) self.setTabBar(tabBar) self.addWidgets() def addWidgets(self): tab1 = QWidget() self.addTab(tab1, "Tab1") textArea = QTextEdit() textArea.setText("Text area 1") vBox = QVBoxLayout() vBox.addWidget(textArea) tab1.setLayout(vBox) tab2 = QWidget() self.addTab(tab2, "Tab2") textArea2 = QTextEdit() textArea2.setText("Text area 2") vBox2 = QVBoxLayout() vBox2.addWidget(textArea2) tab2.setLayout(vBox2) self.setAcceptDrops(True) self.verticalLineOverlay = Overlay(parent = self) self.verticalLineOverlay.hide() def dragEnterEvent(self, event): mimeData = event.mimeData() event.accept() def dragMoveEvent(self, event): print(">>dragMoveEvent()") def dropEvent(self, event): mimeData = event.mimeData() event.setDropAction(QtCore.Qt.MoveAction) event.accept() def resizeEvent(self, event): self.verticalLineOverlay.resize(event.size()) event.accept() class CentralTabBar(QTabBar): def __init__(self, parent=None): QTabBar.__init__(self, parent) self.parent = parent self.__drag_start_pos = QPoint() self.setAcceptDrops(True) def mousePressEvent(self, event): self.__mousePressPos = None self.__mouseMovePos = None if event.button() == QtCore.Qt.LeftButton: self.__mousePressPos = event.globalPos() self.__mouseMovePos = event.globalPos() if self.parent.parent.dndCheckBox.isChecked(): self.startDrag() super(CentralTabBar, self).mousePressEvent(event) def mouseReleaseEvent(self, event): self.parent.verticalLineOverlay.setVisible(False) currPos = self.mapToGlobal(self.pos()) ax, ay, aw, ah = self.geometry().getRect() if currPos.x() > ax + aw/4: self.parent.parent.createSplitter() super(CentralTabBar, self).mouseReleaseEvent(event) def mouseMoveEvent(self, event): if event.buttons() == QtCore.Qt.LeftButton: currPos = self.mapToGlobal(self.pos()) globalPos = event.globalPos() diff = globalPos - self.__mouseMovePos newPos = self.mapFromGlobal(currPos + diff) xp1, yp1, xp2, yp2 = self.geometry().getCoords() ax, ay, aw, ah = self.geometry().getRect() parentx, parenty, parentw, parenth = self.parent.geometry().getCoords() if parenth > 10: if (newPos.y() > yp2) and (newPos.y() < (parenth)): self.parent.verticalLineOverlay.setVisible(True) super(CentralTabBar, self).mouseMoveEvent(event) def startDrag(self): data = QByteArray() mimeData = QMimeData() mimeData.setData("application/x-icon-and-text", data) print("Using DnD") drag = QDrag(self) drag.setMimeData(mimeData) drag.exec_() def dragEnterEvent(self, event): event.accept() def dragMoveEvent(self, event): print("--dragMoveEvent()") def dropEvent(self, event): event.setDropAction(QtCore.Qt.MoveAction) event.accept() class Overlay(QWidget): def __init__(self, parent=None): super(Overlay, self).__init__(parent) print("--__init__() parent type:{0}".format(type(parent))) self.parent = parent palette = QPalette(self.palette()) palette.setColor(palette.Background, QtCore.Qt.transparent) self.setPalette(palette) def paintEvent(self, event): self.painter = QPainter() self.painter.setPen(QPen(QtCore.Qt.NoPen)) self.painter.begin(self) self.painter.setRenderHint(QPainter.Antialiasing) self.painter.fillRect(self.parent.currentWidget().geometry(), QBrush(QColor(255, 255, 255, 10))) parentx, parenty, parentw, parenth = self.parent.geometry().getCoords() self.painter.drawRect( parentx, parenty, (parentw/2)-10, parenth) self.painter.drawRect( (parentw/2)+10, parenty, parentw, parenth) self.painter.setPen(QPen(QtCore.Qt.NoPen)) def setUpPainter(self): self.painter = QPainter() self.painter.setPen(QPen(QtCore.Qt.NoPen)) self.painter.begin(self) self.painter.setRenderHint(QPainter.Antialiasing) self.painter.fillRect(self.parent.currentWidget().geometry(), QBrush(QColor(255, 255, 255, 10))) parentx, parenty, parentw, parenth = self.parent.geometry().getCoords() class Window(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.layout = QHBoxLayout() self.dndCheckBox = QCheckBox("Use DnD") self.dndCheckBox.setChecked(True) self.ctw = CentralTabWidget(self) self.layout.addWidget(self.ctw) self.layout.addWidget(self.dndCheckBox) self.setLayout(self.layout) def createSplitter(self): #not sure why widgets are not redrawn inside the splitter splitter1 = QtGui.QSplitter(QtCore.Qt.Horizontal) self.removeWidgets(self.layout) splitter1.addWidget(self.ctw) self.layout.addWidget(splitter1) self.layout.addWidget(self.dndCheckBox) def removeWidgets(self, layout): for cnt in reversed(range(layout.count())): widget = layout.takeAt(cnt).widget() if widget is not None: widget.deleteLater() if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) window = Window() window.resize(350, 300) window.show() sys.exit(app.exec_())
在我尝试过的QMainMaindow内部使用QMainWindow:
from PyQt4 import QtCore, QtGui from PyQt4.QtGui import QMainWindow, QTextEdit, QDockWidget _DOCK_OPTS = QtGui.QMainWindow.AllowNestedDocks _DOCK_OPTS |= QtGui.QMainWindow.AllowTabbedDocks class Window(QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) secondQMainWindow = QMainWindow() self.central = secondQMainWindow self.setDockOptions(_DOCK_OPTS) dw1 = QDockWidget("One") textArea = QTextEdit() textArea.setText("Text area 1") dw1.setWidget(textArea) dw2 = QDockWidget("Two") textArea2 = QTextEdit() textArea2.setText("Text area 2") dw2.setWidget(textArea2) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dw1) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dw2) self.tabifyDockWidget(dw1, dw2) dw3 = QDockWidget("Three") textArea3 = QTextEdit() textArea3.setText("Text area 3") dw3.setWidget(textArea3) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dw3) if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) window = Window() window.show() app.exec_()
但是我认为我没有在父对子中央小部件中添加小部件。
[我正在尝试从选项卡小部件中拖动选项卡并拆分查看区域(-如Eclipse一样,然后将选项卡标题拖至编辑区域中-类似于...上的'垂直拆分'功能...
这是我过去用来完成您要寻找的技巧。如果您想对参数进行很多控制,则可能会受到很大限制,但确实可以做到。
同时支持选项卡到选项卡和选项卡到其他窗口的选项卡