EventFilterDemo.py :  » GUI » PyQwt » PyQwt-5.2.0 » qt4examples » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » PyQwt 
PyQwt » PyQwt 5.2.0 » qt4examples » EventFilterDemo.py
#!/usr/bin/env python

# The Python version of qwt-*/examples/event_filter


import sys
from PyQt4 import Qt
import PyQt4.Qwt5 as Qwt
from PyQt4.Qwt5.anynumpy import *


class ColorBar(Qt.QWidget):

    def __init__(self, orientation, *args):
        Qt.QWidget.__init__(self, *args)
        self.__orientation = orientation
        self.__light = Qt.QColor(Qt.Qt.white)
        self.__dark = Qt.QColor(Qt.Qt.black)
        self.setCursor(Qt.Qt.PointingHandCursor)

    # __init__()
    
    def setOrientation(self, orientation):
        self.__orientation = orientation
        self.update()

    # setOrientation()
    
    def orientation(self):
        return self.__orientation

    # orientation()
    
    def setRange(self, light, dark):
        self.__light = light
        self.__dark = dark
        self.update()

    # setRange()
    
    def setLight(self, color):
        self.__light = color
        self.update()

    # setLight()
    
    def setDark(self, color):
        self.__dark = color
        self.update()

    # setDark()
    
    def light(self):
        return self.__light

    # light()
    
    def dark(self):
        return self.__dark

    # dark()
    
    def mousePressEvent(self, event):
        if event.button() == Qt.Qt.LeftButton:
            pm = Qt.QPixmap.grabWidget(self)
            color = Qt.QColor()
            color.setRgb(pm.toImage().pixel(event.x(), event.y()))
            self.emit(Qt.SIGNAL("colorSelected"), color)
            event.accept()

    # mousePressEvent()

    def paintEvent(self, _):
        painter = Qt.QPainter(self)
        self.drawColorBar(painter, self.rect())

    # paintEvent()

    def drawColorBar(self, painter, rect):
        h1, s1, v1, _ = self.__light.getHsv()
        h2, s2, v2, _ = self.__dark.getHsv()

        painter.save()
        painter.setClipRect(rect)
        painter.setClipping(True)
        painter.fillRect(rect, Qt.QBrush(self.__dark))
        sectionSize = 2
        if (self.__orientation == Qt.Qt.Horizontal):
            numIntervalls = rect.width()/sectionSize
        else:
            numIntervalls = rect.height()/sectionSize
        section = Qt.QRect()
        for i in range(numIntervalls):
            if self.__orientation == Qt.Qt.Horizontal:
                section.setRect(rect.x() + i*sectionSize, rect.y(),
                                sectionSize, rect.heigh())
            else:
                section.setRect(rect.x(), rect.y() + i*sectionSize,
                                rect.width(), sectionSize)
            ratio = float(i)/float(numIntervalls)
            color = Qt.QColor()
            color.setHsv(h1 + int(ratio*(h2-h1) + 0.5),
                         s1 + int(ratio*(s2-s1) + 0.5),
                         v1 + int(ratio*(v2-v1) + 0.5))
            
            painter.fillRect(section, color)

        painter.restore()

    # drawColorBar()

# class ColorBar


