1#!/usr/bin/env python 2 3 4############################################################################# 5## 6## Copyright (C) 2013 Riverbank Computing Limited. 7## All rights reserved. 8## 9## This file is part of the examples of PyQt. 10## 11## You may use this file under the terms of the BSD license as follows: 12## 13## "Redistribution and use in source and binary forms, with or without 14## modification, are permitted provided that the following conditions are 15## met: 16## * Redistributions of source code must retain the above copyright 17## notice, this list of conditions and the following disclaimer. 18## * Redistributions in binary form must reproduce the above copyright 19## notice, this list of conditions and the following disclaimer in 20## the documentation and/or other materials provided with the 21## distribution. 22## * Neither the name of Riverbank Computing Limited nor the names of 23## its contributors may be used to endorse or promote products 24## derived from this software without specific prior written 25## permission. 26## 27## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 38## 39############################################################################# 40 41 42from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot 43from PyQt5.QtWidgets import QApplication, QTextEdit 44 45 46# The purpose of this class is to show that Designer's property editor shows 47# all Python classes in the hierarchy that define properties. 48class PyTextViewer(QTextEdit): 49 50 # Initialise the instance. 51 def __init__(self, parent=None): 52 super(PyTextViewer, self).__init__(parent) 53 54 self.setReadOnly(True) 55 56 # Initialise the author property by calling it's reset function. 57 self.resetAuthor() 58 59 # The getter for the author property. Note that we cannot follow the Qt 60 # naming convention (ie. by using the naming the getter "author") because 61 # it would conflict with the property name. 62 def getAuthor(self): 63 return self._author 64 65 # The setter for the author property. 66 def setAuthor(self, name): 67 self._author = name 68 69 # The resetter for the author property. Only Qt Designer uses this. Qt 70 # Designer does not use the deleter function of the property. 71 def resetAuthor(self): 72 self._author = "David Boddie" 73 74 # Define the author property. This will look like a C++ property to Qt 75 # Designer and a Python property to Python. 76 author = pyqtProperty(str, getAuthor, setAuthor, resetAuthor) 77 78 79# This is the class that implements the custom widget. 80class PyDemo(PyTextViewer): 81 82 # Define the Qt signals as a sequence of C++ function signatures excluding 83 # the return type. These may be connected to other signals or slots in Qt 84 # Designer. 85 zoomChanged = pyqtSignal(int) 86 87 # Initialise the instance. 88 def __init__(self, parent=None): 89 super(PyDemo, self).__init__(parent) 90 91 self.setWindowTitle("PyQt Demonstration Widget") 92 self.setText(_demo_text) 93 94 # Initialise the zoom property. We don't just call the resetter 95 # because it assumes that this has already been initialised. 96 self._zoom = 0 97 98 # The getter for the zoom property. 99 def getZoom(self): 100 return self._zoom 101 102 # The setter for the zoom property. We also make define this as a Qt slot 103 # which can be connected to Qt signals in Qt Designer. 104 @pyqtSlot(int) 105 def setZoom(self, zoom): 106 # Don't do anything if nothing has changed. 107 if self._zoom == zoom: 108 return 109 110 # Zoom in or out according to the relative zoom levels. 111 if self._zoom < zoom: 112 self.zoomIn(zoom - self._zoom) 113 elif self._zoom > zoom: 114 self.zoomOut(self._zoom - zoom) 115 116 # Remember the new zoom level. 117 self._zoom = zoom 118 119 # Emit the Qt signal to say that the zoom level has changed. 120 self.zoomChanged.emit(zoom) 121 122 # The resetter for the zoom property. 123 def resetZoom(self): 124 self.setZoom(0) 125 126 # Define the zoom property. Changing the value of this in Qt Designer's 127 # property editor causes the zoom level to change dynamically. 128 zoom = pyqtProperty(int, getZoom, setZoom, resetZoom) 129 130 131# The text displayed in the custom widget. 132_demo_text = """<h3>PyQt Demonstration Widget</h3> 133<p>This simple example demonstrates the following features.</p> 134<ul> 135 <li>The definition of properties that behave as C++ properties to Qt and 136 Python properties to Python.</li> 137 <li>The definition of new Qt signals that can be connected to other signals 138 and Qt slots in Designer.</li> 139 <li>The definition of new Qt slots that can be connected to signals in 140 Designer.</li> 141</ul> 142""" 143 144 145# Display the custom widget if the script is being run directly from the 146# command line. 147if __name__ == "__main__": 148 149 import sys 150 151 app = QApplication(sys.argv) 152 153 demo = PyDemo() 154 demo.show() 155 156 sys.exit(app.exec_()) 157