Merge pull request #1502 from pijyoi/pyqt6_compat

Pyqt6 compat
This commit is contained in:
Ogi Moore 2021-01-22 17:42:36 -08:00 committed by GitHub
commit 8670407779
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 1665 additions and 366 deletions

View File

@ -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"

View File

@ -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
-------

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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"))

View File

@ -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

View File

@ -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
@ -158,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.
@ -171,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
@ -197,35 +191,35 @@ 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 int(ev.buttons()) != 0:
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
## 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):
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()
@ -241,24 +235,24 @@ 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 = []
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))
@ -270,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)
@ -312,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):
@ -350,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:
@ -395,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)

View File

@ -140,4 +140,4 @@ class ExportDialog(QtGui.QWidget):
def closeEvent(self, event):
self.close()
QtGui.QWidget.closeEvent(self, event)
super().closeEvent(event)

View File

@ -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

View File

@ -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 "<MouseDragEvent (%g,%g)->(%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 "<MouseDragEvent (%g,%g)->(%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 "<MouseClickEvent (%g,%g) button=%d>" % (p.x(), p.y(), int(self.button()))
return "<MouseClickEvent (%g,%g) button=%s>" % (p.x(), p.y(), str(self.button()))
except:
return "<MouseClickEvent button=%d>" % (int(self.button()))
return "<MouseClickEvent button=%s>" % (str(self.button()))
def time(self):
return self._time
@ -362,7 +362,7 @@ class HoverEvent(object):
else:
lp = self.lastPos()
p = self.pos()
return "<HoverEvent (%g,%g)->(%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 "<HoverEvent (%g,%g)->(%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.

View File

@ -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,67 @@ if QT_LIB in [PYQT4, PYQT5]:
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):
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

View File

@ -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):

View File

@ -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:

View File

@ -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

View File

@ -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"))

View File

@ -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):

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)
@ -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]))
@ -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):

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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():

View File

@ -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)

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -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):

View File

@ -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']
@ -21,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:

View File

@ -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()

View File

@ -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"))

View File

@ -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:
@ -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.
@ -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)
@ -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

View File

@ -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):

View File

@ -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))

View File

@ -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", "<html><head/><body><p>Links this axis with another view. When linked, both views will display the same data range.</p></body></html>"))
self.autoPercentSpin.setToolTip(_translate("Form", "<html><head/><body><p>Percent of data to be visible when auto-scaling. It may be useful to decrease this value for data with spiky noise.</p></body></html>"))
self.autoPercentSpin.setSuffix(_translate("Form", "%"))
self.autoRadio.setToolTip(_translate("Form", "<html><head/><body><p>Automatically resize this axis whenever the displayed data is changed.</p></body></html>"))
self.autoRadio.setText(_translate("Form", "Auto"))
self.manualRadio.setToolTip(_translate("Form", "<html><head/><body><p>Set the range for this axis manually. This disables automatic scaling. </p></body></html>"))
self.manualRadio.setText(_translate("Form", "Manual"))
self.minText.setToolTip(_translate("Form", "<html><head/><body><p>Minimum value to display for this axis.</p></body></html>"))
self.minText.setText(_translate("Form", "0"))
self.maxText.setToolTip(_translate("Form", "<html><head/><body><p>Maximum value to display for this axis.</p></body></html>"))
self.maxText.setText(_translate("Form", "0"))
self.invertCheck.setToolTip(_translate("Form", "<html><head/><body><p>Inverts the display of this axis. (+y points downward instead of upward)</p></body></html>"))
self.invertCheck.setText(_translate("Form", "Invert Axis"))
self.mouseCheck.setToolTip(_translate("Form", "<html><head/><body><p>Enables mouse interaction (panning, scaling) for this axis.</p></body></html>"))
self.mouseCheck.setText(_translate("Form", "Mouse Enabled"))
self.visibleOnlyCheck.setToolTip(_translate("Form", "<html><head/><body><p>When checked, the axis will only auto-scale to data that is visible along the orthogonal axis.</p></body></html>"))
self.visibleOnlyCheck.setText(_translate("Form", "Visible Data Only"))
self.autoPanCheck.setToolTip(_translate("Form", "<html><head/><body><p>When checked, the axis will automatically pan to center on the current data, but the scale along this axis will not change.</p></body></html>"))
self.autoPanCheck.setText(_translate("Form", "Auto Pan Only"))

View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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
@ -157,11 +158,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 +329,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,20 +352,21 @@ 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:
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()
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)
@ -373,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
QtGui.QGraphicsView.mouseMoveEvent(self, ev)
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

View File

@ -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):
@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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
@ -12,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):
"""
@ -114,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
@ -148,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)"""
@ -243,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()
@ -275,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)

View File

@ -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):

View File

@ -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()

View File

@ -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):

View File

@ -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: