PyQt:是否可以在QGridLayout中拖放QWidget以重新排列它们?

问题描述 投票:0回答:1

我正在寻找一种创建图形网格的方法,可以将其拖放以重新排列顺序。我的第一个尝试是使用QDockWidgets,因为它们允许拖放,但是它们在很多其他方面受到限制。是否可以在QGridLayout中实现此功能?

目前,我有一个带有3x3 matplotlib小部件的QGridLayout。

这里是所需布局结果的示例。

enter image description here

示例代码:

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_())
pyqt drag-and-drop pyqt5 qwidget qgridlayout
1个回答
0
投票

这里是一个实现,将交换拖放中所涉及项目的位置。 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_())
© www.soinside.com 2019 - 2024. All rights reserved.