class Plot(Qwt.QwtPlot):

    def __init__(self, *args):
        Qwt.QwtPlot.__init__(self, *args)

        self.setTitle("Interactive Plot")
        
        self.setCanvasColor(Qt.Qt.darkCyan)

        grid = Qwt.QwtPlotGrid()
        grid.attach(self)
        grid.setMajPen(Qt.QPen(Qt.Qt.white, 0, Qt.Qt.DotLine))
        
        self.setAxisScale(Qwt.QwtPlot.xBottom, 0.0, 100.0)
        self.setAxisScale(Qwt.QwtPlot.yLeft, 0.0, 100.0)

        # Avoid jumping when label with 3 digits
        # appear/disappear when scrolling vertically
        scaleDraw = self.axisScaleDraw(Qwt.QwtPlot.yLeft)
        scaleDraw.setMinimumExtent(scaleDraw.extent(
            Qt.QPen(), self.axisWidget(Qwt.QwtPlot.yLeft).font()))

        self.plotLayout().setAlignCanvasToScales(True)

        self.__insertCurve(Qt.Qt.Vertical, Qt.Qt.blue, 30.0)
        self.__insertCurve(Qt.Qt.Vertical, Qt.Qt.magenta, 70.0)
        self.__insertCurve(Qt.Qt.Horizontal, Qt.Qt.yellow, 30.0)
        self.__insertCurve(Qt.Qt.Horizontal, Qt.Qt.white, 70.0)
        
        self.replot()

        scaleWidget = self.axisWidget(Qwt.QwtPlot.yLeft)
        scaleWidget.setMargin(10)

        self.__colorBar = ColorBar(Qt.Qt.Vertical, scaleWidget)
        self.__colorBar.setRange(
            Qt.QColor(Qt.Qt.red), Qt.QColor(Qt.Qt.darkBlue))
        self.__colorBar.setFocusPolicy(Qt.Qt.TabFocus)

        self.connect(self.__colorBar,
                     Qt.SIGNAL('colorSelected'),
                     self.setCanvasColor)
        
        # we need the resize events, to lay out the color bar
        scaleWidget.installEventFilter(self)

        self.__wheel = Qwt.QwtWheel(self.canvas())
        self.__wheel.setOrientation(Qt.Qt.Vertical)
        self.__wheel.setRange(-100, 100)
        self.__wheel.setValue(0.0)
        self.__wheel.setMass(0.2)
        self.__wheel.setTotalAngle(4 * 360.0)

        self.connect(self.__wheel,
                     Qt.SIGNAL('valueChanged(double)'),
                     self.scrollLeftAxis)

        # we need the resize events, to lay out the wheel
        self.canvas().installEventFilter(self)

        scaleWidget.setWhatsThis(
            'Selecting a value at the scale will insert a new curve.')
        self.__colorBar.setWhatsThis(
            'Selecting a color will change the background of the plot.')
        self.__wheel.setWhatsThis(
            'With the wheel you can move the visible area.')
        self.axisWidget(Qwt.QwtPlot.xBottom).setWhatsThis(
            'Selecting a value at the scale will insert a new curve.')

    # __init__()
    
    def setCanvasColor(self, color):
        self.setCanvasBackground(color)
        self.replot()

    # setCanvasColor()

    def scrollLeftAxis(self, value):
        self.setAxisScale(Qwt.QwtPlot.yLeft, value, value + 100)
        self.replot()

    # scrollLeftAxis()

    def eventFilter(self, object, event):
        if event.type() == Qt.QEvent.Resize:
            size = event.size()
            if object == self.axisWidget(Qwt.QwtPlot.yLeft):
                margin = 2
                x = size.width() - object.margin() + margin
                w = object.margin() - 2 * margin
                y = object.startBorderDist()
                h = (size.height()
                     - object.startBorderDist() - object.endBorderDist())
                self.__colorBar.setGeometry(x, y, w, h)
            elif object == self.canvas():
                w, h, margin = 16, 50, 2
                r = object.contentsRect();
                self.__wheel.setGeometry(
                    r.right() - margin - w, r.center().y() - h / 2, w, h)

        return Qwt.QwtPlot.eventFilter(self, object, event)

    # eventFilter()

    def insertCurve(self, axis, base):
        if axis == Qwt.QwtPlot.yLeft or axis == Qwt.QwtPlot.yRight:
            o = Qt.Qt.Horizontal
        else:
            o = Qt.Qt.Vertical
            
        self.__insertCurve(o, Qt.QColor(Qt.Qt.red), base)
        self.replot()

    # insertCurve()

    def __insertCurve(self, orientation, color, base):
        curve = Qwt.QwtPlotCurve()
        curve.attach(self)

        curve.setPen(Qt.QPen(color))
        curve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse,
                                      Qt.QBrush(Qt.Qt.gray),
                                      Qt.QPen(color),
                                      Qt.QSize(8, 8)))

        fixed = base*ones(10, Float)
        changing = arange(0, 95.0, 10.0, Float) + 5.0
        if orientation == Qt.Qt.Horizontal:
            curve.setData(changing, fixed)
        else:
            curve.setData(fixed, changing)

    # __insertCurve()

# class Plot


