0
我試圖從選項卡窗口小部件中拖動一個選項卡並拆分查看區域( - 就像eclipse那樣,然後將選項卡標題拖動到編輯區域 - 類似於「垂直分割」功能在PyCharm的一個標籤中)。從QTabWidget拖放選項卡
我嘗試了使用拖放操作,但無法獲得標籤主區域(例如文本區域)註冊來自QTabBar的拖動。然後,我嘗試了一下鼠標移動,並得到了更多,但分離器代碼不工作,它是非常醜陋的代碼。
NB我沒有使用可停靠的小部件,因爲此代碼將用於應用程序的中央小部件。我寧願使用拖放來做到這一點 - 任何人有任何想法?
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_()
但我不認爲我有另外的小部件的父VS子中央窗口部件是正確的。
我已經加入你的建議,原來的問題,企圖。我沒有正確的代碼 - 是否在第二個主窗口中添加'firstwidget'和'secondWidget'? - 我嘗試過,但有一個空白的對話框。 –
我寫了一個例子。我無法測試它,因爲我從m'y手機上寫下它。它應該工作它接近我做了什麼 –
如果我可以在你的手機上寫這個 –