PySide & QWT object disable/destroy
-
I am just learning OOP and PySide. I have created a code as below. The application doesn't do anything much (it's a development project in learning stages).
import numpy as np import sys from qtpy.QtWidgets import ( QWidget, QMainWindow, QVBoxLayout, QAction, QMenu, QLabel, QApplication, QMessageBox, QDesktopWidget, ) from qtpy.QtCore import Qt, Slot, QPoint, QObject from qwt import ( QwtPlot, QwtPlotMarker, QwtPlotGrid, QwtLegend, QwtPlotCurve, QwtLegendData, ) class contexMenuHelper(QObject): def __init__(self, plot, legend, legendItem): super(contexMenuHelper, self).__init__() self.plot = plot self.legend = legend self.legendItem = legendItem @Slot(QPoint) def contextMenuSlot(self, pos): context = QMenu(self.legendItem) context.addAction(QAction("Delete", self)) context.exec_(self.legendItem.mapToGlobal(pos)) class Plot(QwtPlot, QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setAxisTitle(QwtPlot.xBottom, "X-axis") self.setAxisTitle(QwtPlot.yLeft, "Y-axis") self.setCanvasBackground(Qt.white) self.setAxisScale(QwtPlot.yLeft, -2, 2) QwtPlotGrid.make(self, color=Qt.lightGray, width=0, style=Qt.DotLine) legend = QwtLegend() legend.setDefaultItemMode(QwtLegendData.Checkable) self.insertLegend(legend, QwtPlot.RightLegend) x = np.arange(-5.0, 5.0, 0.1) curves = [] curves.append( QwtPlotCurve.make( x, np.cos(x), "Cosinus", self, linecolor="red", antialiased=True ) ) curves.append( QwtPlotCurve.make( x, np.sin(x), "Sinus", self, linecolor="blue", antialiased=True ) ) self.helpers = dict() for a in curves: legend.legendWidget(a).setContextMenuPolicy(Qt.CustomContextMenu) h = contexMenuHelper(self, legend, legend.legendWidget(a)) self.helpers[a] = h legend.legendWidget(a).customContextMenuRequested.connect(h.contextMenuSlot) QwtPlotMarker.make( align=Qt.AlignRight | Qt.AlignTop, linestyle=QwtPlotMarker.HLine, color="black", plot=self, ) for keys, value in self.helpers.items(): print(keys) print(value) # insert a vertical marker at x = 0 QwtPlotMarker.make( align=Qt.AlignRight | Qt.AlignTop, linestyle=QwtPlotMarker.VLine, color="black", plot=self, ) legend.checked.connect(self.showCurve) self.replot() @Slot(object, bool, int) def showCurve(self, obj, condition, num): obj.setVisible(not condition) self.replot() @Slot(object, bool, int) def __del__(self, obj, condition): print('Destructor called, vehicle deleted.') class SimplePlot(QWidget): def __init__(self, parent=None): super().__init__(parent) layout = QVBoxLayout() self.setLayout(layout) plot = Plot() plot.setTitle("Trigonometric") self.setWindowTitle("Trigonometric") layout.addWidget(plot) label = QLabel("Press the legend to en/disable a curve") layout.addWidget(label) self.center() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def closeEvent(self, event): reply = QMessageBox.question( self, "Message", "Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No, ) if reply == QMessageBox.Yes: event.accept() else: event.ignore() if __name__ == "__main__": app = QApplication(sys.argv) window = SimplePlot() window.show() window.resize(800, 600) sys.exit(app.exec_())
I made the active legend and the context menu.
I want to make it so that when I select "Delete" from the context menu, the corresponding function waveform in the graph and the corresponding object in the legend will be deleted. -
Hi and welcome to devnet,
One way is to keep a map of legend and curve and in the slot connected to your delete action you remove both from the plot.
-
Did you build the map I suggested ?
-
Hi.
@SGaist
Unfortunately I don't understand what you are writing about, I am new to PySide :( . Please provide clear translations.I made it this way.
Please write if it is correct ?
And how else can it be done ?import numpy as np import sys from qtpy.QtWidgets import ( QWidget, QMainWindow, QVBoxLayout, QAction, QMenu, QLabel, QApplication, QMessageBox, QDesktopWidget, ) from qtpy.QtCore import Qt, Slot, QPoint, QObject from qwt import ( QwtPlot, QwtPlotMarker, QwtPlotGrid, QwtLegend, QwtPlotCurve, QwtLegendData, ) class contexMenuHelper(QObject): def __init__(self, plot, legend, legendItem): super(contexMenuHelper, self).__init__() self.plot = plot self.legend = legend self.legendItem = legendItem self.emlSel = QAction("Delete") @Slot(QPoint) def contextMenuSlot(self, pos): context = QMenu(self.legendItem) context.addAction(self.emlSel) context.exec_(self.legendItem.mapToGlobal(pos)) self.emlSel.triggered.connect(self.destroy()) @Slot() def destroy(self): QwtPlotCurve.detach(self.legend) class Plot(QwtPlot, QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setAxisTitle(QwtPlot.xBottom, "X-axis") self.setAxisTitle(QwtPlot.yLeft, "Y-axis") self.setCanvasBackground(Qt.white) self.setAxisScale(QwtPlot.yLeft, -2, 2) QwtPlotGrid.make(self, color=Qt.lightGray, width=0, style=Qt.DotLine) legend = QwtLegend() legend.setDefaultItemMode(QwtLegendData.Checkable) legend.resize(100,100) self.insertLegend(legend, QwtPlot.RightLegend) x = np.arange(-5.0, 5.0, 0.1) curves = [] curves.append( QwtPlotCurve.make( x, np.cos(x), "Cosinus", self, linecolor="red", antialiased=True ) ) curves.append( QwtPlotCurve.make( x, np.sin(x), "Sinus", self, linecolor="blue", antialiased=True ) ) self.helpers = dict() for a in curves: legend.legendWidget(a).setContextMenuPolicy(Qt.CustomContextMenu) h = contexMenuHelper(self, a, legend.legendWidget(a)) self.helpers[a] = h legend.legendWidget(a).customContextMenuRequested.connect(h.contextMenuSlot) QwtPlotMarker.make( align=Qt.AlignRight | Qt.AlignTop, linestyle=QwtPlotMarker.HLine, color="black", plot=self, ) QwtPlotMarker.make( align=Qt.AlignRight | Qt.AlignTop, linestyle=QwtPlotMarker.VLine, color="black", plot=self, ) legend.checked.connect(self.showCurve) self.replot() @Slot(object, bool, int) def showCurve(self, obj, condition, num): obj.setVisible(not condition) self.replot() class SimplePlot(QWidget): def __init__(self, parent=None): super().__init__(parent) layout = QVBoxLayout() self.setLayout(layout) plot = Plot() plot.setTitle("Trigonometric") self.setWindowTitle("Trigonometric") layout.addWidget(plot) label = QLabel("Press the legend to en/disable a curve") layout.addWidget(label) self.center() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def closeEvent(self, event): reply = QMessageBox.question( self, "Message", "Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No, ) if reply == QMessageBox.Yes: event.accept() else: event.ignore() if __name__ == "__main__": app = QApplication(sys.argv) window = SimplePlot() window.show() window.resize(850, 600) sys.exit(app.exec_())
-
Sorry, I think I have misunderstood your answer. You have it working so I am unsure what you were asking.