Fix some bugs in PyQt5

This commit is contained in:
compass 2015-01-17 00:21:33 +08:00
parent 100308a33a
commit 478a3b1aa4
13 changed files with 71 additions and 37 deletions

View File

@ -8,6 +8,8 @@ import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore from pyqtgraph.Qt import QtGui, QtCore
import numpy as np import numpy as np
#FIXME: When running on Qt5, not as perfect as on Qt4
win = pg.plot() win = pg.plot()
win.setWindowTitle('pyqtgraph example: FillBetweenItem') win.setWindowTitle('pyqtgraph example: FillBetweenItem')
win.setXRange(-10, 10) win.setXRange(-10, 10)

View File

@ -16,7 +16,7 @@ app = QtGui.QApplication([])
w = QtGui.QMainWindow() w = QtGui.QMainWindow()
w.show() w.show()
w.setWindowTitle('pyqtgraph example: GradientWidget') w.setWindowTitle('pyqtgraph example: GradientWidget')
w.resize(400,400) w.setGeometry(10, 50, 400, 400)
cw = QtGui.QWidget() cw = QtGui.QWidget()
w.setCentralWidget(cw) w.setCentralWidget(cw)

View File

@ -11,6 +11,8 @@ import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui from pyqtgraph.Qt import QtCore, QtGui
import numpy as np import numpy as np
app = QtGui.QApplication([])
# win.setWindowTitle('pyqtgraph example: ____') # win.setWindowTitle('pyqtgraph example: ____')
## Start Qt event loop unless running in interactive mode or using pyside. ## Start Qt event loop unless running in interactive mode or using pyside.

View File

@ -1,4 +1,4 @@
from ..Qt import QtCore, QtGui, USE_PYSIDE from ..Qt import QtCore, QtGui, USE_PYSIDE, USE_PYQT5
from .. import exporters as exporters from .. import exporters as exporters
from .. import functions as fn from .. import functions as fn
from ..graphicsItems.ViewBox import ViewBox from ..graphicsItems.ViewBox import ViewBox
@ -6,6 +6,8 @@ from ..graphicsItems.PlotItem import PlotItem
if USE_PYSIDE: if USE_PYSIDE:
from . import exportDialogTemplate_pyside as exportDialogTemplate from . import exportDialogTemplate_pyside as exportDialogTemplate
elif USE_PYQT5:
from . import exportDialogTemplate_pyqt5 as exportDialogTemplate
else: else:
from . import exportDialogTemplate_pyqt as exportDialogTemplate from . import exportDialogTemplate_pyqt as exportDialogTemplate

View File

@ -20,7 +20,7 @@ QT_LIB = None
## Automatically determine whether to use PyQt or PySide. ## Automatically determine whether to use PyQt or PySide.
## This is done by first checking to see whether one of the libraries ## 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. ## is already imported. If not, then attempt to import PyQt4, then PySide.
libOrder = [PYQT4, PYSIDE, PYQT5] libOrder = [PYQT5, PYQT4, PYSIDE]
for lib in libOrder: for lib in libOrder:
if lib in sys.modules: if lib in sys.modules:
@ -172,6 +172,8 @@ if QT_LIB.startswith('PyQt'):
## Make sure we have Qt >= 4.7 ## Make sure we have Qt >= 4.7
versionReq = [4, 7] versionReq = [4, 7]
USE_PYSIDE = QT_LIB == PYSIDE # for backward compatibility USE_PYSIDE = QT_LIB == PYSIDE # for backward compatibility
USE_PYQT5 = QT_LIB == PYQT5 # for backward compatibility
USE_PYQT4 = QT_LIB == PYQT4 # for backward compatibility
QtVersion = PySide.QtCore.__version__ if QT_LIB == PYSIDE else QtCore.QT_VERSION_STR QtVersion = PySide.QtCore.__version__ if QT_LIB == PYSIDE else QtCore.QT_VERSION_STR
m = re.match(r'(\d+)\.(\d+).*', QtVersion) m = re.match(r'(\d+)\.(\d+).*', QtVersion)
if m is not None and list(map(int, m.groups())) < versionReq: if m is not None and list(map(int, m.groups())) < versionReq:

View File