class CanvasPicker(Qt.QObject):
    
    def __init__(self, plot):
        Qt.QObject.__init__(self, plot)
        self.__selectedCurve = None
        self.__selectedPoint = -1
        self.__plot = plot

        canvas = plot.canvas()
        canvas.installEventFilter(self)
        
        # We want the focus, but no focus rect.
        # The selected point will be highlighted instead.
        canvas.setFocusPolicy(Qt.Qt.StrongFocus)
        canvas.setCursor(Qt.Qt.PointingHandCursor)
        canvas.setFocusIndicator(Qwt.QwtPlotCanvas.ItemFocusIndicator)
        canvas.setFocus()
        
        canvas.setWhatsThis(
            'All points can be moved using the left mouse button '
            'or with these keys:\n\n'
            '- Up: Select next curve\n'
            '- Down: Select previous curve\n'
            '- Left, "-": Select next point\n'
            '- Right, "+": Select previous point\n'
            '- 7, 8, 9, 4, 6, 1, 2, 3: Move selected point'
            )

        self.__shiftCurveCursor(True)

    # __init__()

    def event(self, event):
        if event.type() == Qt.QEvent.User:
            self.__showCursor(True)
            return True
        return Qt.QObject.event(event)

    # event()
    
    def eventFilter(self, object, event):
        
        if event.type() == Qt.QEvent.FocusIn:
            self.__showCursor(True)
        if event.type() == Qt.QEvent.FocusOut:
            self.__showCursor(False)
         
        if event.type() == Qt.QEvent.Paint:
            Qt.QApplication.postEvent(
                self, Qt.QEvent(Qt.QEvent.User))
        elif event.type() == Qt.QEvent.MouseButtonPress:
            self.__select(event.pos())
            return True
        elif event.type() == Qt.QEvent.MouseMove:
            self.__move(event.pos())
            return True

        if event.type() == Qt.QEvent.KeyPress:
            delta = 5
            key = event.key()
            if key == Qt.Qt.Key_Up:
                self.__shiftCurveCursor(True)
                return True
            elif key == Qt.Qt.Key_Down:
                self.__shiftCurveCursor(False)
                return True
            elif key == Qt.Qt.Key_Right or key == Qt.Qt.Key_Plus:
                if self.__selectedCurve:
                    self.__shiftPointCursor(True)
                else:
                    self.__shiftCurveCursor(True)
                return True
            elif key == Qt.Qt.Key_Left or key == Qt.Qt.Key_Minus:
                if self.__selectedCurve:
                    self.__shiftPointCursor(False)
                else:
                    self.__shiftCurveCursor(True)
                return True

            if key == Qt.Qt.Key_1:
                self.__moveBy(-delta, delta)
            elif key == Qt.Qt.Key_2:
                self.__moveBy(0, delta)
            elif key == Qt.Qt.Key_3:
                self.__moveBy(delta, delta)
            elif key == Qt.Qt.Key_4:
                self.__moveBy(-delta, 0)
            elif key == Qt.Qt.Key_6:
                self.__moveBy(delta, 0)
            elif key == Qt.Qt.Key_7:
                self.__moveBy(-delta, -delta)
            elif key == Qt.Qt.Key_8:
                self.__moveBy(0, -delta)
            elif key == Qt.Qt.Key_9:
                self.__moveBy(delta, -delta)
        
        return Qwt.QwtPlot.eventFilter(self, object, event)

    # eventFilter()

    def __select(self, pos):
        found, distance, point = None, 1e100, -1

        for curve in self.__plot.itemList():
            if isinstance(curve, Qwt.QwtPlotCurve):
                i, d = curve.closestPoint(pos)
                if d < distance:
                    found = curve
                    point = i
                    distance = d

        self.__showCursor(False)
        self.__selectedCurve = None
        self.__selectedPoint = -1

        if found and distance < 10:
            self.__selectedCurve = found
            self.__selectedPoint = point
            self.__showCursor(True)

    # __select()

    def __moveBy(self, dx, dy):
        if dx == 0 and dy == 0:
            return

        curve = self.__selectedCurve
        if not curve:
            return

        x = self.__plot.transform(
            curve.xAxis(), curve.x(self.__selectedPoint)) + dx
        y = self.__plot.transform(
            curve.yAxis(), curve.y(self.__selectedPoint)) + dy
        self.__move(Qt.QPoint(x, y))

    # __moveBy()

    def __move(self, pos):
        curve = self.__selectedCurve
        if not curve:
            return

        xData = zeros(curve.dataSize(), Float)
        yData = zeros(curve.dataSize(), Float)

        for i in range(curve.dataSize()):
            if i == self.__selectedPoint:
                xData[i] = self.__plot.invTransform(curve.xAxis(), pos.x())
                yData[i] = self.__plot.invTransform(curve.yAxis(), pos.y())
            else:
                xData[i] = curve.x(i)
                yData[i] = curve.y(i)
            
        curve.setData(xData, yData)
        self.__plot.replot()
        self.__showCursor(True)

    # __move()

    def __showCursor(self, showIt):
        curve = self.__selectedCurve
        if not curve:
            return

        # Use copy constructors to defeat the reference semantics.
        symbol = Qwt.QwtSymbol(curve.symbol())
        newSymbol = Qwt.QwtSymbol(symbol)
        if showIt:
            newSymbol.setBrush(symbol.brush().color().dark(150))

        doReplot = self.__plot.autoReplot()

        self.__plot.setAutoReplot(False)
        curve.setSymbol(newSymbol)

        curve.draw(self.__selectedPoint, self.__selectedPoint)

        curve.setSymbol(symbol)
        self.__plot.setAutoReplot(doReplot)
        
    # __showCursor()
    
    def __shiftCurveCursor(self, up):
        curves = [curve for curve in self.__plot.itemList()
                  if isinstance(curve, Qwt.QwtPlotCurve)]

        if not curves:
            return

        if self.__selectedCurve in curves:
            index = curves.index(self.__selectedCurve)
            if up:
                index += 1
            else:
                index -= 1
            # keep index within [0, len(curves))
            index += len(curves)
            index %= len(curves)
        else:
            index = 0

        self.__showCursor(False)
        self.__selectedPoint = 0
        self.__selectedCurve = curves[index]
        self.__showCursor(True)

    # __shiftCurveCursor()

    def __shiftPointCursor(self, up):
        curve = self.__selectedCurve
        if not curve:
            return

        if up:
            index = self.__selectedPoint + 1
        else:
            index = self.__selectedPoint - 1
        # keep index within [0, curve.dataSize())
        index += curve.dataSize()
        index %= curve.dataSize()
        if index != self.__selectedPoint:
            self.__showCursor(False)
            self.__selectedPoint = index
            self.__showCursor(True)

    # __shiftPointCursor()
   
