我正在寻找一种创建图形网格的方法,可以将其拖放以重新排列顺序。我的第一个尝试是使用QDockWidgets,因为它们允许拖放,但是它们在很多其他方面受到限制。是否可以在QGridLayout中实现此功能?
目前,我有一个带有3x3 matplotlib小部件的QGridLayout。
这里是所需布局结果的示例。
示例代码:
import sys
from PyQt5 import QtWidgets
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import random
from PyQt5.QtWidgets import QGridLayout, QVBoxLayout, QHBoxLayout, QScrollArea, QWidget, QDialog, QApplication, QFrame
class IndicSelectWindow(QDialog):
def __init__(self, parent=None):
super(IndicSelectWindow, self).__init__(parent=parent)
self.resize(1000, 800)
self.layout = QtWidgets.QHBoxLayout(self)
self.scrollArea = QScrollArea(self)
self.scrollArea.setWidgetResizable(True)
self.scrollAreaWidgetContents = QWidget()
self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.layout.addWidget(self.scrollArea)
for i in range(3):
for j in range(3):
self.Frame = QFrame(self)
self.Frame.setStyleSheet("background-color: white;")
self.Frame.setFrameStyle(QFrame.Panel | QFrame.Raised)
self.Frame.setLineWidth(2)
self.layout = QHBoxLayout(self.Frame)
self.figure = Figure() # a figure to plot on
self.canvas = FigureCanvas(self.figure)
self.ax = self.figure.add_subplot(111) # create an axis
data = [random.random() for i in range(10)]
self.ax.plot(data, '*-') # plot data
self.canvas.draw() # refresh canvas
self.layout.addWidget(self.canvas)
Box = QVBoxLayout()
Box.addWidget(self.Frame)
self.gridLayout.addLayout(Box, i, j)
self.gridLayout.setColumnStretch(i % 3, 1)
self.gridLayout.setRowStretch(j, 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = IndicSelectWindow()
w.show()
sys.exit(app.exec_())
这里是一个实现,将交换拖放中所涉及项目的位置。 3个主要步骤是:
((1)重新实现mousePressEvent
以基于鼠标坐标获得LayoutItem
的索引。
((2)重新实现mouseMoveEvent
以设置FigureCanvas的QDrag
。
((3)重新实现dropEvent
以交换布局中的目标项目。
由于matplotlib小部件吸收了鼠标事件,因此您还需要重新实现eventFilter
才能检测到它们。
导入系统,随机从PyQt5.QtWidgets导入*从PyQt5.QtCore导入*从PyQt5.QtGui导入*从matplotlib.figure导入图从matplotlib.backends.backend_qt4agg导入FigureCanvasQTAgg作为FigureCanvasIndicSelectWindow(QDialog)类:def __init __(self,parent = None):超级(IndicSelectWindow,self).__ init __(parent = parent)self.resize(1000,800)self.target =无self.setAcceptDrops(True)self.layout = QHBoxLayout(self)self.scrollArea = QScrollArea(自我)self.scrollArea.setWidgetResizable(真)self.scrollAreaWidgetContents = QWidget()self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)self.scrollArea.setWidget(self.scrollAreaWidgetContents)self.layout.addWidget(self.scrollArea)对于我在范围(3)中:对于范围(3)中的j:self.Frame = QFrame(自身)self.Frame.setStyleSheet(“ background-color:white;”)self.Frame.setFrameStyle(QFrame.Panel | QFrame.Raised)self.Frame.setLineWidth(2)self.layout = QHBoxLayout(self.Frame)self.figure = Figure()#要绘制的图形self.canvas = FigureCanvas(self.figure)self.ax = self.figure.add_subplot(111)#创建一个轴数据= [i在range(10)中的random.random()]self.ax.plot(data,'*-')#绘制数据self.canvas.draw()#刷新画布self.canvas.installEventFilter(self)self.layout.addWidget(self.canvas)Box = QVBoxLayout()Box.addWidget(self.Frame)self.gridLayout.addLayout(Box,i,j)self.gridLayout.setColumnStretch(i%3,1)self.gridLayout.setRowStretch(j,1)def eventFilter(self,watched,event):如果event.type()== QEvent.MouseButtonPress:self.mousePressEvent(事件)elif event.type()== QEvent.MouseMove:self.mouseMoveEvent(事件)elif event.type()== QEvent.MouseButtonRelease:self.mouseReleaseEvent(事件)返回super()。eventFilter(观看,事件)def get_index(self,pos):对于我在range(self.gridLayout.count())中:如果self.gridLayout.itemAt(i).geometry()。contains(pos)并且i!= self.target:还给我def mousePressEvent(self,event):如果event.button()== Qt.LeftButton:self.target = self.get_index(event.windowPos()。toPoint())其他:self.target =无def mouseMoveEvent(self,event):如果event.buttons()和Qt.LeftButton以及self.target不是None:拖动= QDrag(self.gridLayout.itemAt(self.target))fc = self.gridLayout.itemAt(self.target).itemAt(0).widget()mimedata = QMimeData()mimedata.setImageData(self.gridLayout.itemAt(self.target).itemAt(0).widget()。grab())drag.setMimeData(mimedata)drag.exec_()def mouseReleaseEvent(self,event):self.target =无def dragEnterEvent(自我,事件):如果event.mimeData()。hasImage():event.accept()其他:event.ignore()def dropEvent(self,event):如果不是event.source()。geometry()。contains(event.pos()):源= self.get_index(event.pos())如果来源为None:返回i,j = max(self.target,source),min(self.target,source)p1,p2 = self.gridLayout.getItemPosition(i),self.gridLayout.getItemPosition(j)self.gridLayout.addItem(self.gridLayout.takeAt(i),* p2)self.gridLayout.addItem(self.gridLayout.takeAt(j),* p1)如果__name__ =='__main__':应用= QApplication(sys.argv)w = IndicSelectWindow()w.show()sys.exit(app.exec_())