@ -8,7 +8,7 @@ This class addresses the problem of having to save and restore the state
of a large group of widgets. of a large group of widgets.
""" """
from .Qt import QtCore, QtGui from .Qt import QtCore, QtGui, USE_PYQT5
import weakref, inspect import weakref, inspect
from .python2_3 import asUnicode from .python2_3 import asUnicode
@ -219,7 +219,9 @@ class WidgetGroup(QtCore.QObject):
v2 = self.readWidget(w) v2 = self.readWidget(w)
if v1 != v2: if v1 != v2:
#print "widget", n, " = ", v2 #print "widget", n, " = ", v2
self.emit(QtCore.SIGNAL('changed'), self.widgetList[w], v2) if not USE_PYQT5:
#I don't think this line have any different from the next line
self.emit(QtCore.SIGNAL('changed'), self.widgetList[w], v2)
self.sigChanged.emit(self.widgetList[w], v2) self.sigChanged.emit(self.widgetList[w], v2)
def state(self): def state(self):

View File

@ -1,8 +1,10 @@
from ..Qt import QtCore, QtGui, USE_PYSIDE from ..Qt import QtCore, QtGui, USE_PYSIDE, USE_PYQT5
import sys, re, os, time, traceback, subprocess import sys, re, os, time, traceback, subprocess
if USE_PYSIDE: if USE_PYSIDE:
from . import template_pyside as template from . import template_pyside as template
elif USE_PYQT5:
from . import template_pyqt5 as template
else: else:
from . import template_pyqt as template from . import template_pyqt as template

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from ..Qt import QtCore, QtGui, USE_PYSIDE from ..Qt import QtCore, QtGui, USE_PYSIDE, USE_PYQT5
from .Node import * from .Node import *
from ..pgcollections import OrderedDict from ..pgcollections import OrderedDict
from ..widgets.TreeWidget import * from ..widgets.TreeWidget import *
@ -9,6 +9,9 @@ from .. import FileDialog, DataTreeWidget
if USE_PYSIDE: if USE_PYSIDE:
from . import FlowchartTemplate_pyside as FlowchartTemplate from . import FlowchartTemplate_pyside as FlowchartTemplate
from . import FlowchartCtrlTemplate_pyside as FlowchartCtrlTemplate from . import FlowchartCtrlTemplate_pyside as FlowchartCtrlTemplate
elif USE_PYQT5:
from . import FlowchartTemplate_pyqt5 as FlowchartTemplate
from . import FlowchartCtrlTemplate_pyqt5 as FlowchartCtrlTemplate
else: else:
from . import FlowchartTemplate_pyqt as FlowchartTemplate from . import FlowchartTemplate_pyqt as FlowchartTemplate
from . import FlowchartCtrlTemplate_pyqt as FlowchartCtrlTemplate from . import FlowchartCtrlTemplate_pyqt as FlowchartCtrlTemplate
@ -648,7 +651,10 @@ class FlowchartCtrlWidget(QtGui.QWidget):
self.cwWin.resize(1000,800) self.cwWin.resize(1000,800)
h = self.ui.ctrlList.header() h = self.ui.ctrlList.header()
h.setResizeMode(0, h.Stretch) if not USE_PYQT5:
h.setResizeMode(0, h.Stretch)
else:
h.setSectionResizeMode(0, h.Stretch)
self.ui.ctrlList.itemChanged.connect(self.itemChanged) self.ui.ctrlList.itemChanged.connect(self.itemChanged)
self.ui.loadBtn.clicked.connect(self.loadClicked) self.ui.loadBtn.clicked.connect(self.loadClicked)

View File

