diff options
author | Cristian Maureira-Fredes <Cristian.Maureira-Fredes@qt.io> | 2021-02-05 10:07:19 +0100 |
---|---|---|
committer | Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> | 2021-02-09 07:43:07 +0000 |
commit | 33743aeb2be37d166bcc3291a98dd22026871cef (patch) | |
tree | cd45b08ef2a8c80e5e250e1050a41d8ece6fa199 /examples/widgets | |
parent | ad01b159e02067ba46d6433412cb1e690553e946 (diff) |
examples: directory structure
When generating the gallery automatically, the structure
of the examples was not the same for all the modules.
This reorganization was made under the following assumption:
An example requires:
- its own directory,
- a '.pyproject' file,
- one or more '.py' files,
- extra files (likes images, .rc, .ui, etc)
Even for cases when subdirectories are made to depict categories, like
'widgets/state-machine/...', one directory is required per example.
There should not be '.pyproject' files for categories,
except for the general 'examples.pyproject' to open all of them.
Task-number: PYSIDE-1490
Pick-to: 6.0
Change-Id: Ie690773c816a248016dbebaad90fbb1d1c2aeea5
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'examples/widgets')
65 files changed, 2512 insertions, 226 deletions
diff --git a/examples/widgets/codeeditor/codeeditor.pyproject b/examples/widgets/codeeditor/codeeditor.pyproject new file mode 100644 index 000000000..f51cfc6d2 --- /dev/null +++ b/examples/widgets/codeeditor/codeeditor.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["codeeditor.py", "main.py"] +} diff --git a/examples/widgets/dialogs/dialogs.pyproject b/examples/widgets/dialogs/dialogs.pyproject deleted file mode 100644 index 001fd141b..000000000 --- a/examples/widgets/dialogs/dialogs.pyproject +++ /dev/null @@ -1,4 +0,0 @@ -{ - "files": ["findfiles.py", "standarddialogs.py", "extension.py", - "trivialwizard.py"] -} diff --git a/examples/widgets/dialogs/extension.py b/examples/widgets/dialogs/extension/extension.py index 891e55533..891e55533 100644 --- a/examples/widgets/dialogs/extension.py +++ b/examples/widgets/dialogs/extension/extension.py diff --git a/examples/widgets/dialogs/extension/extension.pyproject b/examples/widgets/dialogs/extension/extension.pyproject new file mode 100644 index 000000000..e0f2ba73b --- /dev/null +++ b/examples/widgets/dialogs/extension/extension.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["extension.py"] +} diff --git a/examples/widgets/dialogs/findfiles.py b/examples/widgets/dialogs/findfiles/findfiles.py index 5e26f73ad..5e26f73ad 100644 --- a/examples/widgets/dialogs/findfiles.py +++ b/examples/widgets/dialogs/findfiles/findfiles.py diff --git a/examples/widgets/dialogs/findfiles/findfiles.pyproject b/examples/widgets/dialogs/findfiles/findfiles.pyproject new file mode 100644 index 000000000..c2fae6dff --- /dev/null +++ b/examples/widgets/dialogs/findfiles/findfiles.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["findfiles.py"] +} diff --git a/examples/widgets/dialogs/standarddialogs.py b/examples/widgets/dialogs/standarddialogs/standarddialogs.py index 5e0f80c4d..5e0f80c4d 100644 --- a/examples/widgets/dialogs/standarddialogs.py +++ b/examples/widgets/dialogs/standarddialogs/standarddialogs.py diff --git a/examples/widgets/dialogs/standarddialogs/standarddialogs.pyproject b/examples/widgets/dialogs/standarddialogs/standarddialogs.pyproject new file mode 100644 index 000000000..766902e3e --- /dev/null +++ b/examples/widgets/dialogs/standarddialogs/standarddialogs.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["standarddialogs.py"] +} diff --git a/examples/widgets/dialogs/trivialwizard.py b/examples/widgets/dialogs/trivialwizard/trivialwizard.py index 88b8e97b8..88b8e97b8 100644 --- a/examples/widgets/dialogs/trivialwizard.py +++ b/examples/widgets/dialogs/trivialwizard/trivialwizard.py diff --git a/examples/widgets/dialogs/trivialwizard/trivialwizard.pyproject b/examples/widgets/dialogs/trivialwizard/trivialwizard.pyproject new file mode 100644 index 000000000..739a43a7a --- /dev/null +++ b/examples/widgets/dialogs/trivialwizard/trivialwizard.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["trivialwizard.py"] +} diff --git a/examples/widgets/graphicsview/anchorlayout.py b/examples/widgets/graphicsview/anchorlayout/anchorlayout.py index 0b1ec0a03..0b1ec0a03 100644 --- a/examples/widgets/graphicsview/anchorlayout.py +++ b/examples/widgets/graphicsview/anchorlayout/anchorlayout.py diff --git a/examples/widgets/graphicsview/anchorlayout/anchorlayout.pyproject b/examples/widgets/graphicsview/anchorlayout/anchorlayout.pyproject new file mode 100644 index 000000000..49ed7b734 --- /dev/null +++ b/examples/widgets/graphicsview/anchorlayout/anchorlayout.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["anchorlayout.py"] +} diff --git a/examples/widgets/graphicsview/elasticnodes.py b/examples/widgets/graphicsview/elasticnodes/elasticnodes.py index 1eefdc0bb..1eefdc0bb 100644 --- a/examples/widgets/graphicsview/elasticnodes.py +++ b/examples/widgets/graphicsview/elasticnodes/elasticnodes.py diff --git a/examples/widgets/graphicsview/elasticnodes/elasticnodes.pyproject b/examples/widgets/graphicsview/elasticnodes/elasticnodes.pyproject new file mode 100644 index 000000000..f6083e795 --- /dev/null +++ b/examples/widgets/graphicsview/elasticnodes/elasticnodes.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["elasticnodes.py"] +} diff --git a/examples/widgets/graphicsview/graphicsview.pyproject b/examples/widgets/graphicsview/graphicsview.pyproject deleted file mode 100644 index 007d36bd2..000000000 --- a/examples/widgets/graphicsview/graphicsview.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["elasticnodes.py", "anchorlayout.py"] -} diff --git a/examples/widgets/itemviews/basicsortfiltermodel.py b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py index 845755cb9..845755cb9 100644 --- a/examples/widgets/itemviews/basicsortfiltermodel.py +++ b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py diff --git a/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.pyproject b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.pyproject new file mode 100644 index 000000000..3351bba88 --- /dev/null +++ b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["basicsortfiltermodel.py"] +} diff --git a/examples/widgets/itemviews/fetchmore.py b/examples/widgets/itemviews/fetchmore/fetchmore.py index c91874004..c91874004 100644 --- a/examples/widgets/itemviews/fetchmore.py +++ b/examples/widgets/itemviews/fetchmore/fetchmore.py diff --git a/examples/widgets/itemviews/fetchmore/fetchmore.pyproject b/examples/widgets/itemviews/fetchmore/fetchmore.pyproject new file mode 100644 index 000000000..e5c369374 --- /dev/null +++ b/examples/widgets/itemviews/fetchmore/fetchmore.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["fetchmore.py"] +} diff --git a/examples/widgets/itemviews/itemviews.pyproject b/examples/widgets/itemviews/itemviews.pyproject deleted file mode 100644 index a582259cc..000000000 --- a/examples/widgets/itemviews/itemviews.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["basicsortfiltermodel.py", "fetchmore.py"] -} diff --git a/examples/widgets/layouts/basiclayouts.py b/examples/widgets/layouts/basiclayouts/basiclayouts.py index 25a9b7760..25a9b7760 100644 --- a/examples/widgets/layouts/basiclayouts.py +++ b/examples/widgets/layouts/basiclayouts/basiclayouts.py diff --git a/examples/widgets/layouts/basiclayouts/basiclayouts.pyproject b/examples/widgets/layouts/basiclayouts/basiclayouts.pyproject new file mode 100644 index 000000000..c573f5688 --- /dev/null +++ b/examples/widgets/layouts/basiclayouts/basiclayouts.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["basiclayouts.py"] +} diff --git a/examples/widgets/layouts/dynamiclayouts.py b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py index 5d2f2babe..5d2f2babe 100644 --- a/examples/widgets/layouts/dynamiclayouts.py +++ b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py diff --git a/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pyproject b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pyproject new file mode 100644 index 000000000..c4276741f --- /dev/null +++ b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["dynamiclayouts.py"] +} diff --git a/examples/widgets/layouts/flowlayout.py b/examples/widgets/layouts/flowlayout/flowlayout.py index 8f4d41480..8f4d41480 100644 --- a/examples/widgets/layouts/flowlayout.py +++ b/examples/widgets/layouts/flowlayout/flowlayout.py diff --git a/examples/widgets/layouts/flowlayout/flowlayout.pyproject b/examples/widgets/layouts/flowlayout/flowlayout.pyproject new file mode 100644 index 000000000..fd7f285de --- /dev/null +++ b/examples/widgets/layouts/flowlayout/flowlayout.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["flowlayout.py"] +} diff --git a/examples/widgets/layouts/layouts.pyproject b/examples/widgets/layouts/layouts.pyproject deleted file mode 100644 index 85eb22785..000000000 --- a/examples/widgets/layouts/layouts.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["basiclayouts.py", "dynamiclayouts.py", "flowlayout.py"] -} diff --git a/examples/widgets/painting/concentriccircles.py b/examples/widgets/painting/concentriccircles/concentriccircles.py index 08520b063..08520b063 100644 --- a/examples/widgets/painting/concentriccircles.py +++ b/examples/widgets/painting/concentriccircles/concentriccircles.py diff --git a/examples/widgets/painting/painting.pyproject b/examples/widgets/painting/concentriccircles/concentriccircles.pyproject index ed24e12b0..ed24e12b0 100644 --- a/examples/widgets/painting/painting.pyproject +++ b/examples/widgets/painting/concentriccircles/concentriccircles.pyproject diff --git a/examples/widgets/richtext/orderform.py b/examples/widgets/richtext/orderform/orderform.py index ed7b29d61..ed7b29d61 100644 --- a/examples/widgets/richtext/orderform.py +++ b/examples/widgets/richtext/orderform/orderform.py diff --git a/examples/widgets/richtext/orderform/orderform.pyproject b/examples/widgets/richtext/orderform/orderform.pyproject new file mode 100644 index 000000000..47be69fd2 --- /dev/null +++ b/examples/widgets/richtext/orderform/orderform.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["orderform.py"] +} diff --git a/examples/widgets/richtext/richtext.pyproject b/examples/widgets/richtext/richtext.pyproject deleted file mode 100644 index e91a98961..000000000 --- a/examples/widgets/richtext/richtext.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["syntaxhighlighter.py", "orderform.py"] -} diff --git a/examples/widgets/richtext/syntaxhighlighter.py b/examples/widgets/richtext/syntaxhighlighter.py deleted file mode 100644 index 52b3d53b8..000000000 --- a/examples/widgets/richtext/syntaxhighlighter.py +++ /dev/null @@ -1,203 +0,0 @@ - -############################################################################# -## -## Copyright (C) 2013 Riverbank Computing Limited. -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: http://www.qt.io/licensing/ -## -## This file is part of the Qt for Python examples of the Qt Toolkit. -## -## $QT_BEGIN_LICENSE:BSD$ -## You may use this file under the terms of the BSD license as follows: -## -## "Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions are -## met: -## * Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## * Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in -## the documentation and/or other materials provided with the -## distribution. -## * Neither the name of The Qt Company Ltd nor the names of its -## contributors may be used to endorse or promote products derived -## from this software without specific prior written permission. -## -## -## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -## -## $QT_END_LICENSE$ -## -############################################################################# - -"""PySide6 port of the widgets/richtext/syntaxhighlighter example from Qt v5.x""" - -from PySide6 import QtCore, QtGui, QtWidgets - - -class MainWindow(QtWidgets.QMainWindow): - def __init__(self, parent=None): - super(MainWindow, self).__init__(parent) - - self.setupFileMenu() - self.setupHelpMenu() - self.setupEditor() - - self.setCentralWidget(self.editor) - self.setWindowTitle("Syntax Highlighter") - - def about(self): - QtWidgets.QMessageBox.about(self, "About Syntax Highlighter", - "<p>The <b>Syntax Highlighter</b> example shows how to " \ - "perform simple syntax highlighting by subclassing the " \ - "QSyntaxHighlighter class and describing highlighting " \ - "rules using regular expressions.</p>") - - def newFile(self): - self.editor.clear() - - def openFile(self, path=None): - if not path: - path = QtWidgets.QFileDialog.getOpenFileName(self, "Open File", - '', "C++ Files (*.cpp *.h)") - - if path: - inFile = QtCore.QFile(path[0]) - if inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text): - text = inFile.readAll() - text = str(text, encoding='ascii') - self.editor.setPlainText(text) - - def setupEditor(self): - font = QtGui.QFont() - font.setFamily('Courier') - font.setFixedPitch(True) - font.setPointSize(10) - - self.editor = QtWidgets.QTextEdit() - self.editor.setFont(font) - - self.highlighter = Highlighter(self.editor.document()) - - def setupFileMenu(self): - fileMenu = QtWidgets.QMenu("&File", self) - self.menuBar().addMenu(fileMenu) - - fileMenu.addAction("&New...", self.newFile, "Ctrl+N") - fileMenu.addAction("&Open...", self.openFile, "Ctrl+O") - fileMenu.addAction("E&xit", qApp.quit, "Ctrl+Q") - - def setupHelpMenu(self): - helpMenu = QtWidgets.QMenu("&Help", self) - self.menuBar().addMenu(helpMenu) - - helpMenu.addAction("&About", self.about) - helpMenu.addAction("About &Qt", qApp.aboutQt) - - -class Highlighter(QtGui.QSyntaxHighlighter): - def __init__(self, parent=None): - super(Highlighter, self).__init__(parent) - - keywordFormat = QtGui.QTextCharFormat() - keywordFormat.setForeground(QtCore.Qt.darkBlue) - keywordFormat.setFontWeight(QtGui.QFont.Bold) - - keywordPatterns = ["\\bchar\\b", "\\bclass\\b", "\\bconst\\b", - "\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b", "\\bfriend\\b", - "\\binline\\b", "\\bint\\b", "\\blong\\b", "\\bnamespace\\b", - "\\boperator\\b", "\\bprivate\\b", "\\bprotected\\b", - "\\bpublic\\b", "\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b", - "\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b", - "\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b", - "\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b", "\\bvoid\\b", - "\\bvolatile\\b"] - - self.highlightingRules = [(QtCore.QRegularExpression(pattern), keywordFormat) - for pattern in keywordPatterns] - - classFormat = QtGui.QTextCharFormat() - classFormat.setFontWeight(QtGui.QFont.Bold) - classFormat.setForeground(QtCore.Qt.darkMagenta) - pattern = QtCore.QRegularExpression(r'\bQ[A-Za-z]+\b') - assert pattern.isValid() - self.highlightingRules.append((pattern, classFormat)) - - singleLineCommentFormat = QtGui.QTextCharFormat() - singleLineCommentFormat.setForeground(QtCore.Qt.red) - pattern = QtCore.QRegularExpression('//[^\n]*') - assert pattern.isValid() - self.highlightingRules.append((pattern, singleLineCommentFormat)) - - self.multiLineCommentFormat = QtGui.QTextCharFormat() - self.multiLineCommentFormat.setForeground(QtCore.Qt.red) - - quotationFormat = QtGui.QTextCharFormat() - quotationFormat.setForeground(QtCore.Qt.darkGreen) - pattern = QtCore.QRegularExpression('".*"') - assert pattern.isValid() - self.highlightingRules.append((pattern, quotationFormat)) - - functionFormat = QtGui.QTextCharFormat() - functionFormat.setFontItalic(True) - functionFormat.setForeground(QtCore.Qt.blue) - pattern = QtCore.QRegularExpression(r'\b[A-Za-z0-9_]+(?=\()') - assert pattern.isValid() - self.highlightingRules.append((pattern, functionFormat)) - - self.commentStartExpression = QtCore.QRegularExpression(r'/\*') - assert self.commentStartExpression.isValid() - self.commentEndExpression = QtCore.QRegularExpression(r'\*/') - assert self.commentEndExpression.isValid() - - def highlightBlock(self, text): - for pattern, format in self.highlightingRules: - match = pattern.match(text) - while match.hasMatch(): - index = match.capturedStart(0) - length = match.capturedLength(0) - self.setFormat(index, length, format) - match = pattern.match(text, index + length) - - self.setCurrentBlockState(0) - - startIndex = 0 - if self.previousBlockState() != 1: - match = self.commentStartExpression.match(text) - startIndex = match.capturedStart(0) if match.hasMatch() else -1 - - while startIndex >= 0: - match = self.commentEndExpression.match(text, startIndex) - if match.hasMatch(): - endIndex = match.capturedStart(0) - length = match.capturedLength(0) - commentLength = endIndex - startIndex + length - else: - self.setCurrentBlockState(1) - commentLength = len(text) - startIndex - - self.setFormat(startIndex, commentLength, - self.multiLineCommentFormat) - match = self.commentStartExpression.match(text, startIndex + commentLength) - startIndex = match.capturedStart(0) if match.hasMatch() else -1 - - -if __name__ == '__main__': - - import sys - - app = QtWidgets.QApplication(sys.argv) - window = MainWindow() - window.resize(640, 512) - window.show() - sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/eventtrans.py b/examples/widgets/state-machine/eventtrans/eventtrans.py index 312b4e258..312b4e258 100644 --- a/examples/widgets/state-machine/eventtrans.py +++ b/examples/widgets/state-machine/eventtrans/eventtrans.py diff --git a/examples/widgets/state-machine/eventtrans/eventtrans.pyproject b/examples/widgets/state-machine/eventtrans/eventtrans.pyproject new file mode 100644 index 000000000..b2f660a8f --- /dev/null +++ b/examples/widgets/state-machine/eventtrans/eventtrans.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["eventtrans.py"] +} diff --git a/examples/widgets/state-machine/factstates.py b/examples/widgets/state-machine/factstates/factstates.py index 3608f2a49..3608f2a49 100644 --- a/examples/widgets/state-machine/factstates.py +++ b/examples/widgets/state-machine/factstates/factstates.py diff --git a/examples/widgets/state-machine/factstates/factstates.pyproject b/examples/widgets/state-machine/factstates/factstates.pyproject new file mode 100644 index 000000000..751a5005b --- /dev/null +++ b/examples/widgets/state-machine/factstates/factstates.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["factstates.py"] +} diff --git a/examples/widgets/state-machine/pingpong.py b/examples/widgets/state-machine/pingpong/pingpong.py index f2e1f59f7..f2e1f59f7 100644 --- a/examples/widgets/state-machine/pingpong.py +++ b/examples/widgets/state-machine/pingpong/pingpong.py diff --git a/examples/widgets/state-machine/pingpong/pingpong.pyproject b/examples/widgets/state-machine/pingpong/pingpong.pyproject new file mode 100644 index 000000000..67b48e5ab --- /dev/null +++ b/examples/widgets/state-machine/pingpong/pingpong.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["pingpong.py"] +} diff --git a/examples/widgets/state-machine/rogue.py b/examples/widgets/state-machine/rogue/rogue.py index b830d6023..b830d6023 100644 --- a/examples/widgets/state-machine/rogue.py +++ b/examples/widgets/state-machine/rogue/rogue.py diff --git a/examples/widgets/state-machine/rogue/rogue.pyproject b/examples/widgets/state-machine/rogue/rogue.pyproject new file mode 100644 index 000000000..b8baf9802 --- /dev/null +++ b/examples/widgets/state-machine/rogue/rogue.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["rogue.py"] +} diff --git a/examples/widgets/state-machine/state-machine.pyproject b/examples/widgets/state-machine/state-machine.pyproject deleted file mode 100644 index dafb204c8..000000000 --- a/examples/widgets/state-machine/state-machine.pyproject +++ /dev/null @@ -1,4 +0,0 @@ -{ - "files": ["pingpong.py", "trafficlight.py", "twowaybutton.py", - "eventtrans.py", "rogue.py", "factstates.py"] -} diff --git a/examples/widgets/state-machine/trafficlight.py b/examples/widgets/state-machine/trafficlight/trafficlight.py index 3631fdbbb..3631fdbbb 100644 --- a/examples/widgets/state-machine/trafficlight.py +++ b/examples/widgets/state-machine/trafficlight/trafficlight.py diff --git a/examples/widgets/state-machine/trafficlight/trafficlight.pyproject b/examples/widgets/state-machine/trafficlight/trafficlight.pyproject new file mode 100644 index 000000000..912472693 --- /dev/null +++ b/examples/widgets/state-machine/trafficlight/trafficlight.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["trafficlight.py"] +} diff --git a/examples/widgets/state-machine/twowaybutton.py b/examples/widgets/state-machine/twowaybutton/twowaybutton.py index 6b3c58359..6b3c58359 100644 --- a/examples/widgets/state-machine/twowaybutton.py +++ b/examples/widgets/state-machine/twowaybutton/twowaybutton.py diff --git a/examples/widgets/state-machine/twowaybutton/twowaybutton.pyproject b/examples/widgets/state-machine/twowaybutton/twowaybutton.pyproject new file mode 100644 index 000000000..223a51e32 --- /dev/null +++ b/examples/widgets/state-machine/twowaybutton/twowaybutton.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["twowaybutton.py"] +} diff --git a/examples/widgets/widgets/tetrix.py b/examples/widgets/tetrix/tetrix.py index 69c6d4bff..69c6d4bff 100644 --- a/examples/widgets/widgets/tetrix.py +++ b/examples/widgets/tetrix/tetrix.py diff --git a/examples/widgets/tetrix/tetrix.pyproject b/examples/widgets/tetrix/tetrix.pyproject new file mode 100644 index 000000000..75121ea64 --- /dev/null +++ b/examples/widgets/tetrix/tetrix.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["tetrix.py"] +} diff --git a/examples/widgets/threads/thread_signals.pyproject b/examples/widgets/threads/thread_signals.pyproject new file mode 100644 index 000000000..e36f7633c --- /dev/null +++ b/examples/widgets/threads/thread_signals.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["thread_signals.py"] +} diff --git a/examples/widgets/tutorials/cannon/cannon.pyproject b/examples/widgets/tutorials/cannon/cannon.pyproject new file mode 100644 index 000000000..09478e108 --- /dev/null +++ b/examples/widgets/tutorials/cannon/cannon.pyproject @@ -0,0 +1,5 @@ +{ + "files": ["t6.py", "t9.py", "t8.py", "t13.py", "t10.py", "t7.py", + "t3.py", "t4.py", "t1.py", "t12.py", "t2.py", "t5.py", + "t11.py", "t14.py"] +} diff --git a/examples/widgets/tutorials/cannon/t1.py b/examples/widgets/tutorials/cannon/t1.py new file mode 100644 index 000000000..43fea90c4 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t1.py @@ -0,0 +1,56 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 1 + + +import sys +from PySide6 import QtWidgets + + +app = QtWidgets.QApplication(sys.argv) + +hello = QtWidgets.QPushButton("Hello world!") +hello.resize(100, 30) + +hello.show() + +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t10.py b/examples/widgets/tutorials/cannon/t10.py new file mode 100644 index 000000000..ca7e9d9b7 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t10.py @@ -0,0 +1,191 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 10 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + lcd = QtWidgets.QLCDNumber(2) + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + self.setLayout(layout) + + self.setFocusProxy(self.slider) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + def setRange(self, minValue, maxValue): + if minValue < 0 or maxValue > 99 or minValue > maxValue: + QtCore.qWarning("LCDRange::setRange(%d, %d)\n" + "\tRange must be 0..99\n" + "\tand minValue must not be greater than maxValue" % (minValue, maxValue)) + return + + self.slider.setRange(minValue, maxValue) + + +class CannonField(QtWidgets.QWidget): + angleChanged = QtCore.Signal(int) + forceChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.currentAngle = 45 + self.currentForce = 0 + self.setPalette(QtGui.QPalette(QtGui.QColor(250, 250, 200))) + self.setAutoFillBackground(True) + + def angle(self): + return self.currentAngle + + @QtCore.Slot(int) + def setAngle(self, angle): + if angle < 5: + angle = 5 + if angle > 70: + angle = 70 + if self.currentAngle == angle: + return + self.currentAngle = angle + self.update() + self.emit(QtCore.SIGNAL("angleChanged(int)"), self.currentAngle) + + def force(self): + return self.currentForce + + @QtCore.Slot(int) + def setForce(self, force): + if force < 0: + force = 0 + if self.currentForce == force: + return + self.currentForce = force + self.emit(QtCore.SIGNAL("forceChanged(int)"), self.currentForce) + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.blue) + + painter.translate(0, self.height()) + painter.drawPie(QtCore.QRect(-35, -35, 70, 70), 0, 90 * 16) + painter.rotate(-self.currentAngle) + painter.drawRect(QtCore.QRect(33, -4, 15, 8)) + + def cannonRect(self): + result = QtCore.QRect(0, 0, 50, 50) + result.moveBottomLeft(self.rect().bottomLect()) + return result + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("&Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + angle = LCDRange() + angle.setRange(5, 70) + + force = LCDRange() + force.setRange(10, 50) + + cannonField = CannonField() + + self.connect(angle, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setAngle) + self.connect(cannonField, QtCore.SIGNAL("angleChanged(int)"), + angle.setValue) + + self.connect(force, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setForce) + self.connect(cannonField, QtCore.SIGNAL("forceChanged(int)"), + force.setValue) + + leftLayout = QtWidgets.QVBoxLayout() + leftLayout.addWidget(angle) + leftLayout.addWidget(force) + + gridLayout = QtWidgets.QGridLayout() + gridLayout.addWidget(quit, 0, 0) + gridLayout.addLayout(leftLayout, 1, 0) + gridLayout.addWidget(cannonField, 1, 1, 2, 1) + gridLayout.setColumnStretch(1, 10) + self.setLayout(gridLayout) + + angle.setValue(60) + force.setValue(25) + angle.setFocus() + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.setGeometry(100, 100, 500, 355) +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t11.py b/examples/widgets/tutorials/cannon/t11.py new file mode 100644 index 000000000..c3d2e1271 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t11.py @@ -0,0 +1,263 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 11 + + +import sys +import math +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + lcd = QtWidgets.QLCDNumber(2) + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + self.setLayout(layout) + + self.setFocusProxy(self.slider) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + def setRange(self, minValue, maxValue): + if minValue < 0 or maxValue > 99 or minValue > maxValue: + QtCore.qWarning("LCDRange::setRange(%d, %d)\n" + "\tRange must be 0..99\n" + "\tand minValue must not be greater than maxValue" % (minValue, maxValue)) + return + + self.slider.setRange(minValue, maxValue) + + +class CannonField(QtWidgets.QWidget): + angleChanged = QtCore.Signal(int) + forceChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.currentAngle = 45 + self.currentForce = 0 + self.timerCount = 0 + self.autoShootTimer = QtCore.QTimer(self) + self.connect(self.autoShootTimer, QtCore.SIGNAL("timeout()"), + self.moveShot) + self.shootAngle = 0 + self.shootForce = 0 + self.setPalette(QtGui.QPalette(QtGui.QColor(250, 250, 200))) + self.setAutoFillBackground(True) + + def angle(self): + return self.currentAngle + + @QtCore.Slot(int) + def setAngle(self, angle): + if angle < 5: + angle = 5 + if angle > 70: + angle = 70 + if self.currentAngle == angle: + return + self.currentAngle = angle + self.update() + self.emit(QtCore.SIGNAL("angleChanged(int)"), self.currentAngle) + + def force(self): + return self.currentForce + + @QtCore.Slot(int) + def setForce(self, force): + if force < 0: + force = 0 + if self.currentForce == force: + return + self.currentForce = force + self.emit(QtCore.SIGNAL("forceChanged(int)"), self.currentForce) + + @QtCore.Slot() + def shoot(self): + if self.autoShootTimer.isActive(): + return + self.timerCount = 0 + self.shootAngle = self.currentAngle + self.shootForce = self.currentForce + self.autoShootTimer.start(5) + + @QtCore.Slot() + def moveShot(self): + region = QtGui.QRegion(self.shotRect()) + self.timerCount += 1 + + shotR = self.shotRect() + + if shotR.x() > self.width() or shotR.y() > self.height(): + self.autoShootTimer.stop() + else: + region = region.united(QtGui.QRegion(shotR)) + + self.update(region) + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + + self.paintCannon(painter) + if self.autoShootTimer.isActive(): + self.paintShot(painter) + + def paintShot(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.black) + painter.drawRect(self.shotRect()) + + barrelRect = QtCore.QRect(33, -4, 15, 8) + + def paintCannon(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.blue) + + painter.save() + painter.translate(0, self.height()) + painter.drawPie(QtCore.QRect(-35, -35, 70, 70), 0, 90 * 16) + painter.rotate(-self.currentAngle) + painter.drawRect(CannonField.barrelRect) + painter.restore() + + def cannonRect(self): + result = QtCore.QRect(0, 0, 50, 50) + result.moveBottomLeft(self.rect().bottomLect()) + return result + + def shotRect(self): + gravity = 4.0 + + time = self.timerCount / 40.0 + velocity = self.shootForce + radians = self.shootAngle * 3.14159265 / 180 + + velx = velocity * math.cos(radians) + vely = velocity * math.sin(radians) + x0 = (CannonField.barrelRect.right() + 5) * math.cos(radians) + y0 = (CannonField.barrelRect.right() + 5) * math.sin(radians) + x = x0 + velx * time + y = y0 + vely * time - 0.5 * gravity * time * time + + result = QtCore.QRect(0, 0, 6, 6) + result.moveCenter(QtCore.QPoint(round(x), self.height() - 1 - round(y))) + return result + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("&Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + angle = LCDRange() + angle.setRange(5, 70) + + force = LCDRange() + force.setRange(10, 50) + + cannonField = CannonField() + + self.connect(angle, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setAngle) + self.connect(cannonField, QtCore.SIGNAL("angleChanged(int)"), + angle.setValue) + + self.connect(force, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setForce) + self.connect(cannonField, QtCore.SIGNAL("forceChanged(int)"), + force.setValue) + + shoot = QtWidgets.QPushButton("&Shoot") + shoot.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(shoot, QtCore.SIGNAL("clicked()"), cannonField.shoot) + + topLayout = QtWidgets.QHBoxLayout() + topLayout.addWidget(shoot) + topLayout.addStretch(1) + + leftLayout = QtWidgets.QVBoxLayout() + leftLayout.addWidget(angle) + leftLayout.addWidget(force) + + gridLayout = QtWidgets.QGridLayout() + gridLayout.addWidget(quit, 0, 0) + gridLayout.addLayout(topLayout, 0, 1) + gridLayout.addLayout(leftLayout, 1, 0) + gridLayout.addWidget(cannonField, 1, 1, 2, 1) + gridLayout.setColumnStretch(1, 10) + self.setLayout(gridLayout) + + angle.setValue(60) + force.setValue(25) + angle.setFocus() + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.setGeometry(100, 100, 500, 355) +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t12.py b/examples/widgets/tutorials/cannon/t12.py new file mode 100644 index 000000000..290ecc82e --- /dev/null +++ b/examples/widgets/tutorials/cannon/t12.py @@ -0,0 +1,312 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 12 + + +import sys +import math +import random +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, text=None, parent=None): + if isinstance(text, QtWidgets.QWidget): + parent = text + text = None + + QtWidgets.QWidget.__init__(self, parent) + + self.init() + + if text: + self.setText(text) + + def init(self): + lcd = QtWidgets.QLCDNumber(2) + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + self.label = QtWidgets.QLabel() + self.label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + layout.addWidget(self.label) + self.setLayout(layout) + + self.setFocusProxy(self.slider) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + def text(self): + return self.label.text() + + def setRange(self, minValue, maxValue): + if minValue < 0 or maxValue > 99 or minValue > maxValue: + QtCore.qWarning("LCDRange::setRange(%d, %d)\n" + "\tRange must be 0..99\n" + "\tand minValue must not be greater than maxValue" % (minValue, maxValue)) + return + + self.slider.setRange(minValue, maxValue) + + def setText(self, text): + self.label.setText(text) + + +class CannonField(QtWidgets.QWidget): + angleChanged = QtCore.Signal(int) + forceChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.currentAngle = 45 + self.currentForce = 0 + self.timerCount = 0 + self.autoShootTimer = QtCore.QTimer(self) + self.connect(self.autoShootTimer, QtCore.SIGNAL("timeout()"), + self.moveShot) + self.shootAngle = 0 + self.shootForce = 0 + self.target = QtCore.QPoint(0, 0) + self.setPalette(QtGui.QPalette(QtGui.QColor(250, 250, 200))) + self.setAutoFillBackground(True) + self.newTarget() + + def angle(self): + return self.currentAngle + + @QtCore.Slot(int) + def setAngle(self, angle): + if angle < 5: + angle = 5 + if angle > 70: + angle = 70 + if self.currentAngle == angle: + return + self.currentAngle = angle + self.update() + self.emit(QtCore.SIGNAL("angleChanged(int)"), self.currentAngle) + + def force(self): + return self.currentForce + + @QtCore.Slot(int) + def setForce(self, force): + if force < 0: + force = 0 + if self.currentForce == force: + return + self.currentForce = force + self.emit(QtCore.SIGNAL("forceChanged(int)"), self.currentForce) + + @QtCore.Slot() + def shoot(self): + if self.autoShootTimer.isActive(): + return + self.timerCount = 0 + self.shootAngle = self.currentAngle + self.shootForce = self.currentForce + self.autoShootTimer.start(5) + + firstTime = True + + def newTarget(self): + if CannonField.firstTime: + CannonField.firstTime = False + midnight = QtCore.QTime(0, 0, 0) + random.seed(midnight.secsTo(QtCore.QTime.currentTime())) + + self.target = QtCore.QPoint(200 + random.randint(0, 190 - 1), 10 + random.randint(0, 255 - 1)) + self.update() + + @QtCore.Slot() + def moveShot(self): + region = QtGui.QRegion(self.shotRect()) + self.timerCount += 1 + + shotR = self.shotRect() + + if shotR.intersects(self.targetRect()): + self.autoShootTimer.stop() + self.emit(QtCore.SIGNAL("hit()")) + elif shotR.x() > self.width() or shotR.y() > self.height(): + self.autoShootTimer.stop() + self.emit(QtCore.SIGNAL("missed()")) + else: + region = region.united(QtGui.QRegion(shotR)) + + self.update(region) + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + + self.paintCannon(painter) + if self.autoShootTimer.isActive(): + self.paintShot(painter) + + self.paintTarget(painter) + + def paintShot(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.black) + painter.drawRect(self.shotRect()) + + def paintTarget(self, painter): + painter.setPen(QtCore.Qt.black) + painter.setBrush(QtCore.Qt.red) + painter.drawRect(self.targetRect()) + + barrelRect = QtCore.QRect(33, -4, 15, 8) + + def paintCannon(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.blue) + + painter.save() + painter.translate(0, self.height()) + painter.drawPie(QtCore.QRect(-35, -35, 70, 70), 0, 90 * 16) + painter.rotate(-self.currentAngle) + painter.drawRect(CannonField.barrelRect) + painter.restore() + + def cannonRect(self): + result = QtCore.QRect(0, 0, 50, 50) + result.moveBottomLeft(self.rect().bottomLect()) + return result + + def shotRect(self): + gravity = 4.0 + + time = self.timerCount / 40.0 + velocity = self.shootForce + radians = self.shootAngle * 3.14159265 / 180 + + velx = velocity * math.cos(radians) + vely = velocity * math.sin(radians) + x0 = (CannonField.barrelRect.right() + 5) * math.cos(radians) + y0 = (CannonField.barrelRect.right() + 5) * math.sin(radians) + x = x0 + velx * time + y = y0 + vely * time - 0.5 * gravity * time * time + + result = QtCore.QRect(0, 0, 6, 6) + result.moveCenter(QtCore.QPoint(round(x), self.height() - 1 - round(y))) + return result + + def targetRect(self): + result = QtCore.QRect(0, 0, 20, 10) + result.moveCenter(QtCore.QPoint(self.target.x(), self.height() - 1 - self.target.y())) + return result + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("&Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + angle = LCDRange("ANGLE") + angle.setRange(5, 70) + + force = LCDRange("FORCE") + force.setRange(10, 50) + + cannonField = CannonField() + + self.connect(angle, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setAngle) + self.connect(cannonField, QtCore.SIGNAL("angleChanged(int)"), + angle.setValue) + + self.connect(force, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setForce) + self.connect(cannonField, QtCore.SIGNAL("forceChanged(int)"), + force.setValue) + + shoot = QtWidgets.QPushButton("&Shoot") + shoot.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(shoot, QtCore.SIGNAL("clicked()"), cannonField.shoot) + + topLayout = QtWidgets.QHBoxLayout() + topLayout.addWidget(shoot) + topLayout.addStretch(1) + + leftLayout = QtWidgets.QVBoxLayout() + leftLayout.addWidget(angle) + leftLayout.addWidget(force) + + gridLayout = QtWidgets.QGridLayout() + gridLayout.addWidget(quit, 0, 0) + gridLayout.addLayout(topLayout, 0, 1) + gridLayout.addLayout(leftLayout, 1, 0) + gridLayout.addWidget(cannonField, 1, 1, 2, 1) + gridLayout.setColumnStretch(1, 10) + self.setLayout(gridLayout) + + angle.setValue(60) + force.setValue(25) + angle.setFocus() + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.setGeometry(100, 100, 500, 355) +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t13.py b/examples/widgets/tutorials/cannon/t13.py new file mode 100644 index 000000000..b54945e25 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t13.py @@ -0,0 +1,395 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 13 + + +import sys +import math +import random +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, text=None, parent=None): + if isinstance(text, QtWidgets.QWidget): + parent = text + text = None + + QtWidgets.QWidget.__init__(self, parent) + + self.init() + + if text: + self.setText(text) + + def init(self): + lcd = QtWidgets.QLCDNumber(2) + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + self.label = QtWidgets.QLabel() + self.label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop) + self.label.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + layout.addWidget(self.label) + self.setLayout(layout) + + self.setFocusProxy(self.slider) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + def text(self): + return self.label.text() + + def setRange(self, minValue, maxValue): + if minValue < 0 or maxValue > 99 or minValue > maxValue: + QtCore.qWarning("LCDRange::setRange(%d, %d)\n" + "\tRange must be 0..99\n" + "\tand minValue must not be greater than maxValue" % (minValue, maxValue)) + return + + self.slider.setRange(minValue, maxValue) + + def setText(self, text): + self.label.setText(text) + + +class CannonField(QtWidgets.QWidget): + angleChanged = QtCore.Signal(int) + forceChanged = QtCore.Signal(int) + hit = QtCore.Signal() + missed = QtCore.Signal() + canShoot = QtCore.Signal(bool) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.currentAngle = 45 + self.currentForce = 0 + self.timerCount = 0 + self.autoShootTimer = QtCore.QTimer(self) + self.connect(self.autoShootTimer, QtCore.SIGNAL("timeout()"), + self.moveShot) + self.shootAngle = 0 + self.shootForce = 0 + self.target = QtCore.QPoint(0, 0) + self.gameEnded = False + self.setPalette(QtGui.QPalette(QtGui.QColor(250, 250, 200))) + self.setAutoFillBackground(True) + self.newTarget() + + def angle(self): + return self.currentAngle + + @QtCore.Slot(int) + def setAngle(self, angle): + if angle < 5: + angle = 5 + if angle > 70: + angle = 70 + if self.currentAngle == angle: + return + self.currentAngle = angle + self.update() + self.emit(QtCore.SIGNAL("angleChanged(int)"), self.currentAngle) + + def force(self): + return self.currentForce + + @QtCore.Slot(int) + def setForce(self, force): + if force < 0: + force = 0 + if self.currentForce == force: + return + self.currentForce = force + self.emit(QtCore.SIGNAL("forceChanged(int)"), self.currentForce) + + @QtCore.Slot() + def shoot(self): + if self.isShooting(): + return + self.timerCount = 0 + self.shootAngle = self.currentAngle + self.shootForce = self.currentForce + self.autoShootTimer.start(5) + self.emit(QtCore.SIGNAL("canShoot(bool)"), False) + + firstTime = True + + def newTarget(self): + if CannonField.firstTime: + CannonField.firstTime = False + midnight = QtCore.QTime(0, 0, 0) + random.seed(midnight.secsTo(QtCore.QTime.currentTime())) + + self.target = QtCore.QPoint(200 + random.randint(0, 190 - 1), 10 + random.randint(0, 255 - 1)) + self.update() + + def setGameOver(self): + if self.gameEnded: + return + if self.isShooting(): + self.autoShootTimer.stop() + self.gameEnded = True + self.update() + + def restartGame(self): + if self.isShooting(): + self.autoShootTimer.stop() + self.gameEnded = False + self.update() + self.emit(QtCore.SIGNAL("canShoot(bool)"), True) + + @QtCore.Slot() + def moveShot(self): + region = QtGui.QRegion(self.shotRect()) + self.timerCount += 1 + + shotR = self.shotRect() + + if shotR.intersects(self.targetRect()): + self.autoShootTimer.stop() + self.emit(QtCore.SIGNAL("hit()")) + self.emit(QtCore.SIGNAL("canShoot(bool)"), True) + elif shotR.x() > self.width() or shotR.y() > self.height(): + self.autoShootTimer.stop() + self.emit(QtCore.SIGNAL("missed()")) + self.emit(QtCore.SIGNAL("canShoot(bool)"), True) + else: + region = region.united(QtGui.QRegion(shotR)) + + self.update(region) + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + + if self.gameEnded: + painter.setPen(QtCore.Qt.black) + painter.setFont(QtGui.QFont("Courier", 48, QtGui.QFont.Bold)) + painter.drawText(self.rect(), QtCore.Qt.AlignCenter, "Game Over") + + self.paintCannon(painter) + if self.isShooting(): + self.paintShot(painter) + if not self.gameEnded: + self.paintTarget(painter) + + def paintShot(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.black) + painter.drawRect(self.shotRect()) + + def paintTarget(self, painter): + painter.setPen(QtCore.Qt.black) + painter.setBrush(QtCore.Qt.red) + painter.drawRect(self.targetRect()) + + barrelRect = QtCore.QRect(33, -4, 15, 8) + + def paintCannon(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.blue) + + painter.save() + painter.translate(0, self.height()) + painter.drawPie(QtCore.QRect(-35, -35, 70, 70), 0, 90 * 16) + painter.rotate(-self.currentAngle) + painter.drawRect(CannonField.barrelRect) + painter.restore() + + def cannonRect(self): + result = QtCore.QRect(0, 0, 50, 50) + result.moveBottomLeft(self.rect().bottomLect()) + return result + + def shotRect(self): + gravity = 4.0 + + time = self.timerCount / 40.0 + velocity = self.shootForce + radians = self.shootAngle * 3.14159265 / 180 + + velx = velocity * math.cos(radians) + vely = velocity * math.sin(radians) + x0 = (CannonField.barrelRect.right() + 5) * math.cos(radians) + y0 = (CannonField.barrelRect.right() + 5) * math.sin(radians) + x = x0 + velx * time + y = y0 + vely * time - 0.5 * gravity * time * time + + result = QtCore.QRect(0, 0, 6, 6) + result.moveCenter(QtCore.QPoint(round(x), self.height() - 1 - round(y))) + return result + + def targetRect(self): + result = QtCore.QRect(0, 0, 20, 10) + result.moveCenter(QtCore.QPoint(self.target.x(), self.height() - 1 - self.target.y())) + return result + + def gameOver(self): + return self.gameEnded + + def isShooting(self): + return self.autoShootTimer.isActive() + + +class GameBoard(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("&Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + angle = LCDRange("ANGLE") + angle.setRange(5, 70) + + force = LCDRange("FORCE") + force.setRange(10, 50) + + self.cannonField = CannonField() + + self.connect(angle, QtCore.SIGNAL("valueChanged(int)"), + self.cannonField.setAngle) + self.connect(self.cannonField, QtCore.SIGNAL("angleChanged(int)"), + angle.setValue) + + self.connect(force, QtCore.SIGNAL("valueChanged(int)"), + self.cannonField.setForce) + self.connect(self.cannonField, QtCore.SIGNAL("forceChanged(int)"), + force.setValue) + + self.connect(self.cannonField, QtCore.SIGNAL("hit()"), self.hit) + self.connect(self.cannonField, QtCore.SIGNAL("missed()"), self.missed) + + shoot = QtWidgets.QPushButton("&Shoot") + shoot.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(shoot, QtCore.SIGNAL("clicked()"), self.fire) + self.connect(self.cannonField, QtCore.SIGNAL("canShoot(bool)"), + shoot, QtCore.SLOT("setEnabled(bool)")) + + restart = QtWidgets.QPushButton("&New Game") + restart.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(restart, QtCore.SIGNAL("clicked()"), self.newGame) + + self.hits = QtWidgets.QLCDNumber(2) + self.shotsLeft = QtWidgets.QLCDNumber(2) + hitsLabel = QtWidgets.QLabel("HITS") + shotsLeftLabel = QtWidgets.QLabel("SHOTS LEFT") + + topLayout = QtWidgets.QHBoxLayout() + topLayout.addWidget(shoot) + topLayout.addWidget(self.hits) + topLayout.addWidget(hitsLabel) + topLayout.addWidget(self.shotsLeft) + topLayout.addWidget(shotsLeftLabel) + topLayout.addStretch(1) + topLayout.addWidget(restart) + + leftLayout = QtWidgets.QVBoxLayout() + leftLayout.addWidget(angle) + leftLayout.addWidget(force) + + gridLayout = QtWidgets.QGridLayout() + gridLayout.addWidget(quit, 0, 0) + gridLayout.addLayout(topLayout, 0, 1) + gridLayout.addLayout(leftLayout, 1, 0) + gridLayout.addWidget(self.cannonField, 1, 1, 2, 1) + gridLayout.setColumnStretch(1, 10) + self.setLayout(gridLayout) + + angle.setValue(60) + force.setValue(25) + angle.setFocus() + + self.newGame() + + @QtCore.Slot() + def fire(self): + if self.cannonField.gameOver() or self.cannonField.isShooting(): + return + self.shotsLeft.display(self.shotsLeft.intValue() - 1) + self.cannonField.shoot() + + @QtCore.Slot() + def hit(self): + self.hits.display(self.hits.intValue() + 1) + if self.shotsLeft.intValue() == 0: + self.cannonField.setGameOver() + else: + self.cannonField.newTarget() + + @QtCore.Slot() + def missed(self): + if self.shotsLeft.intValue() == 0: + self.cannonField.setGameOver() + + @QtCore.Slot() + def newGame(self): + self.shotsLeft.display(15) + self.hits.display(0) + self.cannonField.restartGame() + self.cannonField.newTarget() + + +app = QtWidgets.QApplication(sys.argv) +board = GameBoard() +board.setGeometry(100, 100, 500, 355) +board.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t14.py b/examples/widgets/tutorials/cannon/t14.py new file mode 100644 index 000000000..d558d2e61 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t14.py @@ -0,0 +1,450 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 14 + + +import sys +import math +import random +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, text=None, parent=None): + if isinstance(text, QtWidgets.QWidget): + parent = text + text = None + + QtWidgets.QWidget.__init__(self, parent) + + self.init() + + if text: + self.setText(text) + + def init(self): + lcd = QtWidgets.QLCDNumber(2) + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + self.label = QtWidgets.QLabel() + self.label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop) + self.label.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + layout.addWidget(self.label) + self.setLayout(layout) + + self.setFocusProxy(self.slider) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + def text(self): + return self.label.text() + + def setRange(self, minValue, maxValue): + if minValue < 0 or maxValue > 99 or minValue > maxValue: + QtCore.qWarning("LCDRange::setRange(%d, %d)\n" + "\tRange must be 0..99\n" + "\tand minValue must not be greater than maxValue" % (minValue, maxValue)) + return + + self.slider.setRange(minValue, maxValue) + + def setText(self, text): + self.label.setText(text) + + +class CannonField(QtWidgets.QWidget): + angleChanged = QtCore.Signal(int) + forceChanged = QtCore.Signal(int) + hit = QtCore.Signal() + missed = QtCore.Signal() + canShoot = QtCore.Signal(bool) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.currentAngle = 45 + self.currentForce = 0 + self.timerCount = 0 + self.autoShootTimer = QtCore.QTimer(self) + self.connect(self.autoShootTimer, QtCore.SIGNAL("timeout()"), + self.moveShot) + self.shootAngle = 0 + self.shootForce = 0 + self.target = QtCore.QPoint(0, 0) + self.gameEnded = False + self.barrelPressed = False + self.setPalette(QtGui.QPalette(QtGui.QColor(250, 250, 200))) + self.setAutoFillBackground(True) + self.newTarget() + + def angle(self): + return self.currentAngle + + @QtCore.Slot(int) + def setAngle(self, angle): + if angle < 5: + angle = 5 + if angle > 70: + angle = 70 + if self.currentAngle == angle: + return + self.currentAngle = angle + self.update() + self.emit(QtCore.SIGNAL("angleChanged(int)"), self.currentAngle) + + def force(self): + return self.currentForce + + @QtCore.Slot(int) + def setForce(self, force): + if force < 0: + force = 0 + if self.currentForce == force: + return + self.currentForce = force + self.emit(QtCore.SIGNAL("forceChanged(int)"), self.currentForce) + + @QtCore.Slot() + def shoot(self): + if self.isShooting(): + return + self.timerCount = 0 + self.shootAngle = self.currentAngle + self.shootForce = self.currentForce + self.autoShootTimer.start(5) + self.emit(QtCore.SIGNAL("canShoot(bool)"), False) + + firstTime = True + + def newTarget(self): + if CannonField.firstTime: + CannonField.firstTime = False + midnight = QtCore.QTime(0, 0, 0) + random.seed(midnight.secsTo(QtCore.QTime.currentTime())) + + self.target = QtCore.QPoint(200 + random.randint(0, 190 - 1), 10 + random.randint(0, 255 - 1)) + self.update() + + def setGameOver(self): + if self.gameEnded: + return + if self.isShooting(): + self.autoShootTimer.stop() + self.gameEnded = True + self.update() + + def restartGame(self): + if self.isShooting(): + self.autoShootTimer.stop() + self.gameEnded = False + self.update() + self.emit(QtCore.SIGNAL("canShoot(bool)"), True) + + @QtCore.Slot() + def moveShot(self): + region = QtGui.QRegion(self.shotRect()) + self.timerCount += 1 + + shotR = self.shotRect() + + if shotR.intersects(self.targetRect()): + self.autoShootTimer.stop() + self.emit(QtCore.SIGNAL("hit()")) + self.emit(QtCore.SIGNAL("canShoot(bool)"), True) + elif shotR.x() > self.width() or shotR.y() > self.height() or shotR.intersects(self.barrierRect()): + self.autoShootTimer.stop() + self.emit(QtCore.SIGNAL("missed()")) + self.emit(QtCore.SIGNAL("canShoot(bool)"), True) + else: + region = region.united(QtGui.QRegion(shotR)) + + self.update(region) + + def mousePressEvent(self, event): + if event.button() != QtCore.Qt.LeftButton: + return + if self.barrelHit(event.pos()): + self.barrelPressed = True + + def mouseMoveEvent(self, event): + if not self.barrelPressed: + return + pos = event.pos() + if pos.x() <= 0: + pos.setX(1) + if pos.y() >= self.height(): + pos.setY(self.height() - 1) + rad = math.atan((float(self.rect().bottom()) - pos.y()) / pos.x()) + self.setAngle(round(rad * 180 / 3.14159265)) + + def mouseReleaseEvent(self, event): + if event.button() == QtCore.Qt.LeftButton: + self.barrelPressed = False + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + + if self.gameEnded: + painter.setPen(QtCore.Qt.black) + painter.setFont(QtGui.QFont("Courier", 48, QtGui.QFont.Bold)) + painter.drawText(self.rect(), QtCore.Qt.AlignCenter, "Game Over") + + self.paintCannon(painter) + self.paintBarrier(painter) + if self.isShooting(): + self.paintShot(painter) + if not self.gameEnded: + self.paintTarget(painter) + + def paintShot(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.black) + painter.drawRect(self.shotRect()) + + def paintTarget(self, painter): + painter.setPen(QtCore.Qt.black) + painter.setBrush(QtCore.Qt.red) + painter.drawRect(self.targetRect()) + + def paintBarrier(self, painter): + painter.setPen(QtCore.Qt.black) + painter.setBrush(QtCore.Qt.yellow) + painter.drawRect(self.barrierRect()) + + barrelRect = QtCore.QRect(33, -4, 15, 8) + + def paintCannon(self, painter): + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.blue) + + painter.save() + painter.translate(0, self.height()) + painter.drawPie(QtCore.QRect(-35, -35, 70, 70), 0, 90 * 16) + painter.rotate(-self.currentAngle) + painter.drawRect(CannonField.barrelRect) + painter.restore() + + def cannonRect(self): + result = QtCore.QRect(0, 0, 50, 50) + result.moveBottomLeft(self.rect().bottomLect()) + return result + + def shotRect(self): + gravity = 4.0 + + time = self.timerCount / 40.0 + velocity = self.shootForce + radians = self.shootAngle * 3.14159265 / 180 + + velx = velocity * math.cos(radians) + vely = velocity * math.sin(radians) + x0 = (CannonField.barrelRect.right() + 5) * math.cos(radians) + y0 = (CannonField.barrelRect.right() + 5) * math.sin(radians) + x = x0 + velx * time + y = y0 + vely * time - 0.5 * gravity * time * time + + result = QtCore.QRect(0, 0, 6, 6) + result.moveCenter(QtCore.QPoint(round(x), self.height() - 1 - round(y))) + return result + + def targetRect(self): + result = QtCore.QRect(0, 0, 20, 10) + result.moveCenter(QtCore.QPoint(self.target.x(), self.height() - 1 - self.target.y())) + return result + + def barrierRect(self): + return QtCore.QRect(145, self.height() - 100, 15, 99) + + def barrelHit(self, pos): + matrix = QtGui.QTransform() + matrix.translate(0, self.height()) + matrix.rotate(-self.currentAngle) + matrix, invertible = matrix.inverted() + return self.barrelRect.contains(matrix.map(pos)) + + def gameOver(self): + return self.gameEnded + + def isShooting(self): + return self.autoShootTimer.isActive() + + def sizeHint(self): + return QtCore.QSize(400, 300) + + +class GameBoard(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("&Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + angle = LCDRange("ANGLE") + angle.setRange(5, 70) + + force = LCDRange("FORCE") + force.setRange(10, 50) + + cannonBox = QtWidgets.QFrame() + cannonBox.setFrameStyle(QtWidgets.QFrame.WinPanel | QtWidgets.QFrame.Sunken) + + self.cannonField = CannonField() + + self.connect(angle, QtCore.SIGNAL("valueChanged(int)"), + self.cannonField.setAngle) + self.connect(self.cannonField, QtCore.SIGNAL("angleChanged(int)"), + angle.setValue) + + self.connect(force, QtCore.SIGNAL("valueChanged(int)"), + self.cannonField.setForce) + self.connect(self.cannonField, QtCore.SIGNAL("forceChanged(int)"), + force.setValue) + + self.connect(self.cannonField, QtCore.SIGNAL("hit()"), self.hit) + self.connect(self.cannonField, QtCore.SIGNAL("missed()"), self.missed) + + shoot = QtWidgets.QPushButton("&Shoot") + shoot.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(shoot, QtCore.SIGNAL("clicked()"), self.fire) + self.connect(self.cannonField, QtCore.SIGNAL("canShoot(bool)"), + shoot, QtCore.SLOT("setEnabled(bool)")) + + restart = QtWidgets.QPushButton("&New Game") + restart.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(restart, QtCore.SIGNAL("clicked()"), self.newGame) + + self.hits = QtWidgets.QLCDNumber(2) + self.shotsLeft = QtWidgets.QLCDNumber(2) + hitsLabel = QtWidgets.QLabel("HITS") + shotsLeftLabel = QtWidgets.QLabel("SHOTS LEFT") + + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Enter), + self, self.fire) + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), + self, self.fire) + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_Q), + self, QtCore.SLOT("close()")) + + topLayout = QtWidgets.QHBoxLayout() + topLayout.addWidget(shoot) + topLayout.addWidget(self.hits) + topLayout.addWidget(hitsLabel) + topLayout.addWidget(self.shotsLeft) + topLayout.addWidget(shotsLeftLabel) + topLayout.addStretch(1) + topLayout.addWidget(restart) + + leftLayout = QtWidgets.QVBoxLayout() + leftLayout.addWidget(angle) + leftLayout.addWidget(force) + + cannonLayout = QtWidgets.QVBoxLayout() + cannonLayout.addWidget(self.cannonField) + cannonBox.setLayout(cannonLayout) + + gridLayout = QtWidgets.QGridLayout() + gridLayout.addWidget(quit, 0, 0) + gridLayout.addLayout(topLayout, 0, 1) + gridLayout.addLayout(leftLayout, 1, 0) + gridLayout.addWidget(cannonBox, 1, 1, 2, 1) + gridLayout.setColumnStretch(1, 10) + self.setLayout(gridLayout) + + angle.setValue(60) + force.setValue(25) + angle.setFocus() + + self.newGame() + + @QtCore.Slot() + def fire(self): + if self.cannonField.gameOver() or self.cannonField.isShooting(): + return + self.shotsLeft.display(self.shotsLeft.intValue() - 1) + self.cannonField.shoot() + + @QtCore.Slot() + def hit(self): + self.hits.display(self.hits.intValue() + 1) + if self.shotsLeft.intValue() == 0: + self.cannonField.setGameOver() + else: + self.cannonField.newTarget() + + @QtCore.Slot() + def missed(self): + if self.shotsLeft.intValue() == 0: + self.cannonField.setGameOver() + + @QtCore.Slot() + def newGame(self): + self.shotsLeft.display(15) + self.hits.display(0) + self.cannonField.restartGame() + self.cannonField.newTarget() + + +app = QtWidgets.QApplication(sys.argv) +board = GameBoard() +board.setGeometry(100, 100, 500, 355) +board.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t2.py b/examples/widgets/tutorials/cannon/t2.py new file mode 100644 index 000000000..d51986f47 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t2.py @@ -0,0 +1,59 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 2 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +app = QtWidgets.QApplication(sys.argv) + +quit = QtWidgets.QPushButton("Quit") +quit.resize(75, 30) +quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + +QtCore.QObject.connect(quit, QtCore.SIGNAL("clicked()"), + app, QtCore.SLOT("quit()")) + +quit.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t3.py b/examples/widgets/tutorials/cannon/t3.py new file mode 100644 index 000000000..fa96d6ff1 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t3.py @@ -0,0 +1,61 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 3 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +app = QtWidgets.QApplication(sys.argv) + +window = QtWidgets.QWidget() +window.resize(200, 120) + +quit = QtWidgets.QPushButton("Quit", window) +quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) +quit.setGeometry(10, 40, 180, 40) +QtCore.QObject.connect(quit, QtCore.SIGNAL("clicked()"), + app, QtCore.SLOT("quit()")) + +window.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t4.py b/examples/widgets/tutorials/cannon/t4.py new file mode 100644 index 000000000..4c30dfcbb --- /dev/null +++ b/examples/widgets/tutorials/cannon/t4.py @@ -0,0 +1,66 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 4 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.setFixedSize(200, 120) + + self.quit = QtWidgets.QPushButton("Quit", self) + self.quit.setGeometry(62, 40, 75, 30) + self.quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(self.quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t5.py b/examples/widgets/tutorials/cannon/t5.py new file mode 100644 index 000000000..af36578cd --- /dev/null +++ b/examples/widgets/tutorials/cannon/t5.py @@ -0,0 +1,77 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 5 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + lcd = QtWidgets.QLCDNumber(2) + + slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + slider.setRange(0, 99) + slider.setValue(0) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + self.connect(slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(quit) + layout.addWidget(lcd) + layout.addWidget(slider) + self.setLayout(layout) + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t6.py b/examples/widgets/tutorials/cannon/t6.py new file mode 100644 index 000000000..9094c0ce9 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t6.py @@ -0,0 +1,90 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 6 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + lcd = QtWidgets.QLCDNumber(2) + slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + slider.setRange(0, 99) + slider.setValue(0) + self.connect(slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(slider) + self.setLayout(layout) + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + grid = QtWidgets.QGridLayout() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(quit) + layout.addLayout(grid) + self.setLayout(layout) + for row in range(3): + for column in range(3): + grid.addWidget(LCDRange(), row, column) + + + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t7.py b/examples/widgets/tutorials/cannon/t7.py new file mode 100644 index 000000000..590bd516c --- /dev/null +++ b/examples/widgets/tutorials/cannon/t7.py @@ -0,0 +1,113 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 7 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + lcd = QtWidgets.QLCDNumber(2) + + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + self.setLayout(layout) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + grid = QtWidgets.QGridLayout() + previousRange = None + + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(quit) + layout.addLayout(grid) + self.setLayout(layout) + + for row in range(3): + for column in range(3): + lcdRange = LCDRange() + grid.addWidget(lcdRange, row, column) + + if previousRange: + self.connect(lcdRange, QtCore.SIGNAL("valueChanged(int)"), + previousRange.setValue) + + previousRange = lcdRange + + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t8.py b/examples/widgets/tutorials/cannon/t8.py new file mode 100644 index 000000000..3761b4353 --- /dev/null +++ b/examples/widgets/tutorials/cannon/t8.py @@ -0,0 +1,152 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 8 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + lcd = QtWidgets.QLCDNumber(2) + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + self.setLayout(layout) + + self.setFocusProxy(self.slider) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + def setRange(self, minValue, maxValue): + if minValue < 0 or maxValue > 99 or minValue > maxValue: + QtCore.qWarning("LCDRange.setRange(%d, %d)\n" + "\tRange must be 0..99\n" + "\tand minValue must not be greater than maxValue" % (minValue, maxValue)) + return + + self.slider.setRange(minValue, maxValue) + + +class CannonField(QtWidgets.QWidget): + angleChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.currentAngle = 45 + self.setPalette(QtGui.QPalette(QtGui.QColor(250, 250, 200))) + self.setAutoFillBackground(True) + + def angle(self): + return self.currentAngle + + @QtCore.Slot(int) + def setAngle(self, angle): + if angle < 5: + angle = 5 + if angle > 70: + angle = 70 + if self.currentAngle == angle: + return + self.currentAngle = angle + self.update() + self.emit(QtCore.SIGNAL("angleChanged(int)"), self.currentAngle) + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + painter.drawText(200, 200, "Angle = %d" % self.currentAngle) + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + angle = LCDRange() + angle.setRange(5, 70) + + cannonField = CannonField() + + self.connect(angle, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setAngle) + self.connect(cannonField, QtCore.SIGNAL("angleChanged(int)"), + angle.setValue) + + gridLayout = QtWidgets.QGridLayout() + gridLayout.addWidget(quit, 0, 0) + gridLayout.addWidget(angle, 1, 0) + gridLayout.addWidget(cannonField, 1, 1, 2, 1) + gridLayout.setColumnStretch(1, 10) + self.setLayout(gridLayout) + + angle.setValue(60) + angle.setFocus() + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.setGeometry(100, 100, 500, 355) +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/tutorials/cannon/t9.py b/examples/widgets/tutorials/cannon/t9.py new file mode 100644 index 000000000..ca949c1ac --- /dev/null +++ b/examples/widgets/tutorials/cannon/t9.py @@ -0,0 +1,159 @@ + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +# PySide6 tutorial 9 + + +import sys +from PySide6 import QtCore, QtGui, QtWidgets + + +class LCDRange(QtWidgets.QWidget): + valueChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + lcd = QtWidgets.QLCDNumber(2) + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setRange(0, 99) + self.slider.setValue(0) + + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + lcd, QtCore.SLOT("display(int)")) + self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), + self, QtCore.SIGNAL("valueChanged(int)")) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(lcd) + layout.addWidget(self.slider) + self.setLayout(layout) + + self.setFocusProxy(self.slider) + + def value(self): + return self.slider.value() + + @QtCore.Slot(int) + def setValue(self, value): + self.slider.setValue(value) + + def setRange(self, minValue, maxValue): + if minValue < 0 or maxValue > 99 or minValue > maxValue: + QtCore.qWarning("LCDRange::setRange(%d, %d)\n" + "\tRange must be 0..99\n" + "\tand minValue must not be greater than maxValue" % (minValue, maxValue)) + return + + self.slider.setRange(minValue, maxValue) + + +class CannonField(QtWidgets.QWidget): + angleChanged = QtCore.Signal(int) + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.currentAngle = 45 + self.setPalette(QtGui.QPalette(QtGui.QColor(250, 250, 200))) + self.setAutoFillBackground(True) + + def angle(self): + return self.currentAngle + + @QtCore.Slot(int) + def setAngle(self, angle): + if angle < 5: + angle = 5 + if angle > 70: + angle = 70 + if self.currentAngle == angle: + return + self.currentAngle = angle + self.update() + self.emit(QtCore.SIGNAL("angleChanged(int)"), self.currentAngle) + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(QtCore.Qt.blue) + + painter.translate(0, self.rect().height()) + painter.drawPie(QtCore.QRect(-35, -35, 70, 70), 0, 90 * 16) + painter.rotate(-self.currentAngle) + painter.drawRect(QtCore.QRect(33, -4, 15, 8)) + + +class MyWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + quit = QtWidgets.QPushButton("Quit") + quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) + + self.connect(quit, QtCore.SIGNAL("clicked()"), + qApp, QtCore.SLOT("quit()")) + + angle = LCDRange() + angle.setRange(5, 70) + + cannonField = CannonField() + + self.connect(angle, QtCore.SIGNAL("valueChanged(int)"), + cannonField.setAngle) + self.connect(cannonField, QtCore.SIGNAL("angleChanged(int)"), + angle.setValue) + + gridLayout = QtWidgets.QGridLayout() + gridLayout.addWidget(quit, 0, 0) + gridLayout.addWidget(angle, 1, 0) + gridLayout.addWidget(cannonField, 1, 1, 2, 1) + gridLayout.setColumnStretch(1, 10) + self.setLayout(gridLayout) + + angle.setValue(60) + angle.setFocus() + + +app = QtWidgets.QApplication(sys.argv) +widget = MyWidget() +widget.setGeometry(100, 100, 500, 355) +widget.show() +sys.exit(app.exec_()) diff --git a/examples/widgets/widgets/widgets.pyproject b/examples/widgets/widgets/widgets.pyproject deleted file mode 100644 index b4e3ef67e..000000000 --- a/examples/widgets/widgets/widgets.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["tetrix.py", "hellogl_openglwidget_legacy.py"] -} |