From ab41c0335889d2b7ada7c0bbde1c1dc4972c8b08 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Thu, 14 Jan 2021 19:02:54 +0800
Subject: [PATCH 01/17] generate _pyqt6.py files
VideoTemplate_pyside6.py : regenerate for cuda feature
---
.../ScatterPlotSpeedTestTemplate_pyqt6.py | 44 ++++
examples/VideoTemplate_pyqt6.py | 203 ++++++++++++++++++
examples/VideoTemplate_pyside6.py | 6 +
examples/designerExample_pyqt6.py | 32 +++
examples/exampleLoaderTemplate_pyqt6.py | 93 ++++++++
.../exportDialogTemplate_pyqt6.py | 63 ++++++
pyqtgraph/canvas/CanvasTemplate_pyqt6.py | 92 ++++++++
.../canvas/TransformGuiTemplate_pyqt6.py | 55 +++++
pyqtgraph/console/template_pyqt6.py | 115 ++++++++++
.../flowchart/FlowchartCtrlTemplate_pyqt6.py | 65 ++++++
.../flowchart/FlowchartTemplate_pyqt6.py | 53 +++++
.../PlotItem/plotConfigTemplate_pyqt6.py | 178 +++++++++++++++
.../ViewBox/axisCtrlTemplate_pyqt6.py | 88 ++++++++
.../imageview/ImageViewTemplate_pyqt6.py | 151 +++++++++++++
14 files changed, 1238 insertions(+)
create mode 100644 examples/ScatterPlotSpeedTestTemplate_pyqt6.py
create mode 100644 examples/VideoTemplate_pyqt6.py
create mode 100644 examples/designerExample_pyqt6.py
create mode 100644 examples/exampleLoaderTemplate_pyqt6.py
create mode 100644 pyqtgraph/GraphicsScene/exportDialogTemplate_pyqt6.py
create mode 100644 pyqtgraph/canvas/CanvasTemplate_pyqt6.py
create mode 100644 pyqtgraph/canvas/TransformGuiTemplate_pyqt6.py
create mode 100644 pyqtgraph/console/template_pyqt6.py
create mode 100644 pyqtgraph/flowchart/FlowchartCtrlTemplate_pyqt6.py
create mode 100644 pyqtgraph/flowchart/FlowchartTemplate_pyqt6.py
create mode 100644 pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyqt6.py
create mode 100644 pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyqt6.py
create mode 100644 pyqtgraph/imageview/ImageViewTemplate_pyqt6.py
diff --git a/examples/ScatterPlotSpeedTestTemplate_pyqt6.py b/examples/ScatterPlotSpeedTestTemplate_pyqt6.py
new file mode 100644
index 00000000..d963d8fc
--- /dev/null
+++ b/examples/ScatterPlotSpeedTestTemplate_pyqt6.py
@@ -0,0 +1,44 @@
+# Form implementation generated from reading ui file 'examples\ScatterPlotSpeedTestTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(400, 300)
+ self.gridLayout = QtWidgets.QGridLayout(Form)
+ self.gridLayout.setObjectName("gridLayout")
+ self.sizeSpin = QtWidgets.QSpinBox(Form)
+ self.sizeSpin.setProperty("value", 10)
+ self.sizeSpin.setObjectName("sizeSpin")
+ self.gridLayout.addWidget(self.sizeSpin, 1, 1, 1, 1)
+ self.pixelModeCheck = QtWidgets.QCheckBox(Form)
+ self.pixelModeCheck.setObjectName("pixelModeCheck")
+ self.gridLayout.addWidget(self.pixelModeCheck, 1, 3, 1, 1)
+ self.label = QtWidgets.QLabel(Form)
+ self.label.setObjectName("label")
+ self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
+ self.plot = PlotWidget(Form)
+ self.plot.setObjectName("plot")
+ self.gridLayout.addWidget(self.plot, 0, 0, 1, 4)
+ self.randCheck = QtWidgets.QCheckBox(Form)
+ self.randCheck.setObjectName("randCheck")
+ self.gridLayout.addWidget(self.randCheck, 1, 2, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.pixelModeCheck.setText(_translate("Form", "pixel mode"))
+ self.label.setText(_translate("Form", "Size"))
+ self.randCheck.setText(_translate("Form", "Randomize"))
+from pyqtgraph import PlotWidget
diff --git a/examples/VideoTemplate_pyqt6.py b/examples/VideoTemplate_pyqt6.py
new file mode 100644
index 00000000..f69ebe0f
--- /dev/null
+++ b/examples/VideoTemplate_pyqt6.py
@@ -0,0 +1,203 @@
+# Form implementation generated from reading ui file 'VideoTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(695, 798)
+ self.centralwidget = QtWidgets.QWidget(MainWindow)
+ self.centralwidget.setObjectName("centralwidget")
+ self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.cudaCheck = QtWidgets.QCheckBox(self.centralwidget)
+ self.cudaCheck.setObjectName("cudaCheck")
+ self.gridLayout_2.addWidget(self.cudaCheck, 9, 0, 1, 2)
+ self.downsampleCheck = QtWidgets.QCheckBox(self.centralwidget)
+ self.downsampleCheck.setObjectName("downsampleCheck")
+ self.gridLayout_2.addWidget(self.downsampleCheck, 8, 0, 1, 2)
+ self.scaleCheck = QtWidgets.QCheckBox(self.centralwidget)
+ self.scaleCheck.setObjectName("scaleCheck")
+ self.gridLayout_2.addWidget(self.scaleCheck, 4, 0, 1, 1)
+ self.gridLayout = QtWidgets.QGridLayout()
+ self.gridLayout.setObjectName("gridLayout")
+ self.rawRadio = QtWidgets.QRadioButton(self.centralwidget)
+ self.rawRadio.setObjectName("rawRadio")
+ self.gridLayout.addWidget(self.rawRadio, 3, 0, 1, 1)
+ self.gfxRadio = QtWidgets.QRadioButton(self.centralwidget)
+ self.gfxRadio.setChecked(True)
+ self.gfxRadio.setObjectName("gfxRadio")
+ self.gridLayout.addWidget(self.gfxRadio, 2, 0, 1, 1)
+ self.stack = QtWidgets.QStackedWidget(self.centralwidget)
+ self.stack.setObjectName("stack")
+ self.page = QtWidgets.QWidget()
+ self.page.setObjectName("page")
+ self.gridLayout_3 = QtWidgets.QGridLayout(self.page)
+ self.gridLayout_3.setObjectName("gridLayout_3")
+ self.graphicsView = GraphicsView(self.page)
+ self.graphicsView.setObjectName("graphicsView")
+ self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 1)
+ self.stack.addWidget(self.page)
+ self.page_2 = QtWidgets.QWidget()
+ self.page_2.setObjectName("page_2")
+ self.gridLayout_4 = QtWidgets.QGridLayout(self.page_2)
+ self.gridLayout_4.setObjectName("gridLayout_4")
+ self.rawImg = RawImageWidget(self.page_2)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.rawImg.sizePolicy().hasHeightForWidth())
+ self.rawImg.setSizePolicy(sizePolicy)
+ self.rawImg.setObjectName("rawImg")
+ self.gridLayout_4.addWidget(self.rawImg, 0, 0, 1, 1)
+ self.stack.addWidget(self.page_2)
+ self.gridLayout.addWidget(self.stack, 0, 0, 1, 1)
+ self.rawGLRadio = QtWidgets.QRadioButton(self.centralwidget)
+ self.rawGLRadio.setObjectName("rawGLRadio")
+ self.gridLayout.addWidget(self.rawGLRadio, 4, 0, 1, 1)
+ self.gridLayout_2.addLayout(self.gridLayout, 1, 0, 1, 4)
+ self.dtypeCombo = QtWidgets.QComboBox(self.centralwidget)
+ self.dtypeCombo.setObjectName("dtypeCombo")
+ self.dtypeCombo.addItem("")
+ self.dtypeCombo.addItem("")
+ self.dtypeCombo.addItem("")
+ self.gridLayout_2.addWidget(self.dtypeCombo, 3, 2, 1, 1)
+ self.label = QtWidgets.QLabel(self.centralwidget)
+ self.label.setObjectName("label")
+ self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1)
+ self.rgbLevelsCheck = QtWidgets.QCheckBox(self.centralwidget)
+ self.rgbLevelsCheck.setObjectName("rgbLevelsCheck")
+ self.gridLayout_2.addWidget(self.rgbLevelsCheck, 4, 1, 1, 1)
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.minSpin2 = SpinBox(self.centralwidget)
+ self.minSpin2.setEnabled(False)
+ self.minSpin2.setObjectName("minSpin2")
+ self.horizontalLayout_2.addWidget(self.minSpin2)
+ self.label_3 = QtWidgets.QLabel(self.centralwidget)
+ self.label_3.setAlignment(QtCore.Qt.Alignment.AlignCenter)
+ self.label_3.setObjectName("label_3")
+ self.horizontalLayout_2.addWidget(self.label_3)
+ self.maxSpin2 = SpinBox(self.centralwidget)
+ self.maxSpin2.setEnabled(False)
+ self.maxSpin2.setObjectName("maxSpin2")
+ self.horizontalLayout_2.addWidget(self.maxSpin2)
+ self.gridLayout_2.addLayout(self.horizontalLayout_2, 5, 2, 1, 1)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.minSpin1 = SpinBox(self.centralwidget)
+ self.minSpin1.setObjectName("minSpin1")
+ self.horizontalLayout.addWidget(self.minSpin1)
+ self.label_2 = QtWidgets.QLabel(self.centralwidget)
+ self.label_2.setAlignment(QtCore.Qt.Alignment.AlignCenter)
+ self.label_2.setObjectName("label_2")
+ self.horizontalLayout.addWidget(self.label_2)
+ self.maxSpin1 = SpinBox(self.centralwidget)
+ self.maxSpin1.setObjectName("maxSpin1")
+ self.horizontalLayout.addWidget(self.maxSpin1)
+ self.gridLayout_2.addLayout(self.horizontalLayout, 4, 2, 1, 1)
+ self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+ self.minSpin3 = SpinBox(self.centralwidget)
+ self.minSpin3.setEnabled(False)
+ self.minSpin3.setObjectName("minSpin3")
+ self.horizontalLayout_3.addWidget(self.minSpin3)
+ self.label_4 = QtWidgets.QLabel(self.centralwidget)
+ self.label_4.setAlignment(QtCore.Qt.Alignment.AlignCenter)
+ self.label_4.setObjectName("label_4")
+ self.horizontalLayout_3.addWidget(self.label_4)
+ self.maxSpin3 = SpinBox(self.centralwidget)
+ self.maxSpin3.setEnabled(False)
+ self.maxSpin3.setObjectName("maxSpin3")
+ self.horizontalLayout_3.addWidget(self.maxSpin3)
+ self.gridLayout_2.addLayout(self.horizontalLayout_3, 6, 2, 1, 1)
+ self.lutCheck = QtWidgets.QCheckBox(self.centralwidget)
+ self.lutCheck.setObjectName("lutCheck")
+ self.gridLayout_2.addWidget(self.lutCheck, 7, 0, 1, 1)
+ self.alphaCheck = QtWidgets.QCheckBox(self.centralwidget)
+ self.alphaCheck.setObjectName("alphaCheck")
+ self.gridLayout_2.addWidget(self.alphaCheck, 7, 1, 1, 1)
+ self.gradient = GradientWidget(self.centralwidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.gradient.sizePolicy().hasHeightForWidth())
+ self.gradient.setSizePolicy(sizePolicy)
+ self.gradient.setObjectName("gradient")
+ self.gridLayout_2.addWidget(self.gradient, 7, 2, 1, 2)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
+ self.gridLayout_2.addItem(spacerItem, 3, 3, 1, 1)
+ self.fpsLabel = QtWidgets.QLabel(self.centralwidget)
+ font = QtGui.QFont()
+ font.setPointSize(12)
+ self.fpsLabel.setFont(font)
+ self.fpsLabel.setAlignment(QtCore.Qt.Alignment.AlignCenter)
+ self.fpsLabel.setObjectName("fpsLabel")
+ self.gridLayout_2.addWidget(self.fpsLabel, 0, 0, 1, 4)
+ self.rgbCheck = QtWidgets.QCheckBox(self.centralwidget)
+ self.rgbCheck.setObjectName("rgbCheck")
+ self.gridLayout_2.addWidget(self.rgbCheck, 3, 1, 1, 1)
+ self.label_5 = QtWidgets.QLabel(self.centralwidget)
+ self.label_5.setObjectName("label_5")
+ self.gridLayout_2.addWidget(self.label_5, 2, 0, 1, 1)
+ self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_4.setObjectName("horizontalLayout_4")
+ self.framesSpin = QtWidgets.QSpinBox(self.centralwidget)
+ self.framesSpin.setButtonSymbols(QtWidgets.QAbstractSpinBox.ButtonSymbols.NoButtons)
+ self.framesSpin.setProperty("value", 10)
+ self.framesSpin.setObjectName("framesSpin")
+ self.horizontalLayout_4.addWidget(self.framesSpin)
+ self.widthSpin = QtWidgets.QSpinBox(self.centralwidget)
+ self.widthSpin.setButtonSymbols(QtWidgets.QAbstractSpinBox.ButtonSymbols.PlusMinus)
+ self.widthSpin.setMaximum(10000)
+ self.widthSpin.setProperty("value", 512)
+ self.widthSpin.setObjectName("widthSpin")
+ self.horizontalLayout_4.addWidget(self.widthSpin)
+ self.heightSpin = QtWidgets.QSpinBox(self.centralwidget)
+ self.heightSpin.setButtonSymbols(QtWidgets.QAbstractSpinBox.ButtonSymbols.NoButtons)
+ self.heightSpin.setMaximum(10000)
+ self.heightSpin.setProperty("value", 512)
+ self.heightSpin.setObjectName("heightSpin")
+ self.horizontalLayout_4.addWidget(self.heightSpin)
+ self.gridLayout_2.addLayout(self.horizontalLayout_4, 2, 1, 1, 2)
+ self.sizeLabel = QtWidgets.QLabel(self.centralwidget)
+ self.sizeLabel.setText("")
+ self.sizeLabel.setObjectName("sizeLabel")
+ self.gridLayout_2.addWidget(self.sizeLabel, 2, 3, 1, 1)
+ MainWindow.setCentralWidget(self.centralwidget)
+
+ self.retranslateUi(MainWindow)
+ self.stack.setCurrentIndex(1)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
+ self.cudaCheck.setText(_translate("MainWindow", "Use CUDA (GPU) if available"))
+ self.downsampleCheck.setText(_translate("MainWindow", "Auto downsample"))
+ self.scaleCheck.setText(_translate("MainWindow", "Scale Data"))
+ self.rawRadio.setText(_translate("MainWindow", "RawImageWidget"))
+ self.gfxRadio.setText(_translate("MainWindow", "GraphicsView + ImageItem"))
+ self.rawGLRadio.setText(_translate("MainWindow", "RawGLImageWidget"))
+ self.dtypeCombo.setItemText(0, _translate("MainWindow", "uint8"))
+ self.dtypeCombo.setItemText(1, _translate("MainWindow", "uint16"))
+ self.dtypeCombo.setItemText(2, _translate("MainWindow", "float"))
+ self.label.setText(_translate("MainWindow", "Data type"))
+ self.rgbLevelsCheck.setText(_translate("MainWindow", "RGB"))
+ self.label_3.setText(_translate("MainWindow", "<--->"))
+ self.label_2.setText(_translate("MainWindow", "<--->"))
+ self.label_4.setText(_translate("MainWindow", "<--->"))
+ self.lutCheck.setText(_translate("MainWindow", "Use Lookup Table"))
+ self.alphaCheck.setText(_translate("MainWindow", "alpha"))
+ self.fpsLabel.setText(_translate("MainWindow", "FPS"))
+ self.rgbCheck.setText(_translate("MainWindow", "RGB"))
+ self.label_5.setText(_translate("MainWindow", "Image size"))
+from pyqtgraph import GradientWidget, GraphicsView, SpinBox
+from pyqtgraph.widgets.RawImageWidget import RawImageWidget
diff --git a/examples/VideoTemplate_pyside6.py b/examples/VideoTemplate_pyside6.py
index 5195583d..a9d386c8 100644
--- a/examples/VideoTemplate_pyside6.py
+++ b/examples/VideoTemplate_pyside6.py
@@ -27,6 +27,11 @@ class Ui_MainWindow(object):
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout_2 = QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName(u"gridLayout_2")
+ self.cudaCheck = QCheckBox(self.centralwidget)
+ self.cudaCheck.setObjectName(u"cudaCheck")
+
+ self.gridLayout_2.addWidget(self.cudaCheck, 9, 0, 1, 2)
+
self.downsampleCheck = QCheckBox(self.centralwidget)
self.downsampleCheck.setObjectName(u"downsampleCheck")
@@ -258,6 +263,7 @@ class Ui_MainWindow(object):
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
+ self.cudaCheck.setText(QCoreApplication.translate("MainWindow", u"Use CUDA (GPU) if available", None))
self.downsampleCheck.setText(QCoreApplication.translate("MainWindow", u"Auto downsample", None))
self.scaleCheck.setText(QCoreApplication.translate("MainWindow", u"Scale Data", None))
self.rawRadio.setText(QCoreApplication.translate("MainWindow", u"RawImageWidget", None))
diff --git a/examples/designerExample_pyqt6.py b/examples/designerExample_pyqt6.py
new file mode 100644
index 00000000..4145e6a9
--- /dev/null
+++ b/examples/designerExample_pyqt6.py
@@ -0,0 +1,32 @@
+# Form implementation generated from reading ui file 'examples\designerExample.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(400, 300)
+ self.gridLayout = QtWidgets.QGridLayout(Form)
+ self.gridLayout.setObjectName("gridLayout")
+ self.plotBtn = QtWidgets.QPushButton(Form)
+ self.plotBtn.setObjectName("plotBtn")
+ self.gridLayout.addWidget(self.plotBtn, 0, 0, 1, 1)
+ self.plot = PlotWidget(Form)
+ self.plot.setObjectName("plot")
+ self.gridLayout.addWidget(self.plot, 1, 0, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.plotBtn.setText(_translate("Form", "Plot!"))
+from pyqtgraph import PlotWidget
diff --git a/examples/exampleLoaderTemplate_pyqt6.py b/examples/exampleLoaderTemplate_pyqt6.py
new file mode 100644
index 00000000..dbfa5e08
--- /dev/null
+++ b/examples/exampleLoaderTemplate_pyqt6.py
@@ -0,0 +1,93 @@
+# Form implementation generated from reading ui file 'examples\exampleLoaderTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(846, 552)
+ self.gridLayout_2 = QtWidgets.QGridLayout(Form)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.splitter = QtWidgets.QSplitter(Form)
+ self.splitter.setOrientation(QtCore.Qt.Orientations.Horizontal)
+ self.splitter.setObjectName("splitter")
+ self.widget = QtWidgets.QWidget(self.splitter)
+ self.widget.setObjectName("widget")
+ self.gridLayout = QtWidgets.QGridLayout(self.widget)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.exampleTree = QtWidgets.QTreeWidget(self.widget)
+ self.exampleTree.setObjectName("exampleTree")
+ self.exampleTree.headerItem().setText(0, "1")
+ self.exampleTree.header().setVisible(False)
+ self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
+ self.graphicsSystemCombo = QtWidgets.QComboBox(self.widget)
+ self.graphicsSystemCombo.setObjectName("graphicsSystemCombo")
+ self.graphicsSystemCombo.addItem("")
+ self.graphicsSystemCombo.addItem("")
+ self.graphicsSystemCombo.addItem("")
+ self.graphicsSystemCombo.addItem("")
+ self.gridLayout.addWidget(self.graphicsSystemCombo, 2, 1, 1, 1)
+ self.qtLibCombo = QtWidgets.QComboBox(self.widget)
+ self.qtLibCombo.setObjectName("qtLibCombo")
+ self.qtLibCombo.addItem("")
+ self.qtLibCombo.addItem("")
+ self.qtLibCombo.addItem("")
+ self.qtLibCombo.addItem("")
+ self.qtLibCombo.addItem("")
+ self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
+ self.label_2 = QtWidgets.QLabel(self.widget)
+ self.label_2.setObjectName("label_2")
+ self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
+ self.label = QtWidgets.QLabel(self.widget)
+ self.label.setObjectName("label")
+ self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
+ self.loadBtn = QtWidgets.QPushButton(self.widget)
+ self.loadBtn.setObjectName("loadBtn")
+ self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
+ self.widget1 = QtWidgets.QWidget(self.splitter)
+ self.widget1.setObjectName("widget1")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1)
+ self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.loadedFileLabel = QtWidgets.QLabel(self.widget1)
+ font = QtGui.QFont()
+ font.setBold(True)
+ self.loadedFileLabel.setFont(font)
+ self.loadedFileLabel.setText("")
+ self.loadedFileLabel.setAlignment(QtCore.Qt.Alignment.AlignCenter)
+ self.loadedFileLabel.setObjectName("loadedFileLabel")
+ self.verticalLayout.addWidget(self.loadedFileLabel)
+ self.codeView = QtWidgets.QPlainTextEdit(self.widget1)
+ font = QtGui.QFont()
+ font.setFamily("Courier New")
+ self.codeView.setFont(font)
+ self.codeView.setObjectName("codeView")
+ self.verticalLayout.addWidget(self.codeView)
+ self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.graphicsSystemCombo.setItemText(0, _translate("Form", "default"))
+ self.graphicsSystemCombo.setItemText(1, _translate("Form", "native"))
+ self.graphicsSystemCombo.setItemText(2, _translate("Form", "raster"))
+ self.graphicsSystemCombo.setItemText(3, _translate("Form", "opengl"))
+ self.qtLibCombo.setItemText(0, _translate("Form", "default"))
+ self.qtLibCombo.setItemText(1, _translate("Form", "PyQt4"))
+ self.qtLibCombo.setItemText(2, _translate("Form", "PySide"))
+ self.qtLibCombo.setItemText(3, _translate("Form", "PyQt5"))
+ self.qtLibCombo.setItemText(4, _translate("Form", "PySide2"))
+ self.label_2.setText(_translate("Form", "Graphics System:"))
+ self.label.setText(_translate("Form", "Qt Library:"))
+ self.loadBtn.setText(_translate("Form", "Run Example"))
diff --git a/pyqtgraph/GraphicsScene/exportDialogTemplate_pyqt6.py b/pyqtgraph/GraphicsScene/exportDialogTemplate_pyqt6.py
new file mode 100644
index 00000000..55cbe3a8
--- /dev/null
+++ b/pyqtgraph/GraphicsScene/exportDialogTemplate_pyqt6.py
@@ -0,0 +1,63 @@
+# Form implementation generated from reading ui file 'pyqtgraph\GraphicsScene\exportDialogTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(241, 367)
+ self.gridLayout = QtWidgets.QGridLayout(Form)
+ self.gridLayout.setSpacing(0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.label = QtWidgets.QLabel(Form)
+ self.label.setObjectName("label")
+ self.gridLayout.addWidget(self.label, 0, 0, 1, 3)
+ self.itemTree = QtWidgets.QTreeWidget(Form)
+ self.itemTree.setObjectName("itemTree")
+ self.itemTree.headerItem().setText(0, "1")
+ self.itemTree.header().setVisible(False)
+ self.gridLayout.addWidget(self.itemTree, 1, 0, 1, 3)
+ self.label_2 = QtWidgets.QLabel(Form)
+ self.label_2.setObjectName("label_2")
+ self.gridLayout.addWidget(self.label_2, 2, 0, 1, 3)
+ self.formatList = QtWidgets.QListWidget(Form)
+ self.formatList.setObjectName("formatList")
+ self.gridLayout.addWidget(self.formatList, 3, 0, 1, 3)
+ self.exportBtn = QtWidgets.QPushButton(Form)
+ self.exportBtn.setObjectName("exportBtn")
+ self.gridLayout.addWidget(self.exportBtn, 6, 1, 1, 1)
+ self.closeBtn = QtWidgets.QPushButton(Form)
+ self.closeBtn.setObjectName("closeBtn")
+ self.gridLayout.addWidget(self.closeBtn, 6, 2, 1, 1)
+ self.paramTree = ParameterTree(Form)
+ self.paramTree.setObjectName("paramTree")
+ self.paramTree.headerItem().setText(0, "1")
+ self.paramTree.header().setVisible(False)
+ self.gridLayout.addWidget(self.paramTree, 5, 0, 1, 3)
+ self.label_3 = QtWidgets.QLabel(Form)
+ self.label_3.setObjectName("label_3")
+ self.gridLayout.addWidget(self.label_3, 4, 0, 1, 3)
+ self.copyBtn = QtWidgets.QPushButton(Form)
+ self.copyBtn.setObjectName("copyBtn")
+ self.gridLayout.addWidget(self.copyBtn, 6, 0, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "Export"))
+ self.label.setText(_translate("Form", "Item to export:"))
+ self.label_2.setText(_translate("Form", "Export format"))
+ self.exportBtn.setText(_translate("Form", "Export"))
+ self.closeBtn.setText(_translate("Form", "Close"))
+ self.label_3.setText(_translate("Form", "Export options"))
+ self.copyBtn.setText(_translate("Form", "Copy"))
+from ..parametertree import ParameterTree
diff --git a/pyqtgraph/canvas/CanvasTemplate_pyqt6.py b/pyqtgraph/canvas/CanvasTemplate_pyqt6.py
new file mode 100644
index 00000000..79557936
--- /dev/null
+++ b/pyqtgraph/canvas/CanvasTemplate_pyqt6.py
@@ -0,0 +1,92 @@
+# Form implementation generated from reading ui file 'pyqtgraph\canvas\CanvasTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(821, 578)
+ self.gridLayout_2 = QtWidgets.QGridLayout(Form)
+ self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout_2.setSpacing(0)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.splitter = QtWidgets.QSplitter(Form)
+ self.splitter.setOrientation(QtCore.Qt.Orientations.Horizontal)
+ self.splitter.setObjectName("splitter")
+ self.view = GraphicsView(self.splitter)
+ self.view.setObjectName("view")
+ self.vsplitter = QtWidgets.QSplitter(self.splitter)
+ self.vsplitter.setOrientation(QtCore.Qt.Orientations.Vertical)
+ self.vsplitter.setObjectName("vsplitter")
+ self.canvasCtrlWidget = QtWidgets.QWidget(self.vsplitter)
+ self.canvasCtrlWidget.setObjectName("canvasCtrlWidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.canvasCtrlWidget)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.autoRangeBtn = QtWidgets.QPushButton(self.canvasCtrlWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(1)
+ sizePolicy.setHeightForWidth(self.autoRangeBtn.sizePolicy().hasHeightForWidth())
+ self.autoRangeBtn.setSizePolicy(sizePolicy)
+ self.autoRangeBtn.setObjectName("autoRangeBtn")
+ self.gridLayout.addWidget(self.autoRangeBtn, 0, 0, 1, 2)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setSpacing(0)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.redirectCheck = QtWidgets.QCheckBox(self.canvasCtrlWidget)
+ self.redirectCheck.setObjectName("redirectCheck")
+ self.horizontalLayout.addWidget(self.redirectCheck)
+ self.redirectCombo = CanvasCombo(self.canvasCtrlWidget)
+ self.redirectCombo.setObjectName("redirectCombo")
+ self.horizontalLayout.addWidget(self.redirectCombo)
+ self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 2)
+ self.itemList = TreeWidget(self.canvasCtrlWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(100)
+ sizePolicy.setHeightForWidth(self.itemList.sizePolicy().hasHeightForWidth())
+ self.itemList.setSizePolicy(sizePolicy)
+ self.itemList.setHeaderHidden(True)
+ self.itemList.setObjectName("itemList")
+ self.itemList.headerItem().setText(0, "1")
+ self.gridLayout.addWidget(self.itemList, 2, 0, 1, 2)
+ self.resetTransformsBtn = QtWidgets.QPushButton(self.canvasCtrlWidget)
+ self.resetTransformsBtn.setObjectName("resetTransformsBtn")
+ self.gridLayout.addWidget(self.resetTransformsBtn, 3, 0, 1, 2)
+ self.mirrorSelectionBtn = QtWidgets.QPushButton(self.canvasCtrlWidget)
+ self.mirrorSelectionBtn.setObjectName("mirrorSelectionBtn")
+ self.gridLayout.addWidget(self.mirrorSelectionBtn, 4, 0, 1, 1)
+ self.reflectSelectionBtn = QtWidgets.QPushButton(self.canvasCtrlWidget)
+ self.reflectSelectionBtn.setObjectName("reflectSelectionBtn")
+ self.gridLayout.addWidget(self.reflectSelectionBtn, 4, 1, 1, 1)
+ self.canvasItemCtrl = QtWidgets.QWidget(self.vsplitter)
+ self.canvasItemCtrl.setObjectName("canvasItemCtrl")
+ self.ctrlLayout = QtWidgets.QGridLayout(self.canvasItemCtrl)
+ self.ctrlLayout.setContentsMargins(0, 0, 0, 0)
+ self.ctrlLayout.setSpacing(0)
+ self.ctrlLayout.setObjectName("ctrlLayout")
+ self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.autoRangeBtn.setText(_translate("Form", "Auto Range"))
+ self.redirectCheck.setToolTip(_translate("Form", "Check to display all local items in a remote canvas."))
+ self.redirectCheck.setText(_translate("Form", "Redirect"))
+ self.resetTransformsBtn.setText(_translate("Form", "Reset Transforms"))
+ self.mirrorSelectionBtn.setText(_translate("Form", "Mirror Selection"))
+ self.reflectSelectionBtn.setText(_translate("Form", "MirrorXY"))
+from ..widgets.GraphicsView import GraphicsView
+from ..widgets.TreeWidget import TreeWidget
+from .CanvasManager import CanvasCombo
diff --git a/pyqtgraph/canvas/TransformGuiTemplate_pyqt6.py b/pyqtgraph/canvas/TransformGuiTemplate_pyqt6.py
new file mode 100644
index 00000000..4b0d9880
--- /dev/null
+++ b/pyqtgraph/canvas/TransformGuiTemplate_pyqt6.py
@@ -0,0 +1,55 @@
+# Form implementation generated from reading ui file 'pyqtgraph\canvas\TransformGuiTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(224, 117)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+ Form.setSizePolicy(sizePolicy)
+ self.verticalLayout = QtWidgets.QVBoxLayout(Form)
+ self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout.setSpacing(1)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.translateLabel = QtWidgets.QLabel(Form)
+ self.translateLabel.setObjectName("translateLabel")
+ self.verticalLayout.addWidget(self.translateLabel)
+ self.rotateLabel = QtWidgets.QLabel(Form)
+ self.rotateLabel.setObjectName("rotateLabel")
+ self.verticalLayout.addWidget(self.rotateLabel)
+ self.scaleLabel = QtWidgets.QLabel(Form)
+ self.scaleLabel.setObjectName("scaleLabel")
+ self.verticalLayout.addWidget(self.scaleLabel)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.mirrorImageBtn = QtWidgets.QPushButton(Form)
+ self.mirrorImageBtn.setToolTip("")
+ self.mirrorImageBtn.setObjectName("mirrorImageBtn")
+ self.horizontalLayout.addWidget(self.mirrorImageBtn)
+ self.reflectImageBtn = QtWidgets.QPushButton(Form)
+ self.reflectImageBtn.setObjectName("reflectImageBtn")
+ self.horizontalLayout.addWidget(self.reflectImageBtn)
+ self.verticalLayout.addLayout(self.horizontalLayout)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.translateLabel.setText(_translate("Form", "Translate:"))
+ self.rotateLabel.setText(_translate("Form", "Rotate:"))
+ self.scaleLabel.setText(_translate("Form", "Scale:"))
+ self.mirrorImageBtn.setText(_translate("Form", "Mirror"))
+ self.reflectImageBtn.setText(_translate("Form", "Reflect"))
diff --git a/pyqtgraph/console/template_pyqt6.py b/pyqtgraph/console/template_pyqt6.py
new file mode 100644
index 00000000..0208f128
--- /dev/null
+++ b/pyqtgraph/console/template_pyqt6.py
@@ -0,0 +1,115 @@
+# Form implementation generated from reading ui file 'pyqtgraph\console\template.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(739, 497)
+ self.gridLayout = QtWidgets.QGridLayout(Form)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setSpacing(0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.splitter = QtWidgets.QSplitter(Form)
+ self.splitter.setOrientation(QtCore.Qt.Orientations.Vertical)
+ self.splitter.setObjectName("splitter")
+ self.layoutWidget = QtWidgets.QWidget(self.splitter)
+ self.layoutWidget.setObjectName("layoutWidget")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget)
+ self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.output = QtWidgets.QPlainTextEdit(self.layoutWidget)
+ font = QtGui.QFont()
+ font.setFamily("Monospace")
+ self.output.setFont(font)
+ self.output.setReadOnly(True)
+ self.output.setObjectName("output")
+ self.verticalLayout.addWidget(self.output)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.input = CmdInput(self.layoutWidget)
+ self.input.setObjectName("input")
+ self.horizontalLayout.addWidget(self.input)
+ self.historyBtn = QtWidgets.QPushButton(self.layoutWidget)
+ self.historyBtn.setCheckable(True)
+ self.historyBtn.setObjectName("historyBtn")
+ self.horizontalLayout.addWidget(self.historyBtn)
+ self.exceptionBtn = QtWidgets.QPushButton(self.layoutWidget)
+ self.exceptionBtn.setCheckable(True)
+ self.exceptionBtn.setObjectName("exceptionBtn")
+ self.horizontalLayout.addWidget(self.exceptionBtn)
+ self.verticalLayout.addLayout(self.horizontalLayout)
+ self.historyList = QtWidgets.QListWidget(self.splitter)
+ font = QtGui.QFont()
+ font.setFamily("Monospace")
+ self.historyList.setFont(font)
+ self.historyList.setObjectName("historyList")
+ self.exceptionGroup = QtWidgets.QGroupBox(self.splitter)
+ self.exceptionGroup.setObjectName("exceptionGroup")
+ self.gridLayout_2 = QtWidgets.QGridLayout(self.exceptionGroup)
+ self.gridLayout_2.setContentsMargins(-1, 0, -1, 0)
+ self.gridLayout_2.setHorizontalSpacing(2)
+ self.gridLayout_2.setVerticalSpacing(0)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.clearExceptionBtn = QtWidgets.QPushButton(self.exceptionGroup)
+ self.clearExceptionBtn.setEnabled(False)
+ self.clearExceptionBtn.setObjectName("clearExceptionBtn")
+ self.gridLayout_2.addWidget(self.clearExceptionBtn, 0, 6, 1, 1)
+ self.catchAllExceptionsBtn = QtWidgets.QPushButton(self.exceptionGroup)
+ self.catchAllExceptionsBtn.setCheckable(True)
+ self.catchAllExceptionsBtn.setObjectName("catchAllExceptionsBtn")
+ self.gridLayout_2.addWidget(self.catchAllExceptionsBtn, 0, 1, 1, 1)
+ self.catchNextExceptionBtn = QtWidgets.QPushButton(self.exceptionGroup)
+ self.catchNextExceptionBtn.setCheckable(True)
+ self.catchNextExceptionBtn.setObjectName("catchNextExceptionBtn")
+ self.gridLayout_2.addWidget(self.catchNextExceptionBtn, 0, 0, 1, 1)
+ self.onlyUncaughtCheck = QtWidgets.QCheckBox(self.exceptionGroup)
+ self.onlyUncaughtCheck.setChecked(True)
+ self.onlyUncaughtCheck.setObjectName("onlyUncaughtCheck")
+ self.gridLayout_2.addWidget(self.onlyUncaughtCheck, 0, 4, 1, 1)
+ self.exceptionStackList = QtWidgets.QListWidget(self.exceptionGroup)
+ self.exceptionStackList.setAlternatingRowColors(True)
+ self.exceptionStackList.setObjectName("exceptionStackList")
+ self.gridLayout_2.addWidget(self.exceptionStackList, 2, 0, 1, 7)
+ self.runSelectedFrameCheck = QtWidgets.QCheckBox(self.exceptionGroup)
+ self.runSelectedFrameCheck.setChecked(True)
+ self.runSelectedFrameCheck.setObjectName("runSelectedFrameCheck")
+ self.gridLayout_2.addWidget(self.runSelectedFrameCheck, 3, 0, 1, 7)
+ self.exceptionInfoLabel = QtWidgets.QLabel(self.exceptionGroup)
+ self.exceptionInfoLabel.setWordWrap(True)
+ self.exceptionInfoLabel.setObjectName("exceptionInfoLabel")
+ self.gridLayout_2.addWidget(self.exceptionInfoLabel, 1, 0, 1, 7)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
+ self.gridLayout_2.addItem(spacerItem, 0, 5, 1, 1)
+ self.label = QtWidgets.QLabel(self.exceptionGroup)
+ self.label.setObjectName("label")
+ self.gridLayout_2.addWidget(self.label, 0, 2, 1, 1)
+ self.filterText = QtWidgets.QLineEdit(self.exceptionGroup)
+ self.filterText.setObjectName("filterText")
+ self.gridLayout_2.addWidget(self.filterText, 0, 3, 1, 1)
+ self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "Console"))
+ self.historyBtn.setText(_translate("Form", "History.."))
+ self.exceptionBtn.setText(_translate("Form", "Exceptions.."))
+ self.exceptionGroup.setTitle(_translate("Form", "Exception Handling"))
+ self.clearExceptionBtn.setText(_translate("Form", "Clear Stack"))
+ self.catchAllExceptionsBtn.setText(_translate("Form", "Show All Exceptions"))
+ self.catchNextExceptionBtn.setText(_translate("Form", "Show Next Exception"))
+ self.onlyUncaughtCheck.setText(_translate("Form", "Only Uncaught Exceptions"))
+ self.runSelectedFrameCheck.setText(_translate("Form", "Run commands in selected stack frame"))
+ self.exceptionInfoLabel.setText(_translate("Form", "Stack Trace"))
+ self.label.setText(_translate("Form", "Filter (regex):"))
+from .CmdInput import CmdInput
diff --git a/pyqtgraph/flowchart/FlowchartCtrlTemplate_pyqt6.py b/pyqtgraph/flowchart/FlowchartCtrlTemplate_pyqt6.py
new file mode 100644
index 00000000..5cb9199b
--- /dev/null
+++ b/pyqtgraph/flowchart/FlowchartCtrlTemplate_pyqt6.py
@@ -0,0 +1,65 @@
+# Form implementation generated from reading ui file 'pyqtgraph\flowchart\FlowchartCtrlTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(217, 499)
+ self.gridLayout = QtWidgets.QGridLayout(Form)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setVerticalSpacing(0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.loadBtn = QtWidgets.QPushButton(Form)
+ self.loadBtn.setObjectName("loadBtn")
+ self.gridLayout.addWidget(self.loadBtn, 1, 0, 1, 1)
+ self.saveBtn = FeedbackButton(Form)
+ self.saveBtn.setObjectName("saveBtn")
+ self.gridLayout.addWidget(self.saveBtn, 1, 1, 1, 2)
+ self.saveAsBtn = FeedbackButton(Form)
+ self.saveAsBtn.setObjectName("saveAsBtn")
+ self.gridLayout.addWidget(self.saveAsBtn, 1, 3, 1, 1)
+ self.reloadBtn = FeedbackButton(Form)
+ self.reloadBtn.setCheckable(False)
+ self.reloadBtn.setFlat(False)
+ self.reloadBtn.setObjectName("reloadBtn")
+ self.gridLayout.addWidget(self.reloadBtn, 4, 0, 1, 2)
+ self.showChartBtn = QtWidgets.QPushButton(Form)
+ self.showChartBtn.setCheckable(True)
+ self.showChartBtn.setObjectName("showChartBtn")
+ self.gridLayout.addWidget(self.showChartBtn, 4, 2, 1, 2)
+ self.ctrlList = TreeWidget(Form)
+ self.ctrlList.setObjectName("ctrlList")
+ self.ctrlList.headerItem().setText(0, "1")
+ self.ctrlList.header().setVisible(False)
+ self.ctrlList.header().setStretchLastSection(False)
+ self.gridLayout.addWidget(self.ctrlList, 3, 0, 1, 4)
+ self.fileNameLabel = QtWidgets.QLabel(Form)
+ font = QtGui.QFont()
+ font.setBold(True)
+ self.fileNameLabel.setFont(font)
+ self.fileNameLabel.setText("")
+ self.fileNameLabel.setAlignment(QtCore.Qt.Alignment.AlignCenter)
+ self.fileNameLabel.setObjectName("fileNameLabel")
+ self.gridLayout.addWidget(self.fileNameLabel, 0, 1, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.loadBtn.setText(_translate("Form", "Load.."))
+ self.saveBtn.setText(_translate("Form", "Save"))
+ self.saveAsBtn.setText(_translate("Form", "As.."))
+ self.reloadBtn.setText(_translate("Form", "Reload Libs"))
+ self.showChartBtn.setText(_translate("Form", "Flowchart"))
+from ..widgets.FeedbackButton import FeedbackButton
+from ..widgets.TreeWidget import TreeWidget
diff --git a/pyqtgraph/flowchart/FlowchartTemplate_pyqt6.py b/pyqtgraph/flowchart/FlowchartTemplate_pyqt6.py
new file mode 100644
index 00000000..7296a8da
--- /dev/null
+++ b/pyqtgraph/flowchart/FlowchartTemplate_pyqt6.py
@@ -0,0 +1,53 @@
+# Form implementation generated from reading ui file 'pyqtgraph\flowchart\FlowchartTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(529, 329)
+ self.selInfoWidget = QtWidgets.QWidget(Form)
+ self.selInfoWidget.setGeometry(QtCore.QRect(260, 10, 264, 222))
+ self.selInfoWidget.setObjectName("selInfoWidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.selInfoWidget)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.selDescLabel = QtWidgets.QLabel(self.selInfoWidget)
+ self.selDescLabel.setText("")
+ self.selDescLabel.setAlignment(QtCore.Qt.Alignment.AlignLeading|QtCore.Qt.Alignment.AlignLeft|QtCore.Qt.Alignment.AlignTop)
+ self.selDescLabel.setWordWrap(True)
+ self.selDescLabel.setObjectName("selDescLabel")
+ self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1)
+ self.selNameLabel = QtWidgets.QLabel(self.selInfoWidget)
+ font = QtGui.QFont()
+ font.setBold(True)
+ self.selNameLabel.setFont(font)
+ self.selNameLabel.setText("")
+ self.selNameLabel.setObjectName("selNameLabel")
+ self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1)
+ self.selectedTree = DataTreeWidget(self.selInfoWidget)
+ self.selectedTree.setObjectName("selectedTree")
+ self.selectedTree.headerItem().setText(0, "1")
+ self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2)
+ self.hoverText = QtWidgets.QTextEdit(Form)
+ self.hoverText.setGeometry(QtCore.QRect(0, 240, 521, 81))
+ self.hoverText.setObjectName("hoverText")
+ self.view = FlowchartGraphicsView(Form)
+ self.view.setGeometry(QtCore.QRect(0, 0, 256, 192))
+ self.view.setObjectName("view")
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView
+from ..widgets.DataTreeWidget import DataTreeWidget
diff --git a/pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyqt6.py b/pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyqt6.py
new file mode 100644
index 00000000..213f4db5
--- /dev/null
+++ b/pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyqt6.py
@@ -0,0 +1,178 @@
+# Form implementation generated from reading ui file 'pyqtgraph\graphicsItems\PlotItem\plotConfigTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(481, 840)
+ self.averageGroup = QtWidgets.QGroupBox(Form)
+ self.averageGroup.setGeometry(QtCore.QRect(0, 640, 242, 182))
+ self.averageGroup.setCheckable(True)
+ self.averageGroup.setChecked(False)
+ self.averageGroup.setObjectName("averageGroup")
+ self.gridLayout_5 = QtWidgets.QGridLayout(self.averageGroup)
+ self.gridLayout_5.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout_5.setSpacing(0)
+ self.gridLayout_5.setObjectName("gridLayout_5")
+ self.avgParamList = QtWidgets.QListWidget(self.averageGroup)
+ self.avgParamList.setObjectName("avgParamList")
+ self.gridLayout_5.addWidget(self.avgParamList, 0, 0, 1, 1)
+ self.decimateGroup = QtWidgets.QFrame(Form)
+ self.decimateGroup.setGeometry(QtCore.QRect(10, 140, 191, 171))
+ self.decimateGroup.setObjectName("decimateGroup")
+ self.gridLayout_4 = QtWidgets.QGridLayout(self.decimateGroup)
+ self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout_4.setSpacing(0)
+ self.gridLayout_4.setObjectName("gridLayout_4")
+ self.clipToViewCheck = QtWidgets.QCheckBox(self.decimateGroup)
+ self.clipToViewCheck.setObjectName("clipToViewCheck")
+ self.gridLayout_4.addWidget(self.clipToViewCheck, 7, 0, 1, 3)
+ self.maxTracesCheck = QtWidgets.QCheckBox(self.decimateGroup)
+ self.maxTracesCheck.setObjectName("maxTracesCheck")
+ self.gridLayout_4.addWidget(self.maxTracesCheck, 8, 0, 1, 2)
+ self.downsampleCheck = QtWidgets.QCheckBox(self.decimateGroup)
+ self.downsampleCheck.setObjectName("downsampleCheck")
+ self.gridLayout_4.addWidget(self.downsampleCheck, 0, 0, 1, 3)
+ self.peakRadio = QtWidgets.QRadioButton(self.decimateGroup)
+ self.peakRadio.setChecked(True)
+ self.peakRadio.setObjectName("peakRadio")
+ self.gridLayout_4.addWidget(self.peakRadio, 6, 1, 1, 2)
+ self.maxTracesSpin = QtWidgets.QSpinBox(self.decimateGroup)
+ self.maxTracesSpin.setObjectName("maxTracesSpin")
+ self.gridLayout_4.addWidget(self.maxTracesSpin, 8, 2, 1, 1)
+ self.forgetTracesCheck = QtWidgets.QCheckBox(self.decimateGroup)
+ self.forgetTracesCheck.setObjectName("forgetTracesCheck")
+ self.gridLayout_4.addWidget(self.forgetTracesCheck, 9, 0, 1, 3)
+ self.meanRadio = QtWidgets.QRadioButton(self.decimateGroup)
+ self.meanRadio.setObjectName("meanRadio")
+ self.gridLayout_4.addWidget(self.meanRadio, 3, 1, 1, 2)
+ self.subsampleRadio = QtWidgets.QRadioButton(self.decimateGroup)
+ self.subsampleRadio.setObjectName("subsampleRadio")
+ self.gridLayout_4.addWidget(self.subsampleRadio, 2, 1, 1, 2)
+ self.autoDownsampleCheck = QtWidgets.QCheckBox(self.decimateGroup)
+ self.autoDownsampleCheck.setChecked(True)
+ self.autoDownsampleCheck.setObjectName("autoDownsampleCheck")
+ self.gridLayout_4.addWidget(self.autoDownsampleCheck, 1, 2, 1, 1)
+ spacerItem = QtWidgets.QSpacerItem(30, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Policy.Minimum)
+ self.gridLayout_4.addItem(spacerItem, 2, 0, 1, 1)
+ self.downsampleSpin = QtWidgets.QSpinBox(self.decimateGroup)
+ self.downsampleSpin.setMinimum(1)
+ self.downsampleSpin.setMaximum(100000)
+ self.downsampleSpin.setProperty("value", 1)
+ self.downsampleSpin.setObjectName("downsampleSpin")
+ self.gridLayout_4.addWidget(self.downsampleSpin, 1, 1, 1, 1)
+ self.transformGroup = QtWidgets.QFrame(Form)
+ self.transformGroup.setGeometry(QtCore.QRect(10, 10, 171, 101))
+ self.transformGroup.setObjectName("transformGroup")
+ self.gridLayout = QtWidgets.QGridLayout(self.transformGroup)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setSpacing(0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.logYCheck = QtWidgets.QCheckBox(self.transformGroup)
+ self.logYCheck.setObjectName("logYCheck")
+ self.gridLayout.addWidget(self.logYCheck, 2, 0, 1, 1)
+ self.logXCheck = QtWidgets.QCheckBox(self.transformGroup)
+ self.logXCheck.setObjectName("logXCheck")
+ self.gridLayout.addWidget(self.logXCheck, 1, 0, 1, 1)
+ self.fftCheck = QtWidgets.QCheckBox(self.transformGroup)
+ self.fftCheck.setObjectName("fftCheck")
+ self.gridLayout.addWidget(self.fftCheck, 0, 0, 1, 1)
+ self.derivativeCheck = QtWidgets.QCheckBox(self.transformGroup)
+ self.derivativeCheck.setObjectName("derivativeCheck")
+ self.gridLayout.addWidget(self.derivativeCheck, 3, 0, 1, 1)
+ self.phasemapCheck = QtWidgets.QCheckBox(self.transformGroup)
+ self.phasemapCheck.setObjectName("phasemapCheck")
+ self.gridLayout.addWidget(self.phasemapCheck, 4, 0, 1, 1)
+ self.pointsGroup = QtWidgets.QGroupBox(Form)
+ self.pointsGroup.setGeometry(QtCore.QRect(10, 550, 234, 58))
+ self.pointsGroup.setCheckable(True)
+ self.pointsGroup.setObjectName("pointsGroup")
+ self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.pointsGroup)
+ self.verticalLayout_5.setObjectName("verticalLayout_5")
+ self.autoPointsCheck = QtWidgets.QCheckBox(self.pointsGroup)
+ self.autoPointsCheck.setChecked(True)
+ self.autoPointsCheck.setObjectName("autoPointsCheck")
+ self.verticalLayout_5.addWidget(self.autoPointsCheck)
+ self.gridGroup = QtWidgets.QFrame(Form)
+ self.gridGroup.setGeometry(QtCore.QRect(10, 460, 221, 81))
+ self.gridGroup.setObjectName("gridGroup")
+ self.gridLayout_2 = QtWidgets.QGridLayout(self.gridGroup)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.xGridCheck = QtWidgets.QCheckBox(self.gridGroup)
+ self.xGridCheck.setObjectName("xGridCheck")
+ self.gridLayout_2.addWidget(self.xGridCheck, 0, 0, 1, 2)
+ self.yGridCheck = QtWidgets.QCheckBox(self.gridGroup)
+ self.yGridCheck.setObjectName("yGridCheck")
+ self.gridLayout_2.addWidget(self.yGridCheck, 1, 0, 1, 2)
+ self.gridAlphaSlider = QtWidgets.QSlider(self.gridGroup)
+ self.gridAlphaSlider.setMaximum(255)
+ self.gridAlphaSlider.setProperty("value", 128)
+ self.gridAlphaSlider.setOrientation(QtCore.Qt.Orientations.Horizontal)
+ self.gridAlphaSlider.setObjectName("gridAlphaSlider")
+ self.gridLayout_2.addWidget(self.gridAlphaSlider, 2, 1, 1, 1)
+ self.label = QtWidgets.QLabel(self.gridGroup)
+ self.label.setObjectName("label")
+ self.gridLayout_2.addWidget(self.label, 2, 0, 1, 1)
+ self.alphaGroup = QtWidgets.QGroupBox(Form)
+ self.alphaGroup.setGeometry(QtCore.QRect(10, 390, 234, 60))
+ self.alphaGroup.setCheckable(True)
+ self.alphaGroup.setObjectName("alphaGroup")
+ self.horizontalLayout = QtWidgets.QHBoxLayout(self.alphaGroup)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.autoAlphaCheck = QtWidgets.QCheckBox(self.alphaGroup)
+ self.autoAlphaCheck.setChecked(False)
+ self.autoAlphaCheck.setObjectName("autoAlphaCheck")
+ self.horizontalLayout.addWidget(self.autoAlphaCheck)
+ self.alphaSlider = QtWidgets.QSlider(self.alphaGroup)
+ self.alphaSlider.setMaximum(1000)
+ self.alphaSlider.setProperty("value", 1000)
+ self.alphaSlider.setOrientation(QtCore.Qt.Orientations.Horizontal)
+ self.alphaSlider.setObjectName("alphaSlider")
+ self.horizontalLayout.addWidget(self.alphaSlider)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.averageGroup.setToolTip(_translate("Form", "Display averages of the curves displayed in this plot. The parameter list allows you to choose parameters to average over (if any are available)."))
+ self.averageGroup.setTitle(_translate("Form", "Average"))
+ self.clipToViewCheck.setToolTip(_translate("Form", "Plot only the portion of each curve that is visible. This assumes X values are uniformly spaced."))
+ self.clipToViewCheck.setText(_translate("Form", "Clip to View"))
+ self.maxTracesCheck.setToolTip(_translate("Form", "If multiple curves are displayed in this plot, check this box to limit the number of traces that are displayed."))
+ self.maxTracesCheck.setText(_translate("Form", "Max Traces:"))
+ self.downsampleCheck.setText(_translate("Form", "Downsample"))
+ self.peakRadio.setToolTip(_translate("Form", "Downsample by drawing a saw wave that follows the min and max of the original data. This method produces the best visual representation of the data but is slower."))
+ self.peakRadio.setText(_translate("Form", "Peak"))
+ self.maxTracesSpin.setToolTip(_translate("Form", "If multiple curves are displayed in this plot, check \"Max Traces\" and set this value to limit the number of traces that are displayed."))
+ self.forgetTracesCheck.setToolTip(_translate("Form", "If MaxTraces is checked, remove curves from memory after they are hidden (saves memory, but traces can not be un-hidden)."))
+ self.forgetTracesCheck.setText(_translate("Form", "Forget hidden traces"))
+ self.meanRadio.setToolTip(_translate("Form", "Downsample by taking the mean of N samples."))
+ self.meanRadio.setText(_translate("Form", "Mean"))
+ self.subsampleRadio.setToolTip(_translate("Form", "Downsample by taking the first of N samples. This method is fastest and least accurate."))
+ self.subsampleRadio.setText(_translate("Form", "Subsample"))
+ self.autoDownsampleCheck.setToolTip(_translate("Form", "Automatically downsample data based on the visible range. This assumes X values are uniformly spaced."))
+ self.autoDownsampleCheck.setText(_translate("Form", "Auto"))
+ self.downsampleSpin.setToolTip(_translate("Form", "Downsample data before plotting. (plot every Nth sample)"))
+ self.downsampleSpin.setSuffix(_translate("Form", "x"))
+ self.logYCheck.setText(_translate("Form", "Log Y"))
+ self.logXCheck.setText(_translate("Form", "Log X"))
+ self.fftCheck.setText(_translate("Form", "Power Spectrum (FFT)"))
+ self.derivativeCheck.setText(_translate("Form", "dy/dx"))
+ self.phasemapCheck.setText(_translate("Form", "Y vs. Y\'"))
+ self.pointsGroup.setTitle(_translate("Form", "Points"))
+ self.autoPointsCheck.setText(_translate("Form", "Auto"))
+ self.xGridCheck.setText(_translate("Form", "Show X Grid"))
+ self.yGridCheck.setText(_translate("Form", "Show Y Grid"))
+ self.label.setText(_translate("Form", "Opacity"))
+ self.alphaGroup.setTitle(_translate("Form", "Alpha"))
+ self.autoAlphaCheck.setText(_translate("Form", "Auto"))
diff --git a/pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyqt6.py b/pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyqt6.py
new file mode 100644
index 00000000..6c883610
--- /dev/null
+++ b/pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyqt6.py
@@ -0,0 +1,88 @@
+# Form implementation generated from reading ui file 'pyqtgraph\graphicsItems\ViewBox\axisCtrlTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(186, 154)
+ Form.setMaximumSize(QtCore.QSize(200, 16777215))
+ self.gridLayout = QtWidgets.QGridLayout(Form)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setSpacing(0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.label = QtWidgets.QLabel(Form)
+ self.label.setObjectName("label")
+ self.gridLayout.addWidget(self.label, 7, 0, 1, 2)
+ self.linkCombo = QtWidgets.QComboBox(Form)
+ self.linkCombo.setSizeAdjustPolicy(QtWidgets.QComboBox.SizeAdjustPolicy.AdjustToContents)
+ self.linkCombo.setObjectName("linkCombo")
+ self.gridLayout.addWidget(self.linkCombo, 7, 2, 1, 2)
+ self.autoPercentSpin = QtWidgets.QSpinBox(Form)
+ self.autoPercentSpin.setEnabled(True)
+ self.autoPercentSpin.setMinimum(1)
+ self.autoPercentSpin.setMaximum(100)
+ self.autoPercentSpin.setSingleStep(1)
+ self.autoPercentSpin.setProperty("value", 100)
+ self.autoPercentSpin.setObjectName("autoPercentSpin")
+ self.gridLayout.addWidget(self.autoPercentSpin, 2, 2, 1, 2)
+ self.autoRadio = QtWidgets.QRadioButton(Form)
+ self.autoRadio.setChecked(True)
+ self.autoRadio.setObjectName("autoRadio")
+ self.gridLayout.addWidget(self.autoRadio, 2, 0, 1, 2)
+ self.manualRadio = QtWidgets.QRadioButton(Form)
+ self.manualRadio.setObjectName("manualRadio")
+ self.gridLayout.addWidget(self.manualRadio, 1, 0, 1, 2)
+ self.minText = QtWidgets.QLineEdit(Form)
+ self.minText.setObjectName("minText")
+ self.gridLayout.addWidget(self.minText, 1, 2, 1, 1)
+ self.maxText = QtWidgets.QLineEdit(Form)
+ self.maxText.setObjectName("maxText")
+ self.gridLayout.addWidget(self.maxText, 1, 3, 1, 1)
+ self.invertCheck = QtWidgets.QCheckBox(Form)
+ self.invertCheck.setObjectName("invertCheck")
+ self.gridLayout.addWidget(self.invertCheck, 5, 0, 1, 4)
+ self.mouseCheck = QtWidgets.QCheckBox(Form)
+ self.mouseCheck.setChecked(True)
+ self.mouseCheck.setObjectName("mouseCheck")
+ self.gridLayout.addWidget(self.mouseCheck, 6, 0, 1, 4)
+ self.visibleOnlyCheck = QtWidgets.QCheckBox(Form)
+ self.visibleOnlyCheck.setObjectName("visibleOnlyCheck")
+ self.gridLayout.addWidget(self.visibleOnlyCheck, 3, 2, 1, 2)
+ self.autoPanCheck = QtWidgets.QCheckBox(Form)
+ self.autoPanCheck.setObjectName("autoPanCheck")
+ self.gridLayout.addWidget(self.autoPanCheck, 4, 2, 1, 2)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.label.setText(_translate("Form", "Link Axis:"))
+ self.linkCombo.setToolTip(_translate("Form", "
Links this axis with another view. When linked, both views will display the same data range.
"))
+ self.autoPercentSpin.setToolTip(_translate("Form", "Percent of data to be visible when auto-scaling. It may be useful to decrease this value for data with spiky noise.
"))
+ self.autoPercentSpin.setSuffix(_translate("Form", "%"))
+ self.autoRadio.setToolTip(_translate("Form", "Automatically resize this axis whenever the displayed data is changed.
"))
+ self.autoRadio.setText(_translate("Form", "Auto"))
+ self.manualRadio.setToolTip(_translate("Form", "Set the range for this axis manually. This disables automatic scaling.
"))
+ self.manualRadio.setText(_translate("Form", "Manual"))
+ self.minText.setToolTip(_translate("Form", "Minimum value to display for this axis.
"))
+ self.minText.setText(_translate("Form", "0"))
+ self.maxText.setToolTip(_translate("Form", "Maximum value to display for this axis.
"))
+ self.maxText.setText(_translate("Form", "0"))
+ self.invertCheck.setToolTip(_translate("Form", "Inverts the display of this axis. (+y points downward instead of upward)
"))
+ self.invertCheck.setText(_translate("Form", "Invert Axis"))
+ self.mouseCheck.setToolTip(_translate("Form", "Enables mouse interaction (panning, scaling) for this axis.
"))
+ self.mouseCheck.setText(_translate("Form", "Mouse Enabled"))
+ self.visibleOnlyCheck.setToolTip(_translate("Form", "When checked, the axis will only auto-scale to data that is visible along the orthogonal axis.
"))
+ self.visibleOnlyCheck.setText(_translate("Form", "Visible Data Only"))
+ self.autoPanCheck.setToolTip(_translate("Form", "When checked, the axis will automatically pan to center on the current data, but the scale along this axis will not change.
"))
+ self.autoPanCheck.setText(_translate("Form", "Auto Pan Only"))
diff --git a/pyqtgraph/imageview/ImageViewTemplate_pyqt6.py b/pyqtgraph/imageview/ImageViewTemplate_pyqt6.py
new file mode 100644
index 00000000..c27aa232
--- /dev/null
+++ b/pyqtgraph/imageview/ImageViewTemplate_pyqt6.py
@@ -0,0 +1,151 @@
+# Form implementation generated from reading ui file 'pyqtgraph\imageview\ImageViewTemplate.ui'
+#
+# Created by: PyQt6 UI code generator 6.0.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(726, 588)
+ self.gridLayout_3 = QtWidgets.QGridLayout(Form)
+ self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout_3.setSpacing(0)
+ self.gridLayout_3.setObjectName("gridLayout_3")
+ self.splitter = QtWidgets.QSplitter(Form)
+ self.splitter.setOrientation(QtCore.Qt.Orientations.Vertical)
+ self.splitter.setObjectName("splitter")
+ self.layoutWidget = QtWidgets.QWidget(self.splitter)
+ self.layoutWidget.setObjectName("layoutWidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setSpacing(0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.graphicsView = GraphicsView(self.layoutWidget)
+ self.graphicsView.setObjectName("graphicsView")
+ self.gridLayout.addWidget(self.graphicsView, 0, 0, 2, 1)
+ self.histogram = HistogramLUTWidget(self.layoutWidget)
+ self.histogram.setObjectName("histogram")
+ self.gridLayout.addWidget(self.histogram, 0, 1, 1, 2)
+ self.roiBtn = QtWidgets.QPushButton(self.layoutWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(1)
+ sizePolicy.setHeightForWidth(self.roiBtn.sizePolicy().hasHeightForWidth())
+ self.roiBtn.setSizePolicy(sizePolicy)
+ self.roiBtn.setCheckable(True)
+ self.roiBtn.setObjectName("roiBtn")
+ self.gridLayout.addWidget(self.roiBtn, 1, 1, 1, 1)
+ self.menuBtn = QtWidgets.QPushButton(self.layoutWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(1)
+ sizePolicy.setHeightForWidth(self.menuBtn.sizePolicy().hasHeightForWidth())
+ self.menuBtn.setSizePolicy(sizePolicy)
+ self.menuBtn.setObjectName("menuBtn")
+ self.gridLayout.addWidget(self.menuBtn, 1, 2, 1, 1)
+ self.roiPlot = PlotWidget(self.splitter)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.roiPlot.sizePolicy().hasHeightForWidth())
+ self.roiPlot.setSizePolicy(sizePolicy)
+ self.roiPlot.setMinimumSize(QtCore.QSize(0, 40))
+ self.roiPlot.setObjectName("roiPlot")
+ self.gridLayout_3.addWidget(self.splitter, 0, 0, 1, 1)
+ self.normGroup = QtWidgets.QGroupBox(Form)
+ self.normGroup.setObjectName("normGroup")
+ self.gridLayout_2 = QtWidgets.QGridLayout(self.normGroup)
+ self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout_2.setSpacing(0)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.normSubtractRadio = QtWidgets.QRadioButton(self.normGroup)
+ self.normSubtractRadio.setObjectName("normSubtractRadio")
+ self.gridLayout_2.addWidget(self.normSubtractRadio, 0, 2, 1, 1)
+ self.normDivideRadio = QtWidgets.QRadioButton(self.normGroup)
+ self.normDivideRadio.setChecked(False)
+ self.normDivideRadio.setObjectName("normDivideRadio")
+ self.gridLayout_2.addWidget(self.normDivideRadio, 0, 1, 1, 1)
+ self.label_5 = QtWidgets.QLabel(self.normGroup)
+ font = QtGui.QFont()
+ font.setBold(True)
+ self.label_5.setFont(font)
+ self.label_5.setObjectName("label_5")
+ self.gridLayout_2.addWidget(self.label_5, 0, 0, 1, 1)
+ self.label_3 = QtWidgets.QLabel(self.normGroup)
+ font = QtGui.QFont()
+ font.setBold(True)
+ self.label_3.setFont(font)
+ self.label_3.setObjectName("label_3")
+ self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1)
+ self.label_4 = QtWidgets.QLabel(self.normGroup)
+ font = QtGui.QFont()
+ font.setBold(True)
+ self.label_4.setFont(font)
+ self.label_4.setObjectName("label_4")
+ self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1)
+ self.normROICheck = QtWidgets.QCheckBox(self.normGroup)
+ self.normROICheck.setObjectName("normROICheck")
+ self.gridLayout_2.addWidget(self.normROICheck, 1, 1, 1, 1)
+ self.normXBlurSpin = QtWidgets.QDoubleSpinBox(self.normGroup)
+ self.normXBlurSpin.setObjectName("normXBlurSpin")
+ self.gridLayout_2.addWidget(self.normXBlurSpin, 2, 2, 1, 1)
+ self.label_8 = QtWidgets.QLabel(self.normGroup)
+ self.label_8.setAlignment(QtCore.Qt.Alignment.AlignRight|QtCore.Qt.Alignment.AlignTrailing|QtCore.Qt.Alignment.AlignVCenter)
+ self.label_8.setObjectName("label_8")
+ self.gridLayout_2.addWidget(self.label_8, 2, 1, 1, 1)
+ self.label_9 = QtWidgets.QLabel(self.normGroup)
+ self.label_9.setAlignment(QtCore.Qt.Alignment.AlignRight|QtCore.Qt.Alignment.AlignTrailing|QtCore.Qt.Alignment.AlignVCenter)
+ self.label_9.setObjectName("label_9")
+ self.gridLayout_2.addWidget(self.label_9, 2, 3, 1, 1)
+ self.normYBlurSpin = QtWidgets.QDoubleSpinBox(self.normGroup)
+ self.normYBlurSpin.setObjectName("normYBlurSpin")
+ self.gridLayout_2.addWidget(self.normYBlurSpin, 2, 4, 1, 1)
+ self.label_10 = QtWidgets.QLabel(self.normGroup)
+ self.label_10.setAlignment(QtCore.Qt.Alignment.AlignRight|QtCore.Qt.Alignment.AlignTrailing|QtCore.Qt.Alignment.AlignVCenter)
+ self.label_10.setObjectName("label_10")
+ self.gridLayout_2.addWidget(self.label_10, 2, 5, 1, 1)
+ self.normOffRadio = QtWidgets.QRadioButton(self.normGroup)
+ self.normOffRadio.setChecked(True)
+ self.normOffRadio.setObjectName("normOffRadio")
+ self.gridLayout_2.addWidget(self.normOffRadio, 0, 3, 1, 1)
+ self.normTimeRangeCheck = QtWidgets.QCheckBox(self.normGroup)
+ self.normTimeRangeCheck.setObjectName("normTimeRangeCheck")
+ self.gridLayout_2.addWidget(self.normTimeRangeCheck, 1, 3, 1, 1)
+ self.normFrameCheck = QtWidgets.QCheckBox(self.normGroup)
+ self.normFrameCheck.setObjectName("normFrameCheck")
+ self.gridLayout_2.addWidget(self.normFrameCheck, 1, 2, 1, 1)
+ self.normTBlurSpin = QtWidgets.QDoubleSpinBox(self.normGroup)
+ self.normTBlurSpin.setObjectName("normTBlurSpin")
+ self.gridLayout_2.addWidget(self.normTBlurSpin, 2, 6, 1, 1)
+ self.gridLayout_3.addWidget(self.normGroup, 1, 0, 1, 1)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "PyQtGraph"))
+ self.roiBtn.setText(_translate("Form", "ROI"))
+ self.menuBtn.setText(_translate("Form", "Menu"))
+ self.normGroup.setTitle(_translate("Form", "Normalization"))
+ self.normSubtractRadio.setText(_translate("Form", "Subtract"))
+ self.normDivideRadio.setText(_translate("Form", "Divide"))
+ self.label_5.setText(_translate("Form", "Operation:"))
+ self.label_3.setText(_translate("Form", "Mean:"))
+ self.label_4.setText(_translate("Form", "Blur:"))
+ self.normROICheck.setText(_translate("Form", "ROI"))
+ self.label_8.setText(_translate("Form", "X"))
+ self.label_9.setText(_translate("Form", "Y"))
+ self.label_10.setText(_translate("Form", "T"))
+ self.normOffRadio.setText(_translate("Form", "Off"))
+ self.normTimeRangeCheck.setText(_translate("Form", "Time range"))
+ self.normFrameCheck.setText(_translate("Form", "Frame"))
+from ..widgets.GraphicsView import GraphicsView
+from ..widgets.HistogramLUTWidget import HistogramLUTWidget
+from ..widgets.PlotWidget import PlotWidget
From dcbddb0abfb71f3d4d37334e5d936d43bff45906 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Thu, 14 Jan 2021 19:03:52 +0800
Subject: [PATCH 02/17] add PyQt6 support to Qt.py and functions.py
---
pyqtgraph/Qt.py | 89 ++++++++++++++++++++++++++++++++++++++----
pyqtgraph/functions.py | 55 ++++++++++++++++----------
2 files changed, 115 insertions(+), 29 deletions(-)
diff --git a/pyqtgraph/Qt.py b/pyqtgraph/Qt.py
index 28672cbc..c1509265 100644
--- a/pyqtgraph/Qt.py
+++ b/pyqtgraph/Qt.py
@@ -11,6 +11,8 @@ This module exists to smooth out some of the differences between PySide and PyQt
"""
import os, sys, re, time, subprocess, warnings
+import importlib
+import enum
from .python2_3 import asUnicode
@@ -28,7 +30,7 @@ QT_LIB = os.getenv('PYQTGRAPH_QT_LIB')
## This is done by first checking to see whether one of the libraries
## is already imported. If not, then attempt to import PyQt4, then PySide.
if QT_LIB is None:
- libOrder = [PYQT4, PYSIDE, PYQT5, PYSIDE2, PYSIDE6]
+ libOrder = [PYQT4, PYSIDE, PYQT5, PYSIDE2, PYSIDE6, PYQT6]
for lib in libOrder:
if lib in sys.modules:
@@ -45,7 +47,7 @@ if QT_LIB is None:
pass
if QT_LIB is None:
- raise Exception("PyQtGraph requires one of PyQt4, PyQt5, PySide, PySide2 or PySide6; none of these packages could be imported.")
+ raise Exception("PyQtGraph requires one of PyQt4, PyQt5, PyQt6, PySide, PySide2 or PySide6; none of these packages could be imported.")
class FailedImport(object):
@@ -221,6 +223,25 @@ elif QT_LIB == PYQT5:
VERSION_INFO = 'PyQt5 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
+elif QT_LIB == PYQT6:
+ from PyQt6 import QtGui, QtCore, QtWidgets, uic
+
+ try:
+ from PyQt6 import QtSvg
+ except ImportError as err:
+ QtSvg = FailedImport(err)
+ try:
+ from PyQt6 import QtOpenGLWidgets
+ except ImportError as err:
+ QtOpenGLWidgets = FailedImport(err)
+ try:
+ from PyQt6 import QtTest
+ QtTest.QTest.qWaitForWindowShown = QtTest.QTest.qWaitForWindowExposed
+ except ImportError as err:
+ QtTest = FailedImport(err)
+
+ VERSION_INFO = 'PyQt6 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
+
elif QT_LIB == PYSIDE2:
from PySide2 import QtGui, QtCore, QtWidgets
@@ -277,8 +298,8 @@ else:
raise ValueError("Invalid Qt lib '%s'" % QT_LIB)
-# common to PyQt5, PySide2 and PySide6
-if QT_LIB in [PYQT5, PYSIDE2, PYSIDE6]:
+# common to PyQt5, PyQt6, PySide2 and PySide6
+if QT_LIB in [PYQT5, PYQT6, PYSIDE2, PYSIDE6]:
# We're using Qt5 which has a different structure so we're going to use a shim to
# recreate the Qt4 structure
@@ -353,13 +374,13 @@ if QT_LIB in [PYSIDE, PYSIDE2, PYSIDE6]:
QtTest.QTest.qWait = qWait
-# Common to PyQt4 and 5
-if QT_LIB in [PYQT4, PYQT5]:
+# Common to PyQt4, PyQt5 and PyQt6
+if QT_LIB in [PYQT4, PYQT5, PYQT6]:
QtVersion = QtCore.QT_VERSION_STR
try:
- from PyQt5 import sip
- except ImportError:
+ sip = importlib.import_module(QT_LIB + '.sip')
+ except ModuleNotFoundError:
import sip
def isQObjectAlive(obj):
return not sip.isdeleted(obj)
@@ -369,6 +390,58 @@ if QT_LIB in [PYQT4, PYQT5]:
QtCore.Signal = QtCore.pyqtSignal
+if QT_LIB == PYQT6:
+ # module.Class.EnumClass.Enum -> module.Class.Enum
+ def promote_enums(module):
+ class_names = [x for x in dir(module) if x[0] == 'Q']
+ for class_name in class_names:
+ klass = getattr(module, class_name)
+ if not isinstance(klass, sip.wrappertype):
+ continue
+ attrib_names = [x for x in dir(klass) if x[0].isupper()]
+ for attrib_name in attrib_names:
+ attrib = getattr(klass, attrib_name)
+ if not isinstance(attrib, enum.EnumMeta):
+ continue
+ for e in attrib:
+ setattr(klass, e.name, e)
+
+ promote_enums(QtCore)
+ promote_enums(QtGui)
+ promote_enums(QtWidgets)
+
+ # QKeyEvent::key() returns an int
+ # so comparison with a Key_* enum will always be False
+ # here we convert the enum to its int value
+ for e in QtCore.Qt.Key:
+ setattr(QtCore.Qt, e.name, e.value)
+
+ # shim the old names for QPointF mouse coords
+ QtGui.QSinglePointEvent.localPos = lambda o : o.position()
+ QtGui.QSinglePointEvent.windowPos = lambda o : o.scenePosition()
+ QtGui.QSinglePointEvent.screenPos = lambda o : o.globalPosition()
+ QtGui.QDropEvent.posF = lambda o : o.position()
+
+ QtWidgets.QApplication.exec_ = QtWidgets.QApplication.exec
+ QtWidgets.QDialog.exec_ = lambda o : o.exec()
+ QtGui.QDrag.exec_ = lambda o : o.exec()
+
+ # PyQt6 6.0.0 has a bug where it can't handle certain Type values returned
+ # by the Qt library.
+ try:
+ # 213 is a known failing value
+ QtCore.QEvent.Type(213)
+ except ValueError:
+ def new_method(self, old_method=QtCore.QEvent.type):
+ try:
+ typ = old_method(self)
+ except ValueError:
+ typ = QtCore.QEvent.Type.None_
+ return typ
+ QtCore.QEvent.type = new_method
+ del new_method
+
+
# USE_XXX variables are deprecated
USE_PYSIDE = QT_LIB == PYSIDE
USE_PYQT4 = QT_LIB == PYQT4
diff --git a/pyqtgraph/functions.py b/pyqtgraph/functions.py
index 6bcf8113..c3257f23 100644
--- a/pyqtgraph/functions.py
+++ b/pyqtgraph/functions.py
@@ -19,6 +19,7 @@ from pyqtgraph.util.cupy_helper import getCupy
from . import debug, reload
from .Qt import QtGui, QtCore, QT_LIB, QtVersion
+from . import Qt
from .metaarray import MetaArray
from .pgcollections import OrderedDict
from .python2_3 import asUnicode, basestring
@@ -1254,23 +1255,28 @@ def makeQImage(imgData, alpha=None, copy=True, transpose=True):
imgData = imgData.copy()
profile("copy")
- if QT_LIB == 'PySide':
- ch = ctypes.c_char.from_buffer(imgData, 0)
- img = QtGui.QImage(ch, imgData.shape[1], imgData.shape[0], imgFormat)
- elif QT_LIB in ['PySide2', 'PySide6']:
- img = QtGui.QImage(imgData, imgData.shape[1], imgData.shape[0], imgFormat)
+
+ # C++ QImage has two kind of constructors
+ # - QImage(const uchar*, ...)
+ # - QImage(uchar*, ...)
+ # If the const constructor is used, subsequently calling any non-const method
+ # will trigger the COW mechanism, i.e. a copy is made under the hood.
+
+ if QT_LIB == 'PyQt5':
+ # PyQt5 -> non-const constructor
+ img_ptr = imgData.ctypes.data
+ elif QT_LIB == 'PyQt6':
+ # PyQt5 -> const constructor
+ # PyQt6 -> non-const constructor
+ img_ptr = Qt.sip.voidptr(imgData)
else:
- ## PyQt API for QImage changed between 4.9.3 and 4.9.6 (I don't know exactly which version it was)
- ## So we first attempt the 4.9.6 API, then fall back to 4.9.3
- try:
- img = QtGui.QImage(imgData.ctypes.data, imgData.shape[1], imgData.shape[0], imgFormat)
- except:
- if copy:
- # does not leak memory, is not mutable
- img = QtGui.QImage(buffer(imgData), imgData.shape[1], imgData.shape[0], imgFormat)
- else:
- # mutable, but leaks memory
- img = QtGui.QImage(memoryview(imgData), imgData.shape[1], imgData.shape[0], imgFormat)
+ # bindings that support ndarray
+ # PyQt5 -> const constructor
+ # PySide2 -> non-const constructor
+ # PySide6 -> non-const constructor
+ img_ptr = imgData
+
+ img = QtGui.QImage(img_ptr, imgData.shape[1], imgData.shape[0], imgFormat)
img.data = imgData
return img
@@ -1287,12 +1293,16 @@ def imageToArray(img, copy=False, transpose=True):
if QT_LIB in ['PySide', 'PySide2', 'PySide6']:
arr = np.frombuffer(ptr, dtype=np.ubyte)
else:
- ptr.setsize(img.byteCount())
+ try:
+ # removed in Qt6
+ nbytes = img.byteCount()
+ except AttributeError:
+ # introduced in Qt 5.10
+ # however Python 3.7 + PyQt5-5.12 in the CI fails with
+ # "TypeError: QImage.sizeInBytes() is a private method"
+ nbytes = img.sizeInBytes()
+ ptr.setsize(nbytes)
arr = np.asarray(ptr)
- if img.byteCount() != arr.size * arr.itemsize:
- # Required for Python 2.6, PyQt 4.10
- # If this works on all platforms, then there is no need to use np.asarray..
- arr = np.frombuffer(ptr, np.ubyte, img.byteCount())
arr = arr.reshape(img.height(), img.width(), 4)
if fmt == img.Format_RGB32:
@@ -1546,6 +1556,9 @@ def arrayToQPath(x, y, connect='all'):
buf = QtCore.QByteArray.fromRawData(path.strn)
except TypeError:
buf = QtCore.QByteArray(bytes(path.strn))
+ except AttributeError:
+ # PyQt6 raises AttributeError
+ buf = QtCore.QByteArray(path.strn, path.strn.nbytes)
ds = QtCore.QDataStream(buf)
ds >> path
From 3ce7f58384a8dd1204365925f5437afbde14b7c3 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Sun, 17 Jan 2021 06:45:19 +0800
Subject: [PATCH 03/17] import sip from Qt.py
---
pyqtgraph/GraphicsScene/GraphicsScene.py | 14 ++++----------
pyqtgraph/graphicsItems/GraphicsObject.py | 7 ++-----
pyqtgraph/graphicsItems/UIGraphicsItem.py | 7 ++-----
pyqtgraph/widgets/RemoteGraphicsView.py | 7 ++-----
4 files changed, 10 insertions(+), 25 deletions(-)
diff --git a/pyqtgraph/GraphicsScene/GraphicsScene.py b/pyqtgraph/GraphicsScene/GraphicsScene.py
index 6569d57b..7e7b1daa 100644
--- a/pyqtgraph/GraphicsScene/GraphicsScene.py
+++ b/pyqtgraph/GraphicsScene/GraphicsScene.py
@@ -3,7 +3,7 @@ import time
import weakref
import warnings
-from ..Qt import QtCore, QtGui, isQObjectAlive
+from ..Qt import QtCore, QtGui, QT_LIB, isQObjectAlive
from ..Point import Point
from .. import functions as fn
from .. import ptime as ptime
@@ -14,15 +14,9 @@ from .. import getConfigOption
getMillis = lambda: int(round(time.time() * 1000))
-if hasattr(QtCore, 'PYQT_VERSION'):
- try:
- try:
- from PyQt5 import sip
- except ImportError:
- import sip
- HAVE_SIP = True
- except ImportError:
- HAVE_SIP = False
+if QT_LIB.startswith('PyQt'):
+ from ..Qt import sip
+ HAVE_SIP = True
else:
HAVE_SIP = False
diff --git a/pyqtgraph/graphicsItems/GraphicsObject.py b/pyqtgraph/graphicsItems/GraphicsObject.py
index fac8e819..d83949b7 100644
--- a/pyqtgraph/graphicsItems/GraphicsObject.py
+++ b/pyqtgraph/graphicsItems/GraphicsObject.py
@@ -1,9 +1,6 @@
from ..Qt import QtGui, QtCore, QT_LIB
-if QT_LIB in ['PyQt4', 'PyQt5']:
- try:
- from PyQt5 import sip
- except ImportError:
- import sip
+if QT_LIB.startswith('PyQt'):
+ from ..Qt import sip
from .GraphicsItem import GraphicsItem
__all__ = ['GraphicsObject']
diff --git a/pyqtgraph/graphicsItems/UIGraphicsItem.py b/pyqtgraph/graphicsItems/UIGraphicsItem.py
index 07d32944..2f9a3bfe 100644
--- a/pyqtgraph/graphicsItems/UIGraphicsItem.py
+++ b/pyqtgraph/graphicsItems/UIGraphicsItem.py
@@ -1,11 +1,8 @@
from ..Qt import QtGui, QtCore, QT_LIB
import weakref
from .GraphicsObject import GraphicsObject
-if QT_LIB in ['PyQt4', 'PyQt5']:
- try:
- from PyQt5 import sip
- except ImportError:
- import sip
+if QT_LIB.startswith('PyQt'):
+ from ..Qt import sip
__all__ = ['UIGraphicsItem']
class UIGraphicsItem(GraphicsObject):
diff --git a/pyqtgraph/widgets/RemoteGraphicsView.py b/pyqtgraph/widgets/RemoteGraphicsView.py
index 877425d1..22065c50 100644
--- a/pyqtgraph/widgets/RemoteGraphicsView.py
+++ b/pyqtgraph/widgets/RemoteGraphicsView.py
@@ -1,9 +1,6 @@
from ..Qt import QtGui, QtCore, QT_LIB
-if QT_LIB in ['PyQt4', 'PyQt5']:
- try:
- from PyQt5 import sip
- except ImportError:
- import sip
+if QT_LIB.startswith('PyQt'):
+ from ..Qt import sip
from .. import multiprocess as mp
from .GraphicsView import GraphicsView
from .. import CONFIG_OPTIONS
From 0fa4557ad6237f9d86b671921f23a2a92449d719 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Sun, 17 Jan 2021 12:23:49 +0800
Subject: [PATCH 04/17] don't cast buttons, enums and flags to int
---
pyqtgraph/GraphicsScene/GraphicsScene.py | 24 ++++++++++-----------
pyqtgraph/GraphicsScene/mouseEvents.py | 18 ++++++++--------
pyqtgraph/exporters/Exporter.py | 3 ++-
pyqtgraph/exporters/SVGExporter.py | 6 +++---
pyqtgraph/graphicsItems/LinearRegionItem.py | 2 +-
pyqtgraph/graphicsItems/ROI.py | 8 +++----
pyqtgraph/graphicsItems/ViewBox/ViewBox.py | 2 +-
7 files changed, 32 insertions(+), 31 deletions(-)
diff --git a/pyqtgraph/GraphicsScene/GraphicsScene.py b/pyqtgraph/GraphicsScene/GraphicsScene.py
index 7e7b1daa..77c99431 100644
--- a/pyqtgraph/GraphicsScene/GraphicsScene.py
+++ b/pyqtgraph/GraphicsScene/GraphicsScene.py
@@ -165,7 +165,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
## set focus on the topmost focusable item under this click
items = self.items(ev.scenePos())
for i in items:
- if i.isEnabled() and i.isVisible() and int(i.flags() & i.ItemIsFocusable) > 0:
+ if i.isEnabled() and i.isVisible() and (i.flags() & i.ItemIsFocusable):
i.setFocus(QtCore.Qt.MouseFocusReason)
break
@@ -194,7 +194,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
QtGui.QGraphicsScene.mouseMoveEvent(self, ev)
# Next Deliver our own Hover Events
self.sendHoverEvents(ev)
- if int(ev.buttons()) != 0:
+ if ev.buttons():
# button is pressed' send mouseMoveEvents and mouseDragEvents
QtGui.QGraphicsScene.mouseMoveEvent(self, ev)
if self.mouseGrabberItem() is None:
@@ -202,17 +202,17 @@ class GraphicsScene(QtGui.QGraphicsScene):
init = False
## keep track of which buttons are involved in dragging
for btn in [QtCore.Qt.LeftButton, QtCore.Qt.MiddleButton, QtCore.Qt.RightButton]:
- if int(ev.buttons() & btn) == 0:
+ if not (ev.buttons() & btn):
continue
- if int(btn) not in self.dragButtons: ## see if we've dragged far enough yet
- cev = [e for e in self.clickEvents if int(e.button()) == int(btn)]
+ if btn not in self.dragButtons: ## see if we've dragged far enough yet
+ cev = [e for e in self.clickEvents if e.button() == btn]
if cev:
cev = cev[0]
dist = Point(ev.scenePos() - cev.scenePos()).length()
if dist == 0 or (dist < self._moveDistance and now - cev.time() < self.minDragTime):
continue
init = init or (len(self.dragButtons) == 0) ## If this is the first button to be dragged, then init=True
- self.dragButtons.append(int(btn))
+ self.dragButtons.append(btn)
## if we have dragged buttons, deliver a drag event
if len(self.dragButtons) > 0:
if self.sendDragEvent(ev, init=init):
@@ -235,14 +235,14 @@ class GraphicsScene(QtGui.QGraphicsScene):
ev.accept()
self.dragButtons.remove(ev.button())
else:
- cev = [e for e in self.clickEvents if int(e.button()) == int(ev.button())]
+ cev = [e for e in self.clickEvents if e.button() == ev.button()]
if cev:
if self.sendClickEvent(cev[0]):
#print "sent click event"
ev.accept()
self.clickEvents.remove(cev[0])
- if int(ev.buttons()) == 0:
+ if not ev.buttons():
self.dragItem = None
self.dragButtons = []
self.clickEvents = []
@@ -264,7 +264,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
items = []
event = HoverEvent(None, acceptable)
else:
- acceptable = int(ev.buttons()) == 0 ## if we are in mid-drag, do not allow items to accept the hover event.
+ acceptable = not ev.buttons() ## if we are in mid-drag, do not allow items to accept the hover event.
event = HoverEvent(ev, acceptable)
items = self.itemsNearEvent(event, hoverable=True)
self.sigMouseHover.emit(items)
@@ -306,7 +306,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
# item to continue receiving events until the drag is over
# - event is not a mouse event (QEvent.Leave sometimes appears here)
if (ev.type() == ev.GraphicsSceneMousePress or
- (ev.type() == ev.GraphicsSceneMouseMove and int(ev.buttons()) == 0)):
+ (ev.type() == ev.GraphicsSceneMouseMove and not ev.buttons())):
self.lastHoverEvent = event ## save this so we can ask about accepted events later.
def sendDragEvent(self, ev, init=False, final=False):
@@ -344,7 +344,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
if event.isAccepted():
#print " --> accepted"
self.dragItem = item
- if int(item.flags() & item.ItemIsFocusable) > 0:
+ if item.flags() & item.ItemIsFocusable:
item.setFocus(QtCore.Qt.MouseFocusReason)
break
elif self.dragItem is not None:
@@ -389,7 +389,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
debug.printExc("Error sending click event:")
if ev.isAccepted():
- if int(item.flags() & item.ItemIsFocusable) > 0:
+ if item.flags() & item.ItemIsFocusable:
item.setFocus(QtCore.Qt.MouseFocusReason)
break
self.sigMouseClicked.emit(ev)
diff --git a/pyqtgraph/GraphicsScene/mouseEvents.py b/pyqtgraph/GraphicsScene/mouseEvents.py
index 36b53919..b8c210af 100644
--- a/pyqtgraph/GraphicsScene/mouseEvents.py
+++ b/pyqtgraph/GraphicsScene/mouseEvents.py
@@ -19,8 +19,8 @@ class MouseDragEvent(object):
self._buttonDownScenePos = {}
self._buttonDownScreenPos = {}
for btn in [QtCore.Qt.LeftButton, QtCore.Qt.MiddleButton, QtCore.Qt.RightButton]:
- self._buttonDownScenePos[int(btn)] = moveEvent.buttonDownScenePos(btn)
- self._buttonDownScreenPos[int(btn)] = moveEvent.buttonDownScreenPos(btn)
+ self._buttonDownScenePos[btn] = moveEvent.buttonDownScenePos(btn)
+ self._buttonDownScreenPos[btn] = moveEvent.buttonDownScreenPos(btn)
self._scenePos = moveEvent.scenePos()
self._screenPos = moveEvent.screenPos()
if lastEvent is None:
@@ -61,7 +61,7 @@ class MouseDragEvent(object):
"""
if btn is None:
btn = self.button()
- return Point(self._buttonDownScenePos[int(btn)])
+ return Point(self._buttonDownScenePos[btn])
def buttonDownScreenPos(self, btn=None):
"""
@@ -70,7 +70,7 @@ class MouseDragEvent(object):
"""
if btn is None:
btn = self.button()
- return Point(self._buttonDownScreenPos[int(btn)])
+ return Point(self._buttonDownScreenPos[btn])
def lastScenePos(self):
"""
@@ -119,7 +119,7 @@ class MouseDragEvent(object):
"""
if btn is None:
btn = self.button()
- return Point(self.currentItem.mapFromScene(self._buttonDownScenePos[int(btn)]))
+ return Point(self.currentItem.mapFromScene(self._buttonDownScenePos[btn]))
def isStart(self):
"""Returns True if this event is the first since a drag was initiated."""
@@ -137,7 +137,7 @@ class MouseDragEvent(object):
else:
lp = self.lastPos()
p = self.pos()
- return "(%g,%g) buttons=%d start=%s finish=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isStart()), str(self.isFinish()))
+ return "(%g,%g) buttons=%s start=%s finish=%s>" % (lp.x(), lp.y(), p.x(), p.y(), str(self.buttons()), str(self.isStart()), str(self.isFinish()))
def modifiers(self):
"""Return any keyboard modifiers currently pressed.
@@ -230,9 +230,9 @@ class MouseClickEvent(object):
p = self._scenePos
else:
p = self.pos()
- return "" % (p.x(), p.y(), int(self.button()))
+ return "" % (p.x(), p.y(), str(self.button()))
except:
- return "" % (int(self.button()))
+ return "" % (str(self.button()))
def time(self):
return self._time
@@ -362,7 +362,7 @@ class HoverEvent(object):
else:
lp = self.lastPos()
p = self.pos()
- return "(%g,%g) buttons=%d enter=%s exit=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isEnter()), str(self.isExit()))
+ return "(%g,%g) buttons=%s enter=%s exit=%s>" % (lp.x(), lp.y(), p.x(), p.y(), str(self.buttons()), str(self.isEnter()), str(self.isExit()))
def modifiers(self):
"""Return any keyboard modifiers currently pressed.
diff --git a/pyqtgraph/exporters/Exporter.py b/pyqtgraph/exporters/Exporter.py
index 792e36bd..c89ef050 100644
--- a/pyqtgraph/exporters/Exporter.py
+++ b/pyqtgraph/exporters/Exporter.py
@@ -128,7 +128,8 @@ class Exporter(object):
while len(childs) > 0:
ch = childs.pop(0)
tree = self.getPaintItems(ch)
- if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or (ch.zValue() < 0 and int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0):
+ if (ch.flags() & ch.ItemStacksBehindParent) or \
+ (ch.zValue() < 0 and (ch.flags() & ch.ItemNegativeZStacksBehindParent)):
preItems.extend(tree)
else:
postItems.extend(tree)
diff --git a/pyqtgraph/exporters/SVGExporter.py b/pyqtgraph/exporters/SVGExporter.py
index a8f07582..094988dc 100644
--- a/pyqtgraph/exporters/SVGExporter.py
+++ b/pyqtgraph/exporters/SVGExporter.py
@@ -251,7 +251,7 @@ def _generateItemSvg(item, nodes=None, root=None, options={}):
childGroup = g1 ## add children directly to this node unless we are clipping
if not isinstance(item, QtGui.QGraphicsScene):
## See if this item clips its children
- if int(item.flags() & item.ItemClipsChildrenToShape) > 0:
+ if item.flags() & item.ItemClipsChildrenToShape:
## Generate svg for just the path
path = QtGui.QGraphicsPathItem(item.mapToScene(item.shape()))
item.scene().addItem(path)
@@ -414,7 +414,7 @@ def itemTransform(item, root):
return tr
- if int(item.flags() & item.ItemIgnoresTransformations) > 0:
+ if item.flags() & item.ItemIgnoresTransformations:
pos = item.pos()
parent = item.parentItem()
if parent is not None:
@@ -431,7 +431,7 @@ def itemTransform(item, root):
if nextRoot is None:
nextRoot = root
break
- if nextRoot is root or int(nextRoot.flags() & nextRoot.ItemIgnoresTransformations) > 0:
+ if nextRoot is root or (nextRoot.flags() & nextRoot.ItemIgnoresTransformations):
break
if isinstance(nextRoot, QtGui.QGraphicsScene):
diff --git a/pyqtgraph/graphicsItems/LinearRegionItem.py b/pyqtgraph/graphicsItems/LinearRegionItem.py
index e0fe53c0..93527d14 100644
--- a/pyqtgraph/graphicsItems/LinearRegionItem.py
+++ b/pyqtgraph/graphicsItems/LinearRegionItem.py
@@ -245,7 +245,7 @@ class LinearRegionItem(GraphicsObject):
self.sigRegionChangeFinished.emit(self)
def mouseDragEvent(self, ev):
- if not self.movable or int(ev.button() & QtCore.Qt.LeftButton) == 0:
+ if not self.movable or ev.button() != QtCore.Qt.LeftButton:
return
ev.accept()
diff --git a/pyqtgraph/graphicsItems/ROI.py b/pyqtgraph/graphicsItems/ROI.py
index 1025c5e3..52a61ff5 100644
--- a/pyqtgraph/graphicsItems/ROI.py
+++ b/pyqtgraph/graphicsItems/ROI.py
@@ -722,7 +722,7 @@ class ROI(GraphicsObject):
hover=True
for btn in [QtCore.Qt.LeftButton, QtCore.Qt.RightButton, QtCore.Qt.MiddleButton]:
- if int(self.acceptedMouseButtons() & btn) > 0 and ev.acceptClicks(btn):
+ if (self.acceptedMouseButtons() & btn) and ev.acceptClicks(btn):
hover=True
if self.contextMenuEnabled():
ev.acceptClicks(QtCore.Qt.RightButton)
@@ -794,7 +794,7 @@ class ROI(GraphicsObject):
if ev.button() == QtCore.Qt.RightButton and self.contextMenuEnabled():
self.raiseContextMenu(ev)
ev.accept()
- elif int(ev.button() & self.acceptedMouseButtons()) > 0:
+ elif ev.button() & self.acceptedMouseButtons():
ev.accept()
self.sigClicked.emit(self, ev)
else:
@@ -1343,7 +1343,7 @@ class Handle(UIGraphicsItem):
if ev.acceptDrags(QtCore.Qt.LeftButton):
hover=True
for btn in [QtCore.Qt.LeftButton, QtCore.Qt.RightButton, QtCore.Qt.MiddleButton]:
- if int(self.acceptedMouseButtons() & btn) > 0 and ev.acceptClicks(btn):
+ if (self.acceptedMouseButtons() & btn) and ev.acceptClicks(btn):
hover=True
if hover:
@@ -1358,7 +1358,7 @@ class Handle(UIGraphicsItem):
self.isMoving = False ## prevents any further motion
self.movePoint(self.startPos, finish=True)
ev.accept()
- elif int(ev.button() & self.acceptedMouseButtons()) > 0:
+ elif ev.button() & self.acceptedMouseButtons():
ev.accept()
if ev.button() == QtCore.Qt.RightButton and self.deletable:
self.raiseContextMenu(ev)
diff --git a/pyqtgraph/graphicsItems/ViewBox/ViewBox.py b/pyqtgraph/graphicsItems/ViewBox/ViewBox.py
index 0e17e008..2fd6ea61 100644
--- a/pyqtgraph/graphicsItems/ViewBox/ViewBox.py
+++ b/pyqtgraph/graphicsItems/ViewBox/ViewBox.py
@@ -1397,7 +1397,7 @@ class ViewBox(GraphicsWidget):
itemBounds.append((bounds, useX, useY, pxPad))
else:
- if int(item.flags() & item.ItemHasNoContents) > 0:
+ if item.flags() & item.ItemHasNoContents:
continue
bounds = self.mapFromItemToView(item, item.boundingRect()).boundingRect()
itemBounds.append((bounds, True, True, 0))
From 607db15949c5d7cc689417acf2c3f1e6bf8d9258 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Sun, 17 Jan 2021 12:26:32 +0800
Subject: [PATCH 05/17] call super() on virtual QWidget methods
---
pyqtgraph/GraphicsScene/GraphicsScene.py | 12 ++++++------
pyqtgraph/GraphicsScene/exportDialog.py | 2 +-
pyqtgraph/canvas/Canvas.py | 2 +-
pyqtgraph/console/CmdInput.py | 2 +-
pyqtgraph/dockarea/DockArea.py | 2 +-
pyqtgraph/graphicsItems/ArrowItem.py | 2 +-
pyqtgraph/graphicsItems/GraphicsObject.py | 2 +-
pyqtgraph/imageview/ImageView.py | 4 ++--
pyqtgraph/parametertree/ParameterTree.py | 4 ++--
pyqtgraph/widgets/ColorButton.py | 2 +-
pyqtgraph/widgets/GraphicsView.py | 13 ++++++-------
pyqtgraph/widgets/JoystickButton.py | 4 ++--
pyqtgraph/widgets/PathButton.py | 2 +-
pyqtgraph/widgets/ProgressDialog.py | 2 +-
pyqtgraph/widgets/SpinBox.py | 4 ++--
pyqtgraph/widgets/TableWidget.py | 2 +-
pyqtgraph/widgets/TreeWidget.py | 2 +-
pyqtgraph/widgets/ValueLabel.py | 2 +-
18 files changed, 32 insertions(+), 33 deletions(-)
diff --git a/pyqtgraph/GraphicsScene/GraphicsScene.py b/pyqtgraph/GraphicsScene/GraphicsScene.py
index 77c99431..71631613 100644
--- a/pyqtgraph/GraphicsScene/GraphicsScene.py
+++ b/pyqtgraph/GraphicsScene/GraphicsScene.py
@@ -152,7 +152,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
self._moveDistance = d
def mousePressEvent(self, ev):
- QtGui.QGraphicsScene.mousePressEvent(self, ev)
+ super().mousePressEvent(ev)
if self.mouseGrabberItem() is None: ## nobody claimed press; we are free to generate drag/click events
if self.lastHoverEvent is not None:
# If the mouse has moved since the last hover event, send a new one.
@@ -191,12 +191,12 @@ class GraphicsScene(QtGui.QGraphicsScene):
self.sigMouseMoved.emit(ev.scenePos())
# First allow QGraphicsScene to eliver hoverEvent/Move/Exit Events
- QtGui.QGraphicsScene.mouseMoveEvent(self, ev)
+ super().mouseMoveEvent(ev)
# Next Deliver our own Hover Events
self.sendHoverEvents(ev)
if ev.buttons():
# button is pressed' send mouseMoveEvents and mouseDragEvents
- QtGui.QGraphicsScene.mouseMoveEvent(self, ev)
+ super().mouseMoveEvent(ev)
if self.mouseGrabberItem() is None:
now = ptime.time()
init = False
@@ -219,7 +219,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
ev.accept()
else:
- QtGui.QGraphicsScene.mouseMoveEvent(self, ev)
+ super().mouseMoveEvent(ev)
# if you do not accept event (which is ignored) then cursor will disappear
ev.accept()
@@ -247,12 +247,12 @@ class GraphicsScene(QtGui.QGraphicsScene):
self.dragButtons = []
self.clickEvents = []
self.lastDrag = None
- QtGui.QGraphicsScene.mouseReleaseEvent(self, ev)
+ super().mouseReleaseEvent(ev)
self.sendHoverEvents(ev) ## let items prepare for next click/drag
def mouseDoubleClickEvent(self, ev):
- QtGui.QGraphicsScene.mouseDoubleClickEvent(self, ev)
+ super().mouseDoubleClickEvent(ev)
if self.mouseGrabberItem() is None: ## nobody claimed press; we are free to generate drag/click events
self.clickEvents.append(MouseClickEvent(ev, double=True))
diff --git a/pyqtgraph/GraphicsScene/exportDialog.py b/pyqtgraph/GraphicsScene/exportDialog.py
index 56bd90c0..60cb6cd1 100644
--- a/pyqtgraph/GraphicsScene/exportDialog.py
+++ b/pyqtgraph/GraphicsScene/exportDialog.py
@@ -140,4 +140,4 @@ class ExportDialog(QtGui.QWidget):
def closeEvent(self, event):
self.close()
- QtGui.QWidget.closeEvent(self, event)
+ super().closeEvent(event)
diff --git a/pyqtgraph/canvas/Canvas.py b/pyqtgraph/canvas/Canvas.py
index da6a8b3b..69e67608 100644
--- a/pyqtgraph/canvas/Canvas.py
+++ b/pyqtgraph/canvas/Canvas.py
@@ -107,7 +107,7 @@ class Canvas(QtGui.QWidget):
def resizeEvent(self, ev=None):
if ev is not None:
- QtGui.QWidget.resizeEvent(self, ev)
+ super().resizeEvent(ev)
self.hideBtn.move(self.ui.view.size().width() - self.hideBtn.width(), 0)
if not self.sizeApplied:
diff --git a/pyqtgraph/console/CmdInput.py b/pyqtgraph/console/CmdInput.py
index 21d25382..1148e289 100644
--- a/pyqtgraph/console/CmdInput.py
+++ b/pyqtgraph/console/CmdInput.py
@@ -24,7 +24,7 @@ class CmdInput(QtGui.QLineEdit):
elif ev.key() == QtCore.Qt.Key_Return:
self.execCmd()
else:
- QtGui.QLineEdit.keyPressEvent(self, ev)
+ super().keyPressEvent(ev)
self.history[0] = asUnicode(self.text())
def execCmd(self):
diff --git a/pyqtgraph/dockarea/DockArea.py b/pyqtgraph/dockarea/DockArea.py
index 93841e0a..ee9a5f53 100644
--- a/pyqtgraph/dockarea/DockArea.py
+++ b/pyqtgraph/dockarea/DockArea.py
@@ -382,4 +382,4 @@ class TempAreaWindow(QtGui.QWidget):
dock.orig_area.addDock(dock, )
# clear dock area, and close remaining docks
self.dockarea.clear()
- QtGui.QWidget.closeEvent(self, *args)
+ super().closeEvent(*args)
diff --git a/pyqtgraph/graphicsItems/ArrowItem.py b/pyqtgraph/graphicsItems/ArrowItem.py
index a7cc831c..77b6c44c 100644
--- a/pyqtgraph/graphicsItems/ArrowItem.py
+++ b/pyqtgraph/graphicsItems/ArrowItem.py
@@ -104,7 +104,7 @@ class ArrowItem(QtGui.QGraphicsPathItem):
def paint(self, p, *args):
p.setRenderHint(QtGui.QPainter.Antialiasing)
- QtGui.QGraphicsPathItem.paint(self, p, *args)
+ super().paint(p, *args)
#p.setPen(fn.mkPen('r'))
#p.setBrush(fn.mkBrush(None))
diff --git a/pyqtgraph/graphicsItems/GraphicsObject.py b/pyqtgraph/graphicsItems/GraphicsObject.py
index d83949b7..2e63b531 100644
--- a/pyqtgraph/graphicsItems/GraphicsObject.py
+++ b/pyqtgraph/graphicsItems/GraphicsObject.py
@@ -18,7 +18,7 @@ class GraphicsObject(GraphicsItem, QtGui.QGraphicsObject):
GraphicsItem.__init__(self)
def itemChange(self, change, value):
- ret = QtGui.QGraphicsObject.itemChange(self, change, value)
+ ret = super().itemChange(change, value)
if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]:
self.parentChanged()
try:
diff --git a/pyqtgraph/imageview/ImageView.py b/pyqtgraph/imageview/ImageView.py
index 7b52880e..ca29d1f9 100644
--- a/pyqtgraph/imageview/ImageView.py
+++ b/pyqtgraph/imageview/ImageView.py
@@ -450,7 +450,7 @@ class ImageView(QtGui.QWidget):
self.keysPressed[ev.key()] = 1
self.evalKeyState()
else:
- QtGui.QWidget.keyPressEvent(self, ev)
+ super().keyPressEvent(ev)
def keyReleaseEvent(self, ev):
if ev.key() in [QtCore.Qt.Key_Space, QtCore.Qt.Key_Home, QtCore.Qt.Key_End]:
@@ -465,7 +465,7 @@ class ImageView(QtGui.QWidget):
self.keysPressed = {}
self.evalKeyState()
else:
- QtGui.QWidget.keyReleaseEvent(self, ev)
+ super().keyReleaseEvent(ev)
def evalKeyState(self):
if len(self.keysPressed) == 1:
diff --git a/pyqtgraph/parametertree/ParameterTree.py b/pyqtgraph/parametertree/ParameterTree.py
index de6ab126..8c89d37e 100644
--- a/pyqtgraph/parametertree/ParameterTree.py
+++ b/pyqtgraph/parametertree/ParameterTree.py
@@ -157,8 +157,8 @@ class ParameterTree(TreeWidget):
self.lastSel = sel[0]
if hasattr(sel[0], 'selected'):
sel[0].selected(True)
- return TreeWidget.selectionChanged(self, *args)
+ return super().selectionChanged(*args)
def wheelEvent(self, ev):
self.clearSelection()
- return TreeWidget.wheelEvent(self, ev)
+ return super().wheelEvent(ev)
diff --git a/pyqtgraph/widgets/ColorButton.py b/pyqtgraph/widgets/ColorButton.py
index 43dd16f6..11a5ac14 100644
--- a/pyqtgraph/widgets/ColorButton.py
+++ b/pyqtgraph/widgets/ColorButton.py
@@ -35,7 +35,7 @@ class ColorButton(QtGui.QPushButton):
self.setMinimumWidth(15)
def paintEvent(self, ev):
- QtGui.QPushButton.paintEvent(self, ev)
+ super().paintEvent(ev)
p = QtGui.QPainter(self)
rect = self.rect().adjusted(6, 6, -6, -6)
## draw white base, then texture for indicating transparency, then actual color
diff --git a/pyqtgraph/widgets/GraphicsView.py b/pyqtgraph/widgets/GraphicsView.py
index accaf2a9..78b06ae6 100644
--- a/pyqtgraph/widgets/GraphicsView.py
+++ b/pyqtgraph/widgets/GraphicsView.py
@@ -157,11 +157,11 @@ class GraphicsView(QtGui.QGraphicsView):
def paintEvent(self, ev):
self.scene().prepareForPaint()
- return QtGui.QGraphicsView.paintEvent(self, ev)
+ return super().paintEvent(ev)
def render(self, *args, **kwds):
self.scene().prepareForPaint()
- return QtGui.QGraphicsView.render(self, *args, **kwds)
+ return super().render(*args, **kwds)
def close(self):
@@ -328,10 +328,9 @@ class GraphicsView(QtGui.QGraphicsView):
GraphicsView.setRange(self, r1, padding=[0, padding], propagate=False)
def wheelEvent(self, ev):
- QtGui.QGraphicsView.wheelEvent(self, ev)
+ super().wheelEvent(ev)
if not self.mouseEnabled:
return
-
delta = 0
if QT_LIB in ['PyQt4', 'PySide']:
delta = ev.delta()
@@ -352,7 +351,7 @@ class GraphicsView(QtGui.QGraphicsView):
self.scene().leaveEvent(ev) ## inform scene when mouse leaves
def mousePressEvent(self, ev):
- QtGui.QGraphicsView.mousePressEvent(self, ev)
+ super().mousePressEvent(ev)
if not self.mouseEnabled:
@@ -365,7 +364,7 @@ class GraphicsView(QtGui.QGraphicsView):
return ## Everything below disabled for now..
def mouseReleaseEvent(self, ev):
- QtGui.QGraphicsView.mouseReleaseEvent(self, ev)
+ super().mouseReleaseEvent(ev)
if not self.mouseEnabled:
return
self.sigMouseReleased.emit(ev)
@@ -378,7 +377,7 @@ class GraphicsView(QtGui.QGraphicsView):
delta = Point(ev.pos() - self.lastMousePos.toQPoint())
self.lastMousePos = Point(ev.pos())
- QtGui.QGraphicsView.mouseMoveEvent(self, ev)
+ super().mouseMoveEvent(ev)
if not self.mouseEnabled:
return
self.sigSceneMouseMoved.emit(self.mapToScene(ev.pos()))
diff --git a/pyqtgraph/widgets/JoystickButton.py b/pyqtgraph/widgets/JoystickButton.py
index 6f73c8dc..709797b5 100644
--- a/pyqtgraph/widgets/JoystickButton.py
+++ b/pyqtgraph/widgets/JoystickButton.py
@@ -64,14 +64,14 @@ class JoystickButton(QtGui.QPushButton):
self.sigStateChanged.emit(self, self.state)
def paintEvent(self, ev):
- QtGui.QPushButton.paintEvent(self, ev)
+ super().paintEvent(ev)
p = QtGui.QPainter(self)
p.setBrush(QtGui.QBrush(QtGui.QColor(0,0,0)))
p.drawEllipse(self.spotPos.x()-3,self.spotPos.y()-3,6,6)
def resizeEvent(self, ev):
self.setState(*self.state)
- QtGui.QPushButton.resizeEvent(self, ev)
+ super().resizeEvent(ev)
diff --git a/pyqtgraph/widgets/PathButton.py b/pyqtgraph/widgets/PathButton.py
index ee2e0bca..06fe131f 100644
--- a/pyqtgraph/widgets/PathButton.py
+++ b/pyqtgraph/widgets/PathButton.py
@@ -32,7 +32,7 @@ class PathButton(QtGui.QPushButton):
self.update()
def paintEvent(self, ev):
- QtGui.QPushButton.paintEvent(self, ev)
+ super().paintEvent(ev)
margin = self.margin
geom = QtCore.QRectF(0, 0, self.width(), self.height()).adjusted(margin, margin, -margin, -margin)
rect = self.path.boundingRect()
diff --git a/pyqtgraph/widgets/ProgressDialog.py b/pyqtgraph/widgets/ProgressDialog.py
index 7d2ef8a4..989a8d61 100644
--- a/pyqtgraph/widgets/ProgressDialog.py
+++ b/pyqtgraph/widgets/ProgressDialog.py
@@ -195,7 +195,7 @@ class ProgressDialog(QtGui.QProgressDialog):
if self._nestingReady:
# don't let progress dialog manage widgets anymore.
return
- return QtGui.QProgressDialog.resizeEvent(self, ev)
+ return super().resizeEvent(ev)
## wrap all other functions to make sure they aren't being called from non-gui threads
diff --git a/pyqtgraph/widgets/SpinBox.py b/pyqtgraph/widgets/SpinBox.py
index bc83bb28..10c40c8e 100644
--- a/pyqtgraph/widgets/SpinBox.py
+++ b/pyqtgraph/widgets/SpinBox.py
@@ -114,7 +114,7 @@ class SpinBox(QtGui.QAbstractSpinBox):
self.editingFinished.connect(self.editingFinishedEvent)
def event(self, ev):
- ret = QtGui.QAbstractSpinBox.event(self, ev)
+ ret = super().event(ev)
if ev.type() == QtCore.QEvent.KeyPress and ev.key() == QtCore.Qt.Key_Return:
ret = True ## For some reason, spinbox pretends to ignore return key press
return ret
@@ -596,7 +596,7 @@ class SpinBox(QtGui.QAbstractSpinBox):
def paintEvent(self, ev):
self._updateHeight()
- QtGui.QAbstractSpinBox.paintEvent(self, ev)
+ super().paintEvent(ev)
class ErrorBox(QtGui.QWidget):
diff --git a/pyqtgraph/widgets/TableWidget.py b/pyqtgraph/widgets/TableWidget.py
index c0e6ea90..3fc526ab 100644
--- a/pyqtgraph/widgets/TableWidget.py
+++ b/pyqtgraph/widgets/TableWidget.py
@@ -366,7 +366,7 @@ class TableWidget(QtGui.QTableWidget):
ev.accept()
self.copySel()
else:
- QtGui.QTableWidget.keyPressEvent(self, ev)
+ super().keyPressEvent(ev)
def handleItemChanged(self, item):
item.itemChanged()
diff --git a/pyqtgraph/widgets/TreeWidget.py b/pyqtgraph/widgets/TreeWidget.py
index 8c55ae2f..2f8ce544 100644
--- a/pyqtgraph/widgets/TreeWidget.py
+++ b/pyqtgraph/widgets/TreeWidget.py
@@ -144,7 +144,7 @@ class TreeWidget(QtGui.QTreeWidget):
return items
def dropEvent(self, ev):
- QtGui.QTreeWidget.dropEvent(self, ev)
+ super().dropEvent(ev)
self.updateDropFlags()
def updateDropFlags(self):
diff --git a/pyqtgraph/widgets/ValueLabel.py b/pyqtgraph/widgets/ValueLabel.py
index b24fb16c..0714689f 100644
--- a/pyqtgraph/widgets/ValueLabel.py
+++ b/pyqtgraph/widgets/ValueLabel.py
@@ -58,7 +58,7 @@ class ValueLabel(QtGui.QLabel):
def paintEvent(self, ev):
self.setText(self.generateText())
- return QtGui.QLabel.paintEvent(self, ev)
+ return super().paintEvent(ev)
def generateText(self):
if len(self.values) == 0:
From 13d652c794f99d586c68a71bfffc49001010b6e3 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Sun, 17 Jan 2021 12:30:12 +0800
Subject: [PATCH 06/17] convert to QPointF mouse event position
DockDrop.py : use QPointF mouse coords
---
pyqtgraph/dockarea/Dock.py | 5 +++--
pyqtgraph/dockarea/DockDrop.py | 4 ++--
pyqtgraph/opengl/GLViewWidget.py | 7 ++++---
pyqtgraph/widgets/GraphicsView.py | 15 +++++++++------
pyqtgraph/widgets/JoystickButton.py | 4 ++--
5 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/pyqtgraph/dockarea/Dock.py b/pyqtgraph/dockarea/Dock.py
index f1dd64f3..a4997b8c 100644
--- a/pyqtgraph/dockarea/Dock.py
+++ b/pyqtgraph/dockarea/Dock.py
@@ -5,6 +5,7 @@ from .DockDrop import *
from ..widgets.VerticalLabel import VerticalLabel
from ..python2_3 import asUnicode
+
class Dock(QtGui.QWidget, DockDrop):
sigStretchChanged = QtCore.Signal()
@@ -328,13 +329,13 @@ class DockLabel(VerticalLabel):
self.updateStyle()
def mousePressEvent(self, ev):
- self.pressPos = ev.pos()
+ self.pressPos = ev.localPos()
self.mouseMoved = False
ev.accept()
def mouseMoveEvent(self, ev):
if not self.mouseMoved:
- self.mouseMoved = (ev.pos() - self.pressPos).manhattanLength() > QtGui.QApplication.startDragDistance()
+ self.mouseMoved = (ev.localPos() - self.pressPos).manhattanLength() > QtGui.QApplication.startDragDistance()
if self.mouseMoved and ev.buttons() == QtCore.Qt.LeftButton:
self.dock.startDrag()
diff --git a/pyqtgraph/dockarea/DockDrop.py b/pyqtgraph/dockarea/DockDrop.py
index bd364f50..e16f3e7a 100644
--- a/pyqtgraph/dockarea/DockDrop.py
+++ b/pyqtgraph/dockarea/DockDrop.py
@@ -30,9 +30,9 @@ class DockDrop(object):
def dragMoveEvent(self, ev):
#print "drag move"
- ld = ev.pos().x()
+ ld = ev.posF().x()
rd = self.width() - ld
- td = ev.pos().y()
+ td = ev.posF().y()
bd = self.height() - td
mn = min(ld, rd, td, bd)
diff --git a/pyqtgraph/opengl/GLViewWidget.py b/pyqtgraph/opengl/GLViewWidget.py
index 2c9bff01..1426a424 100644
--- a/pyqtgraph/opengl/GLViewWidget.py
+++ b/pyqtgraph/opengl/GLViewWidget.py
@@ -401,11 +401,12 @@ class GLViewWidget(QtWidgets.QOpenGLWidget):
return xDist / self.width()
def mousePressEvent(self, ev):
- self.mousePos = ev.pos()
+ self.mousePos = ev.localPos()
def mouseMoveEvent(self, ev):
- diff = ev.pos() - self.mousePos
- self.mousePos = ev.pos()
+ lpos = ev.localPos()
+ diff = lpos - self.mousePos
+ self.mousePos = lpos
if ev.buttons() == QtCore.Qt.LeftButton:
if (ev.modifiers() & QtCore.Qt.ControlModifier):
diff --git a/pyqtgraph/widgets/GraphicsView.py b/pyqtgraph/widgets/GraphicsView.py
index 78b06ae6..4490d4de 100644
--- a/pyqtgraph/widgets/GraphicsView.py
+++ b/pyqtgraph/widgets/GraphicsView.py
@@ -25,6 +25,7 @@ from .. import getConfigOption
__all__ = ['GraphicsView']
+
class GraphicsView(QtGui.QGraphicsView):
"""Re-implementation of QGraphicsView that removes scrollbars and allows unambiguous control of the
viewed coordinate range. Also automatically creates a GraphicsScene and a central QGraphicsWidget
@@ -356,8 +357,9 @@ class GraphicsView(QtGui.QGraphicsView):
if not self.mouseEnabled:
return
- self.lastMousePos = Point(ev.pos())
- self.mousePressPos = ev.pos()
+ lpos = ev.localPos()
+ self.lastMousePos = lpos
+ self.mousePressPos = lpos
self.clickAccepted = ev.isAccepted()
if not self.clickAccepted:
self.scene().clearSelection()
@@ -372,15 +374,16 @@ class GraphicsView(QtGui.QGraphicsView):
return ## Everything below disabled for now..
def mouseMoveEvent(self, ev):
+ lpos = ev.localPos()
if self.lastMousePos is None:
- self.lastMousePos = Point(ev.pos())
- delta = Point(ev.pos() - self.lastMousePos.toQPoint())
- self.lastMousePos = Point(ev.pos())
+ self.lastMousePos = lpos
+ delta = Point(lpos - self.lastMousePos)
+ self.lastMousePos = lpos
super().mouseMoveEvent(ev)
if not self.mouseEnabled:
return
- self.sigSceneMouseMoved.emit(self.mapToScene(ev.pos()))
+ self.sigSceneMouseMoved.emit(self.mapToScene(lpos))
if self.clickAccepted: ## Ignore event if an item in the scene has already claimed it.
return
diff --git a/pyqtgraph/widgets/JoystickButton.py b/pyqtgraph/widgets/JoystickButton.py
index 709797b5..b668d82d 100644
--- a/pyqtgraph/widgets/JoystickButton.py
+++ b/pyqtgraph/widgets/JoystickButton.py
@@ -18,11 +18,11 @@ class JoystickButton(QtGui.QPushButton):
def mousePressEvent(self, ev):
self.setChecked(True)
- self.pressPos = ev.pos()
+ self.pressPos = ev.localPos()
ev.accept()
def mouseMoveEvent(self, ev):
- dif = ev.pos()-self.pressPos
+ dif = ev.localPos()-self.pressPos
self.setState(dif.x(), -dif.y())
def mouseReleaseEvent(self, ev):
From edea696bc3a43a02f15a2e8af7d98690bc198411 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Sat, 16 Jan 2021 17:36:27 +0800
Subject: [PATCH 07/17] ROI.py : pyqt6 has no KeyboardModifier class
the correct type to use is actually KeyboardModifiers
---
pyqtgraph/graphicsItems/ROI.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyqtgraph/graphicsItems/ROI.py b/pyqtgraph/graphicsItems/ROI.py
index 52a61ff5..b775a4ad 100644
--- a/pyqtgraph/graphicsItems/ROI.py
+++ b/pyqtgraph/graphicsItems/ROI.py
@@ -820,7 +820,7 @@ class ROI(GraphicsObject):
"""
return True
- def movePoint(self, handle, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True, coords='parent'):
+ def movePoint(self, handle, pos, modifiers=QtCore.Qt.KeyboardModifiers(0), finish=True, coords='parent'):
## called by Handles when they are moved.
## pos is the new position of the handle in scene coords, as requested by the handle.
@@ -1415,7 +1415,7 @@ class Handle(UIGraphicsItem):
self.currentPen = self.hoverPen
self.movePoint(pos, ev.modifiers(), finish=False)
- def movePoint(self, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True):
+ def movePoint(self, pos, modifiers=QtCore.Qt.KeyboardModifiers(0), finish=True):
for r in self.rois:
if not r.checkPointMove(self, pos, modifiers):
return
From 04e0a5e5af480bedd63b158846191130173c31fe Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Sun, 17 Jan 2021 12:59:02 +0800
Subject: [PATCH 08/17] WidgetGroup.py : PyQt6 was taking PyQt4 codepath
we drop PyQt4 codepath
---
pyqtgraph/WidgetGroup.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/pyqtgraph/WidgetGroup.py b/pyqtgraph/WidgetGroup.py
index 4656cc62..6b99f86c 100644
--- a/pyqtgraph/WidgetGroup.py
+++ b/pyqtgraph/WidgetGroup.py
@@ -218,9 +218,6 @@ class WidgetGroup(QtCore.QObject):
v1 = self.cache[n]
v2 = self.readWidget(w)
if v1 != v2:
- if QT_LIB != 'PyQt5':
- # Old signal kept for backward compatibility.
- self.emit(QtCore.SIGNAL('changed'), self.widgetList[w], v2)
self.sigChanged.emit(self.widgetList[w], v2)
def state(self):
From 0957735255846ba0e92677be2efb44c87064df70 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Sun, 17 Jan 2021 07:19:51 +0800
Subject: [PATCH 09/17] AxisItem.py : workaround or-ing of text flags
---
pyqtgraph/graphicsItems/AxisItem.py | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/pyqtgraph/graphicsItems/AxisItem.py b/pyqtgraph/graphicsItems/AxisItem.py
index 4c0f0de2..92cd84f2 100644
--- a/pyqtgraph/graphicsItems/AxisItem.py
+++ b/pyqtgraph/graphicsItems/AxisItem.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-from ..Qt import QtGui, QtCore
+from ..Qt import QtGui, QtCore, QT_LIB
from ..python2_3 import asUnicode
import numpy as np
from ..Point import Point
@@ -1103,19 +1103,28 @@ class AxisItem(GraphicsWidget):
width = textRect.width()
#self.textHeight = height
offset = max(0,self.style['tickLength']) + textOffset
+
if self.orientation == 'left':
- textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
+ alignFlags = QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
rect = QtCore.QRectF(tickStop-offset-width, x-(height/2), width, height)
elif self.orientation == 'right':
- textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
+ alignFlags = QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
rect = QtCore.QRectF(tickStop+offset, x-(height/2), width, height)
elif self.orientation == 'top':
- textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom
+ alignFlags = QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom
rect = QtCore.QRectF(x-width/2., tickStop-offset-height, width, height)
elif self.orientation == 'bottom':
- textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop
+ alignFlags = QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop
rect = QtCore.QRectF(x-width/2., tickStop+offset, width, height)
+ if QT_LIB == 'PyQt6':
+ # PyQt6 doesn't allow or-ing of different enum types
+ # so we need to take its value property
+ textFlags = alignFlags.value | QtCore.Qt.TextDontClip.value
+ else:
+ # for PyQt5, the following expression is not commutative!
+ textFlags = alignFlags | QtCore.Qt.TextDontClip
+
#p.setPen(self.pen())
#p.drawText(rect, textFlags, vstr)
textSpecs.append((rect, textFlags, vstr))
From 8a091859f1e74ac2f772307af4d9e7ab0e57f1ec Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Mon, 18 Jan 2021 09:37:54 +0800
Subject: [PATCH 10/17] GradientWidget.py : workaround or-ing of enum flag
values
---
pyqtgraph/widgets/GradientWidget.py | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/pyqtgraph/widgets/GradientWidget.py b/pyqtgraph/widgets/GradientWidget.py
index 77881b30..c5396d75 100644
--- a/pyqtgraph/widgets/GradientWidget.py
+++ b/pyqtgraph/widgets/GradientWidget.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-from ..Qt import QtGui, QtCore
+from ..Qt import QtGui, QtCore, QtWidgets, QT_LIB
from .GraphicsView import GraphicsView
from ..graphicsItems.GradientEditorItem import GradientEditorItem
import weakref
@@ -40,7 +40,18 @@ class GradientWidget(GraphicsView):
self.setOrientation(orientation)
self.setCacheMode(self.CacheNone)
self.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing)
- self.setFrameStyle(QtGui.QFrame.NoFrame | QtGui.QFrame.Plain)
+
+ if QT_LIB == 'PyQt6':
+ # PyQt6 doesn't allow or-ing of different enum types
+ # so we need to take its value property
+ NoFrame = QtWidgets.QFrame.Shape.NoFrame.value
+ Plain = QtWidgets.QFrame.Shadow.Plain.value
+ else:
+ NoFrame = QtWidgets.QFrame.NoFrame
+ Plain = QtWidgets.QFrame.Plain
+ frame_style = NoFrame | Plain
+
+ self.setFrameStyle(frame_style)
#self.setBackgroundRole(QtGui.QPalette.NoRole)
#self.setBackgroundBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
#self.setAutoFillBackground(False)
From 6dbda78231b10d4aa9be526569ec75e06564fd42 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Mon, 18 Jan 2021 12:24:20 +0800
Subject: [PATCH 11/17] Container.py : fix RecursionError
---
pyqtgraph/dockarea/Container.py | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/pyqtgraph/dockarea/Container.py b/pyqtgraph/dockarea/Container.py
index bc0b3648..04b775f9 100644
--- a/pyqtgraph/dockarea/Container.py
+++ b/pyqtgraph/dockarea/Container.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-from ..Qt import QtCore, QtGui
+from ..Qt import QtCore, QtGui, QtWidgets
import weakref
class Container(object):
@@ -76,7 +76,11 @@ class Container(object):
self.area.topContainer = None
self.containerChanged(None)
- def childEvent(self, ev):
+ def childEvent_(self, ev):
+ # NOTE: this method has been renamed to avoid having the same method name as
+ # QSplitter.childEvent()
+ # this causes problems for PyQt6 since SplitContainer inherits from
+ # Container and QSplitter.
ch = ev.child()
if ev.removed() and hasattr(ch, 'sigStretchChanged'):
#print "Child", ev.child(), "removed, updating", self
@@ -133,8 +137,8 @@ class SplitContainer(Container, QtGui.QSplitter):
self.setStretchFactor(i, sizes[i])
def childEvent(self, ev):
- QtGui.QSplitter.childEvent(self, ev)
- Container.childEvent(self, ev)
+ super().childEvent(ev) # call QSplitter.childEvent()
+ Container.childEvent_(self, ev)
#def restretchChildren(self):
#sizes = self.sizes()
@@ -204,6 +208,16 @@ class VContainer(SplitContainer):
self.setSizes([int(s*scale) for s in sizes])
+class StackedWidget(QtWidgets.QStackedWidget):
+ def __init__(self, *, container):
+ super().__init__()
+ self.container = container
+
+ def childEvent(self, ev):
+ super().childEvent(ev)
+ self.container.childEvent_(ev)
+
+
class TContainer(Container, QtGui.QWidget):
sigStretchChanged = QtCore.Signal()
def __init__(self, area):
@@ -221,9 +235,8 @@ class TContainer(Container, QtGui.QWidget):
self.hTabLayout.setContentsMargins(0,0,0,0)
self.layout.addWidget(self.hTabBox, 0, 1)
- self.stack = QtGui.QStackedWidget()
+ self.stack = StackedWidget(container=self)
self.layout.addWidget(self.stack, 1, 1)
- self.stack.childEvent = self.stackChildEvent
self.setLayout(self.layout)
@@ -276,8 +289,4 @@ class TContainer(Container, QtGui.QWidget):
y = max(y, wy)
self.setStretch(x, y)
- def stackChildEvent(self, ev):
- QtGui.QStackedWidget.childEvent(self.stack, ev)
- Container.childEvent(self, ev)
-
from . import Dock
From c0336acc11bcebc8be961c345ee29e24bc31d31d Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Mon, 18 Jan 2021 15:22:29 +0800
Subject: [PATCH 12/17] bug: style() should have been styleHint()
Style is enum for { StyleNormal, StyleItalic, StyleOblique }
---
pyqtgraph/exporters/SVGExporter.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pyqtgraph/exporters/SVGExporter.py b/pyqtgraph/exporters/SVGExporter.py
index 094988dc..a8f0a17b 100644
--- a/pyqtgraph/exporters/SVGExporter.py
+++ b/pyqtgraph/exporters/SVGExporter.py
@@ -377,11 +377,11 @@ def correctCoordinates(node, defs, item, options):
families = ch.getAttribute('font-family').split(',')
if len(families) == 1:
font = QtGui.QFont(families[0].strip('" '))
- if font.style() == font.SansSerif:
+ if font.styleHint() == font.StyleHint.SansSerif:
families.append('sans-serif')
- elif font.style() == font.Serif:
+ elif font.styleHint() == font.StyleHint.Serif:
families.append('serif')
- elif font.style() == font.Courier:
+ elif font.styleHint() == font.StyleHint.Courier:
families.append('monospace')
ch.setAttribute('font-family', ', '.join([f if ' ' not in f else '"%s"'%f for f in families]))
From 3a9e81cc490b98a58e0bdeb2869d00a6de97b8b3 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Mon, 18 Jan 2021 10:54:24 +0800
Subject: [PATCH 13/17] update RemoteGraphicsView.py for Qt6
---
pyqtgraph/widgets/RemoteGraphicsView.py | 195 +++++++++---------------
1 file changed, 76 insertions(+), 119 deletions(-)
diff --git a/pyqtgraph/widgets/RemoteGraphicsView.py b/pyqtgraph/widgets/RemoteGraphicsView.py
index 22065c50..620f4085 100644
--- a/pyqtgraph/widgets/RemoteGraphicsView.py
+++ b/pyqtgraph/widgets/RemoteGraphicsView.py
@@ -9,55 +9,6 @@ import mmap, tempfile, ctypes, atexit, sys, random
__all__ = ['RemoteGraphicsView']
-class SerializableWheelEvent:
- """
- Contains all information of a QWheelEvent, is serializable and can generate QWheelEvents.
-
- Methods have the functionality of their QWheelEvent equivalent.
- """
- def __init__(self, _pos, _globalPos, _delta, _buttons, _modifiers, _orientation):
- self._pos = _pos
- self._globalPos = _globalPos
- self._delta = _delta
- self._buttons = _buttons
- self._modifiers = _modifiers
- self._orientation_vertical = _orientation == QtCore.Qt.Vertical
-
- def pos(self):
- return self._pos
-
- def globalPos(self):
- return self._globalPos
-
- def delta(self):
- return self._delta
-
- def orientation(self):
- if self._orientation_vertical:
- return QtCore.Qt.Vertical
- else:
- return QtCore.Qt.Horizontal
-
- def angleDelta(self):
- if self._orientation_vertical:
- return QtCore.QPoint(0, self._delta)
- else:
- return QtCore.QPoint(self._delta, 0)
-
- def buttons(self):
- return QtCore.Qt.MouseButtons(self._buttons)
-
- def modifiers(self):
- return QtCore.Qt.KeyboardModifiers(self._modifiers)
-
- def toQWheelEvent(self):
- """
- Generate QWheelEvent from SerializableWheelEvent.
- """
- if QT_LIB in ['PyQt4', 'PySide']:
- return QtGui.QWheelEvent(self.pos(), self.globalPos(), self.delta(), self.buttons(), self.modifiers(), self.orientation())
- else:
- return QtGui.QWheelEvent(self.pos(), self.globalPos(), QtCore.QPoint(), self.angleDelta(), self.delta(), self.orientation(), self.buttons(), self.modifiers())
class RemoteGraphicsView(QtGui.QWidget):
"""
@@ -111,7 +62,7 @@ class RemoteGraphicsView(QtGui.QWidget):
setattr(self, method, getattr(self._view, method))
def resizeEvent(self, ev):
- ret = QtGui.QWidget.resizeEvent(self, ev)
+ ret = super().resizeEvent(ev)
self._view.resize(self.size(), _callSync='off')
return ret
@@ -145,52 +96,60 @@ class RemoteGraphicsView(QtGui.QWidget):
p = QtGui.QPainter(self)
p.drawImage(self.rect(), self._img, QtCore.QRect(0, 0, self._img.width(), self._img.height()))
p.end()
-
+
+ def serialize_mouse_common(self, ev):
+ if QT_LIB == 'PyQt6':
+ # PyQt6 can pickle MouseButtons and KeyboardModifiers but cannot cast to int
+ btns = ev.buttons()
+ mods = ev.modifiers()
+ else:
+ # PyQt5, PySide2, PySide6 cannot pickle MouseButtons and KeyboardModifiers
+ btns = int(ev.buttons())
+ mods = int(ev.modifiers())
+ return (btns, mods)
+
+ def serialize_mouse_event(self, ev):
+ # lpos, gpos = ev.localPos(), ev.screenPos()
+ # RemoteGraphicsView Renderer assumes to be at (0, 0)
+ gpos = lpos = ev.localPos()
+ btns, mods = self.serialize_mouse_common(ev)
+ return (ev.type(), lpos, gpos, ev.button(), btns, mods)
+
+ def serialize_wheel_event(self, ev):
+ # lpos, gpos = ev.position(), globalPosition()
+ # RemoteGraphicsView Renderer assumes to be at (0, 0)
+ gpos = lpos = ev.position()
+ btns, mods = self.serialize_mouse_common(ev)
+ return (lpos, gpos, ev.pixelDelta(), ev.angleDelta(), btns, mods, ev.phase(), ev.inverted())
+
def mousePressEvent(self, ev):
- self._view.mousePressEvent(int(ev.type()), ev.pos(), ev.pos(), int(ev.button()), int(ev.buttons()), int(ev.modifiers()), _callSync='off')
+ self._view.mousePressEvent(self.serialize_mouse_event(ev), _callSync='off')
ev.accept()
- return QtGui.QWidget.mousePressEvent(self, ev)
+ return super().mousePressEvent(ev)
def mouseReleaseEvent(self, ev):
- self._view.mouseReleaseEvent(int(ev.type()), ev.pos(), ev.pos(), int(ev.button()), int(ev.buttons()), int(ev.modifiers()), _callSync='off')
+ self._view.mouseReleaseEvent(self.serialize_mouse_event(ev), _callSync='off')
ev.accept()
- return QtGui.QWidget.mouseReleaseEvent(self, ev)
+ return super().mouseReleaseEvent(ev)
def mouseMoveEvent(self, ev):
- self._view.mouseMoveEvent(int(ev.type()), ev.pos(), ev.pos(), int(ev.button()), int(ev.buttons()), int(ev.modifiers()), _callSync='off')
+ self._view.mouseMoveEvent(self.serialize_mouse_event(ev), _callSync='off')
ev.accept()
- return QtGui.QWidget.mouseMoveEvent(self, ev)
+ return super().mouseMoveEvent(ev)
def wheelEvent(self, ev):
- delta = 0
- orientation = QtCore.Qt.Horizontal
- if QT_LIB in ['PyQt4', 'PySide']:
- delta = ev.delta()
- orientation = ev.orientation()
- else:
- delta = ev.angleDelta().x()
- if delta == 0:
- orientation = QtCore.Qt.Vertical
- delta = ev.angleDelta().y()
-
- serializableEvent = SerializableWheelEvent(ev.pos(), ev.pos(), delta, int(ev.buttons()), int(ev.modifiers()), orientation)
- self._view.wheelEvent(serializableEvent, _callSync='off')
+ self._view.wheelEvent(self.serialize_wheel_event(ev), _callSync='off')
ev.accept()
- return QtGui.QWidget.wheelEvent(self, ev)
-
- def keyEvent(self, ev):
- if self._view.keyEvent(int(ev.type()), int(ev.modifiers()), text, autorep, count):
- ev.accept()
- return QtGui.QWidget.keyEvent(self, ev)
-
+ return super().wheelEvent(ev)
+
def enterEvent(self, ev):
lws = ev.localPos(), ev.windowPos(), ev.screenPos()
self._view.enterEvent(lws, _callSync='off')
- return QtGui.QWidget.enterEvent(self, ev)
+ return super().enterEvent(ev)
def leaveEvent(self, ev):
- self._view.leaveEvent(int(ev.type()), _callSync='off')
- return QtGui.QWidget.leaveEvent(self, ev)
+ self._view.leaveEvent(ev.type(), _callSync='off')
+ return super().leaveEvent(ev)
def remoteProcess(self):
"""Return the remote process handle. (see multiprocess.remoteproxy.RemoteEventHandler)"""
@@ -240,11 +199,11 @@ class Renderer(GraphicsView):
def update(self):
self.img = None
- return GraphicsView.update(self)
+ return super().update()
def resize(self, size):
oldSize = self.size()
- GraphicsView.resize(self, size)
+ super().resize(size)
self.resizeEvent(QtGui.QResizeEvent(size, oldSize))
self.update()
@@ -272,62 +231,60 @@ class Renderer(GraphicsView):
self.shm.resize(size)
## render the scene directly to shared memory
+ ctypes_obj = ctypes.c_char.from_buffer(self.shm, 0)
if QT_LIB.startswith('PySide'):
- ch = ctypes.c_char.from_buffer(self.shm, 0)
- self.img = QtGui.QImage(ch, self.width(), self.height(), QtGui.QImage.Format_ARGB32)
+ # PySide2, PySide6
+ img_ptr = ctypes_obj
else:
- address = ctypes.addressof(ctypes.c_char.from_buffer(self.shm, 0))
+ # PyQt5, PyQt6
+ img_ptr = sip.voidptr(ctypes.addressof(ctypes_obj))
+
+ if QT_LIB == 'PyQt6':
+ img_ptr.setsize(size)
+
+ self.img = QtGui.QImage(img_ptr, self.width(), self.height(), QtGui.QImage.Format_ARGB32)
- # different versions of pyqt have different requirements here..
- try:
- self.img = QtGui.QImage(sip.voidptr(address), self.width(), self.height(), QtGui.QImage.Format_ARGB32)
- except TypeError:
- try:
- self.img = QtGui.QImage(memoryview(buffer(self.shm)), self.width(), self.height(), QtGui.QImage.Format_ARGB32)
- except TypeError:
- # Works on PyQt 4.9.6
- self.img = QtGui.QImage(address, self.width(), self.height(), QtGui.QImage.Format_ARGB32)
self.img.fill(0xffffffff)
p = QtGui.QPainter(self.img)
self.render(p, self.viewRect(), self.rect())
p.end()
self.sceneRendered.emit((self.width(), self.height(), self.shm.size(), self.shmFileName()))
- def mousePressEvent(self, typ, pos, gpos, btn, btns, mods):
- typ = QtCore.QEvent.Type(typ)
- btn = QtCore.Qt.MouseButton(btn)
+ def deserialize_mouse_event(self, mouse_event):
+ typ, pos, gpos, btn, btns, mods = mouse_event
+ typ = QtCore.QEvent.Type(typ) # this line needed by PyQt5 only
btns = QtCore.Qt.MouseButtons(btns)
mods = QtCore.Qt.KeyboardModifiers(mods)
- return GraphicsView.mousePressEvent(self, QtGui.QMouseEvent(typ, pos, gpos, btn, btns, mods))
+ return QtGui.QMouseEvent(typ, pos, gpos, btn, btns, mods)
- def mouseMoveEvent(self, typ, pos, gpos, btn, btns, mods):
- typ = QtCore.QEvent.Type(typ)
- btn = QtCore.Qt.MouseButton(btn)
+ def deserialize_wheel_event(self, wheel_event):
+ pos, gpos, pixelDelta, angleDelta, btns, mods, scrollPhase, inverted = wheel_event
btns = QtCore.Qt.MouseButtons(btns)
mods = QtCore.Qt.KeyboardModifiers(mods)
- return GraphicsView.mouseMoveEvent(self, QtGui.QMouseEvent(typ, pos, gpos, btn, btns, mods))
+ return QtGui.QWheelEvent(pos, gpos, pixelDelta, angleDelta, btns, mods, scrollPhase, inverted)
- def mouseReleaseEvent(self, typ, pos, gpos, btn, btns, mods):
- typ = QtCore.QEvent.Type(typ)
- btn = QtCore.Qt.MouseButton(btn)
- btns = QtCore.Qt.MouseButtons(btns)
- mods = QtCore.Qt.KeyboardModifiers(mods)
- return GraphicsView.mouseReleaseEvent(self, QtGui.QMouseEvent(typ, pos, gpos, btn, btns, mods))
+ def mousePressEvent(self, mouse_event):
+ ev = self.deserialize_mouse_event(mouse_event)
+ return super().mousePressEvent(ev)
+
+ def mouseMoveEvent(self, mouse_event):
+ ev = self.deserialize_mouse_event(mouse_event)
+ return super().mouseMoveEvent(ev)
+
+ def mouseReleaseEvent(self, mouse_event):
+ ev = self.deserialize_mouse_event(mouse_event)
+ return super().mouseReleaseEvent(ev)
- def wheelEvent(self, ev):
- return GraphicsView.wheelEvent(self, ev.toQWheelEvent())
+ def wheelEvent(self, wheel_event):
+ ev = self.deserialize_wheel_event(wheel_event)
+ return super().wheelEvent(ev)
- def keyEvent(self, typ, mods, text, autorep, count):
- typ = QtCore.QEvent.Type(typ)
- mods = QtCore.Qt.KeyboardModifiers(mods)
- GraphicsView.keyEvent(self, QtGui.QKeyEvent(typ, mods, text, autorep, count))
- return ev.accepted()
-
def enterEvent(self, lws):
ev = QtGui.QEnterEvent(*lws)
- return GraphicsView.enterEvent(self, ev)
+ return super().enterEvent(ev)
def leaveEvent(self, typ):
- ev = QtCore.QEvent(QtCore.QEvent.Type(typ))
- return GraphicsView.leaveEvent(self, ev)
+ typ = QtCore.QEvent.Type(typ) # this line needed by PyQt5 only
+ ev = QtCore.QEvent(typ)
+ return super().leaveEvent(ev)
From 2e688cf67244662f215854851e50cb21c4078b1c Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Fri, 22 Jan 2021 12:29:23 +0800
Subject: [PATCH 14/17] PySide6 : shim missing binding QGradient.setStops
---
pyqtgraph/Qt.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/pyqtgraph/Qt.py b/pyqtgraph/Qt.py
index c1509265..5323c46c 100644
--- a/pyqtgraph/Qt.py
+++ b/pyqtgraph/Qt.py
@@ -390,6 +390,15 @@ if QT_LIB in [PYQT4, PYQT5, PYQT6]:
QtCore.Signal = QtCore.pyqtSignal
+if QT_LIB == PYSIDE6:
+ # PySide6 6.0 has a missing binding
+ if not hasattr(QtGui.QGradient, 'setStops'):
+ def __setStops(self, stops):
+ for pos, color in stops:
+ self.setColorAt(pos, color)
+ QtGui.QGradient.setStops = __setStops
+
+
if QT_LIB == PYQT6:
# module.Class.EnumClass.Enum -> module.Class.Enum
def promote_enums(module):
From d0c062d7e59a659c1db8377de5d4afbca04a817d Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Fri, 22 Jan 2021 12:30:49 +0800
Subject: [PATCH 15/17] Revert "workaround missing setStops binding"
This reverts commit c4addbeaeab027d3979968373d0a3ce3abbd8f0f.
---
pyqtgraph/colormap.py | 8 +-------
pyqtgraph/graphicsItems/GradientEditorItem.py | 8 +-------
2 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/pyqtgraph/colormap.py b/pyqtgraph/colormap.py
index 741cea08..3661bf75 100644
--- a/pyqtgraph/colormap.py
+++ b/pyqtgraph/colormap.py
@@ -359,13 +359,7 @@ class ColorMap(object):
pos, color = self.getStops(mode=self.BYTE)
color = [QtGui.QColor(*x) for x in color]
- stops = zip(pos, color)
- if hasattr(g, 'setStops'):
- g.setStops(list(stops))
- else:
- # PySide6 has a missing setStops binding
- for pos, col in stops:
- g.setColorAt(pos, col)
+ g.setStops(list(zip(pos, color)))
return g
def getColors(self, mode=None):
diff --git a/pyqtgraph/graphicsItems/GradientEditorItem.py b/pyqtgraph/graphicsItems/GradientEditorItem.py
index d763e965..6f5d9132 100644
--- a/pyqtgraph/graphicsItems/GradientEditorItem.py
+++ b/pyqtgraph/graphicsItems/GradientEditorItem.py
@@ -626,10 +626,9 @@ class GradientEditorItem(TickSliderItem):
def getGradient(self):
"""Return a QLinearGradient object."""
g = QtGui.QLinearGradient(QtCore.QPointF(0,0), QtCore.QPointF(self.length,0))
- stops = []
if self.colorMode == 'rgb':
ticks = self.listTicks()
- stops = [(x, QtGui.QColor(t.color)) for t,x in ticks]
+ g.setStops([(x, QtGui.QColor(t.color)) for t,x in ticks])
elif self.colorMode == 'hsv': ## HSV mode is approximated for display by interpolating 10 points between each stop
ticks = self.listTicks()
stops = []
@@ -642,12 +641,7 @@ class GradientEditorItem(TickSliderItem):
x = x1 + dx*j
stops.append((x, self.getColor(x)))
stops.append((x2, self.getColor(x2)))
- if hasattr(g, 'setStops'):
g.setStops(stops)
- else:
- # PySide6 has a missing setStops binding
- for pos, col in stops:
- g.setColorAt(pos, col)
return g
def getColor(self, x, toQColor=True):
From eec411a3c67d077768bb443daf20f5c9dd12780c Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Fri, 22 Jan 2021 11:09:59 +0800
Subject: [PATCH 16/17] fixup Flowchart for PyQt6
---
pyqtgraph/flowchart/Node.py | 39 ++++++++++++++++-------------
pyqtgraph/flowchart/Terminal.py | 36 +++++++++++++++-----------
pyqtgraph/flowchart/library/Data.py | 28 ++++++++++++---------
3 files changed, 60 insertions(+), 43 deletions(-)
diff --git a/pyqtgraph/flowchart/Node.py b/pyqtgraph/flowchart/Node.py
index dcda62d7..eebbfac4 100644
--- a/pyqtgraph/flowchart/Node.py
+++ b/pyqtgraph/flowchart/Node.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-from ..Qt import QtCore, QtGui
+from ..Qt import QtCore, QtGui, QtWidgets
from ..graphicsItems.GraphicsObject import GraphicsObject
from .. import functions as fn
from .Terminal import *
@@ -436,6 +436,24 @@ class Node(QtCore.QObject):
t.disconnectAll()
+class TextItem(QtWidgets.QGraphicsTextItem):
+ def __init__(self, text, parent, on_update):
+ super().__init__(text, parent)
+ self.on_update = on_update
+
+ def focusOutEvent(self, ev):
+ super().focusOutEvent(ev)
+ if self.on_update is not None:
+ self.on_update()
+
+ def keyPressEvent(self, ev):
+ if ev.key() == QtCore.Qt.Key_Enter or ev.key() == QtCore.Qt.Key_Return:
+ if self.on_update is not None:
+ self.on_update()
+ return
+ super().keyPressEvent(ev)
+
+
#class NodeGraphicsItem(QtGui.QGraphicsItem):
class NodeGraphicsItem(GraphicsObject):
def __init__(self, node):
@@ -461,16 +479,13 @@ class NodeGraphicsItem(GraphicsObject):
self.setFlags(flags)
self.bounds = QtCore.QRectF(0, 0, 100, 100)
- self.nameItem = QtGui.QGraphicsTextItem(self.node.name(), self)
+ self.nameItem = TextItem(self.node.name(), self, self.labelChanged)
self.nameItem.setDefaultTextColor(QtGui.QColor(50, 50, 50))
self.nameItem.moveBy(self.bounds.width()/2. - self.nameItem.boundingRect().width()/2., 0)
self.nameItem.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction)
self.updateTerminals()
#self.setZValue(10)
- self.nameItem.focusOutEvent = self.labelFocusOut
- self.nameItem.keyPressEvent = self.labelKeyPress
-
self.menu = None
self.buildMenu()
@@ -481,16 +496,6 @@ class NodeGraphicsItem(GraphicsObject):
#item.setZValue(z+1)
#GraphicsObject.setZValue(self, z)
- def labelFocusOut(self, ev):
- QtGui.QGraphicsTextItem.focusOutEvent(self.nameItem, ev)
- self.labelChanged()
-
- def labelKeyPress(self, ev):
- if ev.key() == QtCore.Qt.Key_Enter or ev.key() == QtCore.Qt.Key_Return:
- self.labelChanged()
- else:
- QtGui.QGraphicsTextItem.keyPressEvent(self.nameItem, ev)
-
def labelChanged(self):
newName = str(self.nameItem.toPlainText())
if newName != self.node.name():
@@ -574,7 +579,7 @@ class NodeGraphicsItem(GraphicsObject):
def mouseClickEvent(self, ev):
#print "Node.mouseClickEvent called."
- if int(ev.button()) == int(QtCore.Qt.LeftButton):
+ if ev.button() == QtCore.Qt.LeftButton:
ev.accept()
#print " ev.button: left"
sel = self.isSelected()
@@ -587,7 +592,7 @@ class NodeGraphicsItem(GraphicsObject):
self.update()
#return ret
- elif int(ev.button()) == int(QtCore.Qt.RightButton):
+ elif ev.button() == QtCore.Qt.RightButton:
#print " ev.button: right"
ev.accept()
#pos = ev.screenPos()
diff --git a/pyqtgraph/flowchart/Terminal.py b/pyqtgraph/flowchart/Terminal.py
index 7c512dda..c2e60a55 100644
--- a/pyqtgraph/flowchart/Terminal.py
+++ b/pyqtgraph/flowchart/Terminal.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-from ..Qt import QtCore, QtGui
+from ..Qt import QtCore, QtGui, QtWidgets
import weakref
from ..graphicsItems.GraphicsObject import GraphicsObject
from .. import functions as fn
@@ -273,6 +273,25 @@ class Terminal(object):
"""
return self._name < other._name
+
+class TextItem(QtWidgets.QGraphicsTextItem):
+ def __init__(self, text, parent, on_update):
+ super().__init__(text, parent)
+ self.on_update = on_update
+
+ def focusOutEvent(self, ev):
+ super().focusOutEvent(ev)
+ if self.on_update is not None:
+ self.on_update()
+
+ def keyPressEvent(self, ev):
+ if ev.key() == QtCore.Qt.Key_Enter or ev.key() == QtCore.Qt.Key_Return:
+ if self.on_update is not None:
+ self.on_update()
+ return
+ super().keyPressEvent(ev)
+
+
class TerminalGraphicsItem(GraphicsObject):
def __init__(self, term, parent=None):
@@ -280,27 +299,16 @@ class TerminalGraphicsItem(GraphicsObject):
GraphicsObject.__init__(self, parent)
self.brush = fn.mkBrush(0,0,0)
self.box = QtGui.QGraphicsRectItem(0, 0, 10, 10, self)
- self.label = QtGui.QGraphicsTextItem(self.term.name(), self)
+ on_update = self.labelChanged if self.term.isRenamable() else None
+ self.label = TextItem(self.term.name(), self, on_update)
self.label.scale(0.7, 0.7)
self.newConnection = None
self.setFiltersChildEvents(True) ## to pick up mouse events on the rectitem
if self.term.isRenamable():
self.label.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction)
- self.label.focusOutEvent = self.labelFocusOut
- self.label.keyPressEvent = self.labelKeyPress
self.setZValue(1)
self.menu = None
- def labelFocusOut(self, ev):
- QtGui.QGraphicsTextItem.focusOutEvent(self.label, ev)
- self.labelChanged()
-
- def labelKeyPress(self, ev):
- if ev.key() == QtCore.Qt.Key_Enter or ev.key() == QtCore.Qt.Key_Return:
- self.labelChanged()
- else:
- QtGui.QGraphicsTextItem.keyPressEvent(self.label, ev)
-
def labelChanged(self):
newName = str(self.label.toPlainText())
if newName != self.term.name():
diff --git a/pyqtgraph/flowchart/library/Data.py b/pyqtgraph/flowchart/library/Data.py
index b133b159..6edd3a80 100644
--- a/pyqtgraph/flowchart/library/Data.py
+++ b/pyqtgraph/flowchart/library/Data.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from ..Node import Node
-from ...Qt import QtGui, QtCore
+from ...Qt import QtGui, QtCore, QtWidgets
import numpy as np
import sys
from .common import *
@@ -173,6 +173,20 @@ class RegionSelectNode(CtrlNode):
self.update()
+class TextEdit(QtWidgets.QTextEdit):
+ def __init__(self, on_update):
+ super().__init__()
+ self.on_update = on_update
+ self.lastText = None
+
+ def focusOutEvent(self, ev):
+ text = str(self.toPlainText())
+ if text != self.lastText:
+ self.lastText = text
+ self.on_update()
+ super().focusOutEvent(ev)
+
+
class EvalNode(Node):
"""Return the output of a string evaluated/executed by the python interpreter.
The string may be either an expression or a python script, and inputs are accessed as the name of the terminal.
@@ -190,15 +204,12 @@ class EvalNode(Node):
self.ui = QtGui.QWidget()
self.layout = QtGui.QGridLayout()
- self.text = QtGui.QTextEdit()
+ self.text = TextEdit(self.update)
self.text.setTabStopWidth(30)
self.text.setPlainText("# Access inputs as args['input_name']\nreturn {'output': None} ## one key per output terminal")
self.layout.addWidget(self.text, 1, 0, 1, 2)
self.ui.setLayout(self.layout)
- self.text.focusOutEvent = self.focusOutEvent
- self.lastText = None
-
def ctrlWidget(self):
return self.ui
@@ -221,13 +232,6 @@ class EvalNode(Node):
def code(self):
return self.text.toPlainText()
- def focusOutEvent(self, ev):
- text = str(self.text.toPlainText())
- if text != self.lastText:
- self.lastText = text
- self.update()
- return QtGui.QTextEdit.focusOutEvent(self.text, ev)
-
def process(self, display=True, **args):
l = locals()
l.update(args)
From 6c760f3de17bc4677eddc1b64054ca8aa6eba1d7 Mon Sep 17 00:00:00 2001
From: KIU Shueng Chuan
Date: Mon, 18 Jan 2021 12:38:28 +0800
Subject: [PATCH 17/17] add PyQt6 to CI
skip tests that don't work for Qt6
add Qt6 and remove Qt4 from test_examples.py
update README.md
switch mouse tests to use QPointF
this eliminates all the special casing for different bindings
---
.github/workflows/main.yml | 2 +-
README.md | 7 ++++---
examples/test_examples.py | 13 +++----------
pyqtgraph/exporters/tests/test_matplotlib.py | 2 +-
.../graphicsItems/tests/test_InfiniteLine.py | 18 +++++++++---------
pyqtgraph/tests/image_testing.py | 2 +-
pyqtgraph/tests/ui_testing.py | 8 +-------
7 files changed, 20 insertions(+), 32 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ad152f7f..ea6046a3 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -31,7 +31,7 @@ jobs:
numpy-version: "~=1.19.0"
- python-version: "3.9"
qt-lib: "pyqt"
- qt-version: "PyQt5~=5.15"
+ qt-version: "PyQt6"
numpy-version: "~=1.19.0"
- python-version: "3.9"
qt-lib: "pyside"
diff --git a/README.md b/README.md
index 7a8e745a..d92402d2 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ PyQtGraph
[![Total alerts](https://img.shields.io/lgtm/alerts/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/alerts/)
[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/context:python)
-A pure-Python graphics library for PyQt5/PySide2/PySide6
+A pure-Python graphics library for PyQt5/PyQt6/PySide2/PySide6
Copyright 2020 Luke Campagnola, University of North Carolina at Chapel Hill
@@ -36,7 +36,7 @@ Currently this means:
* Python 3.7+
* Qt 5.12-6.0
* Required
- * PyQt5, PySide2 or PySide6
+ * PyQt5, PyQt6, PySide2 or PySide6
* `numpy` 1.17+
* Optional
* `scipy` for image processing
@@ -57,8 +57,9 @@ The following table represents the python environments we test in our CI system.
| PySide2-5.12 | :white_check_mark: | :x: | :x: |
| PyQt5-5.12 | :white_check_mark: | :x: | :x: |
| PySide2-5.15 | :x: | :white_check_mark: | :x: |
-| PyQt5-5.15 | :x: | :white_check_mark: | :white_check_mark: |
+| PyQt5-5.15 | :x: | :white_check_mark: | :x: |
| PySide6-6.0 | :x: | :x: | :white_check_mark: |
+| PyQt6-6.0 | :x: | :x: | :white_check_mark: |
Support
-------
diff --git a/examples/test_examples.py b/examples/test_examples.py
index b5baf76f..f3ffcebd 100644
--- a/examples/test_examples.py
+++ b/examples/test_examples.py
@@ -35,10 +35,10 @@ def buildFileList(examples, files=None):
path = os.path.abspath(os.path.dirname(__file__))
files = sorted(set(buildFileList(examples)))
frontends = {
- Qt.PYQT4: False,
Qt.PYQT5: False,
- Qt.PYSIDE: False,
- Qt.PYSIDE2: False
+ Qt.PYQT6: False,
+ Qt.PYSIDE2: False,
+ Qt.PYSIDE6: False,
}
# sort out which of the front ends are available
for frontend in frontends.keys():
@@ -66,13 +66,6 @@ conditionalExamples = {
False,
reason="Test is being problematic on CI machines"
),
- "optics_demos.py": exceptionCondition(
- not frontends[Qt.PYSIDE],
- reason=(
- "Test fails due to PySide bug: ",
- "https://bugreports.qt.io/browse/PYSIDE-671"
- )
- ),
'GLVolumeItem.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
diff --git a/pyqtgraph/exporters/tests/test_matplotlib.py b/pyqtgraph/exporters/tests/test_matplotlib.py
index fbff04f3..3e3e98dd 100644
--- a/pyqtgraph/exporters/tests/test_matplotlib.py
+++ b/pyqtgraph/exporters/tests/test_matplotlib.py
@@ -7,7 +7,7 @@ pytest.importorskip("matplotlib")
app = pg.mkQApp()
skip_qt6 = pytest.mark.skipif(
- pg.QT_LIB == "PySide6",
+ pg.QT_LIB in ["PySide6", "PyQt6"],
reason= (
"Matplotlib has no Qt6 support yet, "
"see https://github.com/matplotlib/matplotlib/pull/19255"
diff --git a/pyqtgraph/graphicsItems/tests/test_InfiniteLine.py b/pyqtgraph/graphicsItems/tests/test_InfiniteLine.py
index 5d9a2184..689e1963 100644
--- a/pyqtgraph/graphicsItems/tests/test_InfiniteLine.py
+++ b/pyqtgraph/graphicsItems/tests/test_InfiniteLine.py
@@ -63,8 +63,8 @@ def test_mouseInteraction():
plt.setYRange(-10, 10)
# test horizontal drag
- pos = plt.plotItem.vb.mapViewToScene(pg.Point(0,5)).toPoint()
- pos2 = pos - QtCore.QPoint(200, 200)
+ pos = plt.plotItem.vb.mapViewToScene(pg.Point(0,5))
+ pos2 = pos - QtCore.QPointF(200, 200)
mouseMove(plt, pos)
assert vline.mouseHovering is True and hline.mouseHovering is False
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
@@ -72,17 +72,17 @@ def test_mouseInteraction():
assert abs(vline.value() - plt.plotItem.vb.mapSceneToView(pos2).x()) <= px
# test missed drag
- pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
- pos = pos + QtCore.QPoint(0, 6)
- pos2 = pos + QtCore.QPoint(-20, -20)
+ pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0))
+ pos = pos + QtCore.QPointF(0, 6)
+ pos2 = pos + QtCore.QPointF(-20, -20)
mouseMove(plt, pos)
assert vline.mouseHovering is False and hline.mouseHovering is False
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
assert hline.value() == 0
# test vertical drag
- pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
- pos2 = pos - QtCore.QPoint(50, 50)
+ pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0))
+ pos2 = pos - QtCore.QPointF(50, 50)
mouseMove(plt, pos)
assert vline.mouseHovering is False and hline.mouseHovering is True
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
@@ -90,8 +90,8 @@ def test_mouseInteraction():
assert abs(hline.value() - plt.plotItem.vb.mapSceneToView(pos2).y()) <= px
# test non-interactive line
- pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,-1)).toPoint()
- pos2 = pos - QtCore.QPoint(50, 50)
+ pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,-1))
+ pos2 = pos - QtCore.QPointF(50, 50)
mouseMove(plt, pos)
assert hline2.mouseHovering == False
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
diff --git a/pyqtgraph/tests/image_testing.py b/pyqtgraph/tests/image_testing.py
index 7cb993f9..1245bb02 100644
--- a/pyqtgraph/tests/image_testing.py
+++ b/pyqtgraph/tests/image_testing.py
@@ -257,7 +257,7 @@ def assertImageMatch(im1, im2, minCorr=None, pxThreshold=50.,
assert im1.dtype == im2.dtype
if pxCount == -1:
- if QT_LIB in {'PyQt5', 'PySide2', 'PySide6'}:
+ if QT_LIB in {'PyQt5', 'PySide2', 'PySide6', 'PyQt6'}:
# Qt5 generates slightly different results; relax the tolerance
# until test images are updated.
pxCount = int(im1.shape[0] * im1.shape[1] * 0.01)
diff --git a/pyqtgraph/tests/ui_testing.py b/pyqtgraph/tests/ui_testing.py
index 4bcb7606..747aadf9 100644
--- a/pyqtgraph/tests/ui_testing.py
+++ b/pyqtgraph/tests/ui_testing.py
@@ -1,5 +1,5 @@
import time
-from ..Qt import QtCore, QtGui, QtTest, QT_LIB
+from ..Qt import QtCore, QtGui, QtTest
def resizeWindow(win, w, h, timeout=2.0):
@@ -32,8 +32,6 @@ def mousePress(widget, pos, button, modifier=None):
widget = widget.viewport()
if modifier is None:
modifier = QtCore.Qt.NoModifier
- if QT_LIB != 'PyQt5' and isinstance(pos, QtCore.QPointF):
- pos = pos.toPoint()
event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress, pos, button, QtCore.Qt.NoButton, modifier)
QtGui.QApplication.sendEvent(widget, event)
@@ -43,8 +41,6 @@ def mouseRelease(widget, pos, button, modifier=None):
widget = widget.viewport()
if modifier is None:
modifier = QtCore.Qt.NoModifier
- if QT_LIB != 'PyQt5' and isinstance(pos, QtCore.QPointF):
- pos = pos.toPoint()
event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonRelease, pos, button, QtCore.Qt.NoButton, modifier)
QtGui.QApplication.sendEvent(widget, event)
@@ -56,8 +52,6 @@ def mouseMove(widget, pos, buttons=None, modifier=None):
modifier = QtCore.Qt.NoModifier
if buttons is None:
buttons = QtCore.Qt.NoButton
- if QT_LIB != 'PyQt5' and isinstance(pos, QtCore.QPointF):
- pos = pos.toPoint()
event = QtGui.QMouseEvent(QtCore.QEvent.MouseMove, pos, QtCore.Qt.NoButton, buttons, modifier)
QtGui.QApplication.sendEvent(widget, event)