@ -1,4 +1,4 @@
from ..Qt import QtGui from ..Qt import QtGui, USE_PYQT5, USE_PYQT4, USE_PYSIDE
from .. import functions as fn from .. import functions as fn
from .PlotDataItem import PlotDataItem from .PlotDataItem import PlotDataItem
from .PlotCurveItem import PlotCurveItem from .PlotCurveItem import PlotCurveItem
@ -14,23 +14,23 @@ class FillBetweenItem(QtGui.QGraphicsPathItem):
self.setCurves(curve1, curve2) self.setCurves(curve1, curve2)
elif curve1 is not None or curve2 is not None: elif curve1 is not None or curve2 is not None:
raise Exception("Must specify two curves to fill between.") raise Exception("Must specify two curves to fill between.")
if brush is not None: if brush is not None:
self.setBrush(fn.mkBrush(brush)) self.setBrush(fn.mkBrush(brush))
self.updatePath() self.updatePath()
def setCurves(self, curve1, curve2): def setCurves(self, curve1, curve2):
"""Set the curves to fill between. """Set the curves to fill between.
Arguments must be instances of PlotDataItem or PlotCurveItem.""" Arguments must be instances of PlotDataItem or PlotCurveItem."""
if self.curves is not None: if self.curves is not None:
for c in self.curves: for c in self.curves:
try: try:
c.sigPlotChanged.disconnect(self.curveChanged) c.sigPlotChanged.disconnect(self.curveChanged)
except (TypeError, RuntimeError): except (TypeError, RuntimeError):
pass pass
curves = [curve1, curve2] curves = [curve1, curve2]
for c in curves: for c in curves:
if not isinstance(c, PlotDataItem) and not isinstance(c, PlotCurveItem): if not isinstance(c, PlotDataItem) and not isinstance(c, PlotCurveItem):
@ -40,7 +40,7 @@ class FillBetweenItem(QtGui.QGraphicsPathItem):
curve2.sigPlotChanged.connect(self.curveChanged) curve2.sigPlotChanged.connect(self.curveChanged)
self.setZValue(min(curve1.zValue(), curve2.zValue())-1) self.setZValue(min(curve1.zValue(), curve2.zValue())-1)
self.curveChanged() self.curveChanged()
def setBrush(self, *args, **kwds): def setBrush(self, *args, **kwds):
"""Change the fill brush. Acceps the same arguments as pg.mkBrush()""" """Change the fill brush. Acceps the same arguments as pg.mkBrush()"""
QtGui.QGraphicsPathItem.setBrush(self, fn.mkBrush(*args, **kwds)) QtGui.QGraphicsPathItem.setBrush(self, fn.mkBrush(*args, **kwds))
@ -58,13 +58,14 @@ class FillBetweenItem(QtGui.QGraphicsPathItem):
paths.append(c.curve.getPath()) paths.append(c.curve.getPath())
elif isinstance(c, PlotCurveItem): elif isinstance(c, PlotCurveItem):
paths.append(c.getPath()) paths.append(c.getPath())
path = QtGui.QPainterPath() path = QtGui.QPainterPath()
p1 = paths[0].toSubpathPolygons() transform = QtGui.QTransform()
p2 = paths[1].toReversed().toSubpathPolygons() p1 = paths[0].toSubpathPolygons(transform)
p2 = paths[1].toReversed().toSubpathPolygons(transform)
if len(p1) == 0 or len(p2) == 0: if len(p1) == 0 or len(p2) == 0:
self.setPath(QtGui.QPainterPath()) self.setPath(QtGui.QPainterPath())
return return
path.addPolygon(p1[0] + p2[0]) path.addPolygon(p1[0] + p2[0])
self.setPath(path) self.setPath(path)

View File

@ -116,16 +116,20 @@ class TickSliderItem(GraphicsWidget):
self.resetTransform() self.resetTransform()
ort = orientation ort = orientation
if ort == 'top': if ort == 'top':
self.scale(1, -1) transform = QtGui.QTransform.fromScale(1, -1)
self.translate(0, -self.height()) transform.translate(0, -self.height())
self.setTransform(transform)
elif ort == 'left': elif ort == 'left':
self.rotate(270) transform = QtGui.QTransform()
self.scale(1, -1) transform.rotate(270)
self.translate(-self.height(), -self.maxDim) transform.scale(1, -1)
transform.translate(-self.height(), -self.maxDim)
self.setTransform(transform)
elif ort == 'right': elif ort == 'right':
self.rotate(270) transform = QtGui.QTransform()
self.translate(-self.height(), 0) transform.rotate(270)
#self.setPos(0, -self.height()) transform.translate(-self.height(), 0)
self.setTransform(transform)
elif ort != 'bottom': elif ort != 'bottom':
raise Exception("%s is not a valid orientation. Options are 'left', 'right', 'top', and 'bottom'" %str(ort)) raise Exception("%s is not a valid orientation. Options are 'left', 'right', 'top', and 'bottom'" %str(ort))
@ -237,7 +241,7 @@ class TickSliderItem(GraphicsWidget):
self.addTick(pos.x()/self.length) self.addTick(pos.x()/self.length)
elif ev.button() == QtCore.Qt.RightButton: elif ev.button() == QtCore.Qt.RightButton:
self.showMenu(ev) self.showMenu(ev)
#if ev.button() == QtCore.Qt.RightButton: #if ev.button() == QtCore.Qt.RightButton:
#if self.moving: #if self.moving:
#ev.accept() #ev.accept()
@ -781,11 +785,15 @@ class GradientEditorItem(TickSliderItem):
self.updateGradient() self.updateGradient()
self.sigGradientChangeFinished.emit(self) self.sigGradientChangeFinished.emit(self)
class Tick(QtGui.QGraphicsObject): ## NOTE: Making this a subclass of GraphicsObject instead results in class Tick(QtGui.QGraphicsWidget): ## NOTE: Making this a subclass of GraphicsObject instead results in
## activating this bug: https://bugreports.qt-project.org/browse/PYSIDE-86 ## activating this bug: https://bugreports.qt-project.org/browse/PYSIDE-86
## private class ## private class
# When making Tick a subclass of QtGui.QGraphicsObject as origin,
# ..GraphicsScene.items(self, *args) will get Tick object as a
# class of QtGui.QMultimediaWidgets.QGraphicsVideoItem in python2.7-PyQt5(5.4.0)
sigMoving = QtCore.Signal(object) sigMoving = QtCore.Signal(object)
sigMoved = QtCore.Signal(object) sigMoved = QtCore.Signal(object)