# class CanvasPicker


class ScalePicker(Qt.QObject):

    def __init__(self, plot):
        Qt.QObject.__init__(self, plot)
        for i in range(Qwt.QwtPlot.axisCnt):
            scaleWidget = plot.axisWidget(i)
            if scaleWidget:
                scaleWidget.installEventFilter(self)

    # __init__()

    def eventFilter(self, object, event):
        if (event.type() == Qt.QEvent.MouseButtonPress):
            self.__mouseClicked(object, event.pos())
            return True
        return Qt.QObject.eventFilter(self, object, event)

    # eventFilter()

    def __mouseClicked(self, scale, pos):
        rect = self.__scaleRect(scale)

        margin = 10
        rect.setRect(rect.x() - margin,
                     rect.y() - margin,
                     rect.width() + 2 * margin,
                     rect.height() +  2 * margin)

        if rect.contains(pos):
            value = 0.0
            axis = -1

        sd = scale.scaleDraw()
        if scale.alignment() == Qwt.QwtScaleDraw.LeftScale:
            value = sd.map().invTransform(pos.y())
            axis = Qwt.QwtPlot.yLeft
        elif scale.alignment() == Qwt.QwtScaleDraw.RightScale:
            value = sd.map().invTransform(pos.y())
            axis = Qwt.QwtPlot.yRight
        elif scale.alignment() == Qwt.QwtScaleDraw.BottomScale:
            value = sd.map().invTransform(pos.x())
            axis = Qwt.QwtPlot.xBottom
        elif scale.alignment() == Qwt.QwtScaleDraw.TopScale:
            value = sd.map().invTransform(pos.x())
            axis = Qwt.QwtPlot.xBottom

        self.emit(Qt.SIGNAL("clicked"), axis, value)

    # __mouseClicked()
 
    def __scaleRect(self, scale):
        bld = scale.margin()
        mjt = scale.scaleDraw().majTickLength()
        sbd = scale.startBorderDist()
        ebd = scale.endBorderDist()

        if scale.alignment() == Qwt.QwtScaleDraw.LeftScale:
            return Qt.QRect(scale.width() - bld - mjt, sbd,
                                mjt, scale.height() - sbd - ebd)
        elif scale.alignment() == Qwt.QwtScaleDraw.RightScale: 
            return Qt.QRect(bld, sbd,mjt, scale.height() - sbd - ebd)
        elif scale.alignment() == Qwt.QwtScaleDraw.BottomScale:
            return Qt.QRect(sbd, bld, scale.width() - sbd - ebd, mjt)
        elif scale.alignment() == Qwt.QwtScaleDraw.TopScale:
            return Qt.QRect(sbd, scale.height() - bld - mjt,
                                scale.width() - sbd - ebd, mjt)
        else:
            return Qt.QRect()

    # __scaleRect

# class ScalePicker


def make():
    demo = Qt.QMainWindow()

    toolBar = Qt.QToolBar(demo)
    toolBar.addAction(Qt.QWhatsThis.createAction(toolBar))
    demo.addToolBar(toolBar)

    plot = Plot(demo)
    demo.setCentralWidget(plot)
    plot.setWhatsThis(
        'An useless plot to demonstrate how to use event filtering.\n\n'
        'You can click on the color bar, the scales or move the slider.\n'
        'All points can be moved using the mouse or the keyboard.'
        )

    CanvasPicker(plot)
    scalePicker = ScalePicker(plot)
    Qt.QObject.connect(scalePicker,
                           Qt.SIGNAL("clicked"),
                           plot.insertCurve)

    demo.resize(540, 400)
    demo.show()
    return demo

# make()

def main(args):
    app = Qt.QApplication(args)
    demo = make()
    sys.exit(app.exec_())

# main()

# Admire!
if __name__ == '__main__':
    main(sys.argv)

# Local Variables: ***
# mode: python ***
# End: ***
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.