View File

@ -1008,7 +1008,7 @@ class ROI(GraphicsObject):
#print " dataBounds:", dataBounds #print " dataBounds:", dataBounds
## Intersect transformed ROI bounds with data bounds ## Intersect transformed ROI bounds with data bounds
intBounds = dataBounds.intersect(QtCore.QRectF(0, 0, dShape[0], dShape[1])) intBounds = dataBounds.intersected(QtCore.QRectF(0, 0, dShape[0], dShape[1]))
#print " intBounds:", intBounds #print " intBounds:", intBounds
## Determine index values to use when referencing the array. ## Determine index values to use when referencing the array.

View File

@ -1,4 +1,4 @@
from ..Qt import QtGui, QtCore, USE_PYSIDE from ..Qt import QtGui, QtCore, USE_PYSIDE, USE_PYQT5
from ..Point import Point from ..Point import Point
from .. import functions as fn from .. import functions as fn
from .GraphicsItem import GraphicsItem from .GraphicsItem import GraphicsItem
@ -752,7 +752,7 @@ class ScatterPlotItem(GraphicsObject):
self.data['targetRect'][updateMask] = list(imap(QtCore.QRectF, updatePts[0,:], updatePts[1,:], width, width)) self.data['targetRect'][updateMask] = list(imap(QtCore.QRectF, updatePts[0,:], updatePts[1,:], width, width))
data = self.data[viewMask] data = self.data[viewMask]
if USE_PYSIDE: if USE_PYSIDE or USE_PYQT5:
list(imap(p.drawPixmap, data['targetRect'], repeat(atlas), data['sourceRect'])) list(imap(p.drawPixmap, data['targetRect'], repeat(atlas), data['sourceRect']))
else: else:
p.drawPixmapFragments(data['targetRect'].tolist(), data['sourceRect'].tolist(), atlas) p.drawPixmapFragments(data['targetRect'].tolist(), data['sourceRect'].tolist(), atlas)

View File

@ -1,4 +1,4 @@
from ..Qt import QtCore, QtGui, QtOpenGL from ..Qt import QtCore, QtGui, QtOpenGL, USE_PYQT5
from OpenGL.GL import * from OpenGL.GL import *
import OpenGL.GL.framebufferobjects as glfbo import OpenGL.GL.framebufferobjects as glfbo
import numpy as np import numpy as np
@ -323,10 +323,17 @@ class GLViewWidget(QtOpenGL.QGLWidget):
def wheelEvent(self, ev): def wheelEvent(self, ev):
if (ev.modifiers() & QtCore.Qt.ControlModifier): delta = 0
self.opts['fov'] *= 0.999**ev.delta() if not USE_PYQT5:
delta = ev.delta()
else: else:
self.opts['distance'] *= 0.999**ev.delta() delta = ev.angleDelta().x()
if delta == 0:
delta = ev.angleDelta().y()
if (ev.modifiers() & QtCore.Qt.ControlModifier):
self.opts['fov'] *= 0.999**delta
else:
self.opts['distance'] *= 0.999**delta
self.update() self.update()
def keyPressEvent(self, ev): def keyPressEvent(self, ev):