Commit 94c7b22f authored by Wichit Sombat's avatar Wichit Sombat

add ubuscribble to Session-3

parent 70c7431e
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
.static_storage/
.media/
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# Make Scribble Module with PyQt5
1. install cookiecutter
```sh
pip install --user cookiecutter
```
2. create project using cookiecutter
```sh
cookiecutter https://github.com/globality-corp/cookiecutter-python-library.git
```
3. enter the following information
```txt
author [Globality Engineering]: Benjama EEP
author_email [engineering@globality.com]: benjama.eep@benjama.edu
organization_name [globality-corp]: benjama.eep
repo_name [repo_name]: ubuscribble
project_name [project_name]: ubuscribble
project_version [0.1.0]: <enter>
short_description [Short Project Description]: scribble widget for pyqt5
```
4. build and install
```sh
cd ubuscribble/
python3 setup.py install --user
```
5. run
```sh
BenApp
```
# Desktop Application Development with PyQt5
1. install cookiecutter
```sh
pip install --user cookiecutter
```
2. create project using cookiecutter
```sh
cookiecutter https://github.com/mandeep/cookiecutter-pyqt5.git
```
3. enter the following information
```txt
full_name [Mandeep]: Benjama EEP
email [info@mandeep.xyz]: benjama.eep@benjama.edu
github_username [mandeep]: benjama.eep
repo_name [cookiecutter-pyqt5]: ubuworkshop
package_name [cookiecutter-pyqt5]: workshopapp
application_name [application]: workshopapp
application_title [Template]: BenApp
project_short_description [A PyQt5 GUI application]: Desktop Application
version [0.0.1]: <enter>
insert_toolbar [yes]: <enter>
insert_statusbar [yes]: <enter>
```
4. build and install
```sh
cd workshopapp/
python3 setup.py install --user
```
5. run
```sh
BenApp
```
#!/usr/bin/python3
from PyQt5.QtWidgets import QAction, QMenu, QMainWindow, QApplication, QMessageBox, QFileDialog, QInputDialog
from PyQt5.QtGui import QImage, QImageWriter
from PyQt5.QtCore import QDir
from ubuscribble.scribble import Scribble
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.saveAsActs = []
self.scribble= Scribble()
self.setCentralWidget(self.scribble)
self.createActions()
self.createMenus()
self.setWindowTitle("Scribble")
self.resize(500, 500)
def closeEvent(self, event):
if self.maybeSave():
event.accept()
else:
event.ignore()
def open(self):
if self.maybeSave():
fileName, _ = QFileDialog.getOpenFileName(self, "Open File",
QDir.currentPath())
if fileName:
self.scribble.openImage(fileName)
def save(self):
action = self.sender()
fileFormat = action.data()
self.saveFile(fileFormat)
def penColor(self):
newColor = QColorDialog.getColor(self.scribble.penColor())
if newColor.isValid():
self.scribble.setPenColor(newColor)
def penWidth(self):
newWidth, ok = QInputDialog.getInt(self, "Scribble",
"Select pen width:", self.scribble.penWidth(), 1, 50, 1)
if ok:
self.scribble.setPenWidth(newWidth)
def about(self):
QMessageBox.about(self, "About Scribble",
"<p>The <b>Scribble</b> example shows how to use "
"QMainWindow as the base widget for an application, and how "
"to reimplement some of QWidget's event handlers to receive "
"the events generated for the application's widgets:</p>"
"<p> We reimplement the mouse event handlers to facilitate "
"drawing, the paint event handler to update the application "
"and the resize event handler to optimize the application's "
"appearance. In addition we reimplement the close event "
"handler to intercept the close events before terminating "
"the application.</p>"
"<p> The example also demonstrates how to use QPainter to "
"draw an image in real time, as well as to repaint "
"widgets.</p>")
def createActions(self):
self.openAct = QAction("&Open...", self, shortcut="Ctrl+O",
triggered=self.open)
for format in QImageWriter.supportedImageFormats():
format = str(format)
text = format.upper() + "..."
action = QAction(text, self, triggered=self.save)
action.setData(format)
self.saveAsActs.append(action)
self.printAct = QAction("&Print...", self,
triggered=self.scribble.print_)
self.exitAct = QAction("E&xit", self, shortcut="Ctrl+Q",
triggered=self.close)
self.penColorAct = QAction("&Pen Color...", self,
triggered=self.penColor)
self.penWidthAct = QAction("Pen &Width...", self,
triggered=self.penWidth)
self.clearScreenAct = QAction("&Clear Screen", self, shortcut="Ctrl+L",
triggered=self.scribble.clearImage)
self.aboutAct = QAction("&About", self, triggered=self.about)
self.aboutQtAct = QAction("About &Qt", self,
triggered=QApplication.instance().aboutQt)
def createMenus(self):
self.saveAsMenu = QMenu("&Save As", self)
for action in self.saveAsActs:
self.saveAsMenu.addAction(action)
fileMenu = QMenu("&File", self)
fileMenu.addAction(self.openAct)
fileMenu.addMenu(self.saveAsMenu)
fileMenu.addAction(self.printAct)
fileMenu.addSeparator()
fileMenu.addAction(self.exitAct)
optionMenu = QMenu("&Options", self)
optionMenu.addAction(self.penColorAct)
optionMenu.addAction(self.penWidthAct)
optionMenu.addSeparator()
optionMenu.addAction(self.clearScreenAct)
helpMenu = QMenu("&Help", self)
helpMenu.addAction(self.aboutAct)
helpMenu.addAction(self.aboutQtAct)
self.menuBar().addMenu(fileMenu)
self.menuBar().addMenu(optionMenu)
self.menuBar().addMenu(helpMenu)
def maybeSave(self):
if self.scribble.isModified():
ret = QMessageBox.warning(self, "Scribble",
"The image has been modified.\n"
"Do you want to save your changes?",
QMessageBox.Save | QMessageBox.Discard |
QMessageBox.Cancel)
if ret == QMessageBox.Save:
return self.saveFile('png')
elif ret == QMessageBox.Cancel:
return False
return True
def saveFile(self, fileFormat):
initialPath = QDir.currentPath() + '/untitled.' + fileFormat
fileName, _ = QFileDialog.getSaveFileName(self, "Save As", initialPath,
"%s Files (*.%s);;All Files (*)" % (fileFormat.upper(), fileFormat))
if fileName:
return self.scribble.saveImage(fileName, fileFormat)
return False
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
# Always color, even if piping to a another program
--color
# Python project settings
--ignore-dir=.eggs/
--ignore-dir=.tox/
--ignore-dir=build/
--ignore-dir=cover/
[bumpversion]
current_version = 0.1.0
commit = False
tag = False
[bumpversion:file:setup.py]
search = version = "{current_version}"
replace = version = "{new_version}"
##
# .gitignore
#
# Based on:
#
# https://github.com/github/gitignore/blob/master/Global/OSX.gitignore
# https://github.com/github/gitignore/blob/master/Python.gitignore
##
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
extends: globality-opensource-defaults
This diff is collapsed.
# ubuscribble
scribble widget for pyqt5
[![Circle CI](https://circleci.com/gh/benjama.eep/ubuscribble/tree/develop.svg?style=svg)](https://circleci.com/gh/benjama.eep/ubuscribble/tree/develop)
# CircleCI Configuration file
machine:
python:
version: 2.7.11
general:
artifacts:
- "dist"
- "cover"
dependencies:
override:
- pip install tox tox-pyenv
- pyenv local 2.7.11 3.5.1 # Should correspond to pre-installed Python versions on CircleCI
test:
override:
- tox
deployment:
pypi:
tag: /[0-9]+(\.[0-9]+)*/
owner: benjama.eep
commands:
- echo "[distutils]" > ~/.pypirc
- echo "index-servers =" >> ~/.pypirc
- echo " pypi" >> ~/.pypirc
- echo >> ~/.pypirc
- echo "[pypi]" >> ~/.pypirc
- echo "username:$PYPI_USERNAME" >> ~/.pypirc
- echo "password:$PYPI_PASSWORD" >> ~/.pypirc
- echo >> ~/.pypirc
- python setup.py register -r pypi
- python setup.py sdist upload -r pypi
[flake8]
max-line-length = 120
max-complexity = 15
#!/usr/bin/env python
from setuptools import find_packages, setup
project = "ubuscribble"
version = "0.1.0"
setup(
name=project,
version=version,
description="scribble widget for pyqt5",
author="Benjama EEP",
author_email="benjama.eep@benjama.edu",
url="https://github.com/benjama.eep/ubuscribble",
packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
include_package_data=True,
zip_safe=False,
install_requires=[
"PyQt5>=5.9"
],
setup_requires=[
"nose>=1.3.6",
],
dependency_links=[
],
entry_points={
},
tests_require=[
"coverage>=3.7.1",
"mock>=1.0.1",
"PyHamcrest>=1.8.5",
],
)
[tox]
envlist = py27, py35, lint
[testenv]
commands =
python setup.py nosetests --with-coverage --cover-package=ubuscribble --cover-erase --cover-html
python setup.py sdist
deps =
setuptools>=17.1
[testenv:lint]
commands=flake8 ubuscribble
basepython=python2.7
deps=
flake8
flake8-print
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
## All rights reserved.
##
## This file is part of the examples of PyQt.
##
## $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 Nokia Corporation and its Subsidiary(-ies) 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$
##
#############################################################################
from PyQt5.QtCore import QDir, QPoint, QRect, QSize, Qt
from PyQt5.QtGui import QImage, QImageWriter, QPainter, QPen, qRgb
from PyQt5.QtWidgets import (QAction, QApplication, QColorDialog, QFileDialog,
QInputDialog, QMainWindow, QMenu, QMessageBox, QWidget)
from PyQt5.QtPrintSupport import QPrintDialog, QPrinter
class Scribble(QWidget):
def __init__(self, parent=None):
super(Scribble, self).__init__(parent)
self.setAttribute(Qt.WA_StaticContents)
self.modified = False
self.scribbling = False
self.myPenWidth = 1
self.myPenColor = Qt.blue
self.image = QImage()
self.lastPoint = QPoint()
def openImage(self, fileName):
loadedImage = QImage()
if not loadedImage.load(fileName):
return False
newSize = loadedImage.size().expandedTo(self.size())
self.resizeImage(loadedImage, newSize)
self.image = loadedImage
self.modified = False
self.update()
return True
def saveImage(self, fileName, fileFormat):
visibleImage = self.image
self.resizeImage(visibleImage, self.size())
if visibleImage.save(fileName, fileFormat):
self.modified = False
return True
else:
return False
def setPenColor(self, newColor):
self.myPenColor = newColor
def setPenWidth(self, newWidth):
self.myPenWidth = newWidth
def clearImage(self):
self.image.fill(qRgb(255, 255, 255))
self.modified = True
self.update()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.lastPoint = event.pos()
self.scribbling = True
def mouseMoveEvent(self, event):
if (event.buttons() & Qt.LeftButton) and self.scribbling:
self.drawLineTo(event.pos())
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton and self.scribbling:
self.drawLineTo(event.pos())
self.scribbling = False
def paintEvent(self, event):
painter = QPainter(self)
dirtyRect = event.rect()
painter.drawImage(dirtyRect, self.image, dirtyRect)
def resizeEvent(self, event):
if self.width() > self.image.width() or self.height() > self.image.height():
newWidth = max(self.width() + 128, self.image.width())
newHeight = max(self.height() + 128, self.image.height())
self.resizeImage(self.image, QSize(newWidth, newHeight))
self.update()
super(Scribble, self).resizeEvent(event)
def drawLineTo(self, endPoint):
painter = QPainter(self.image)
painter.setPen(QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine,
Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.lastPoint, endPoint)
self.modified = True
rad = self.myPenWidth / 2 + 2
self.update(QRect(self.lastPoint, endPoint).normalized().adjusted(-rad, -rad, +rad, +rad))
self.lastPoint = QPoint(endPoint)
def resizeImage(self, image, newSize):
if image.size() == newSize:
return
newImage = QImage(newSize, QImage.Format_RGB32)
newImage.fill(qRgb(255, 255, 255))
painter = QPainter(newImage)
painter.drawImage(QPoint(0, 0), image)
self.image = newImage
def print_(self):
printer = QPrinter(QPrinter.HighResolution)
printDialog = QPrintDialog(printer, self)
if printDialog.exec_() == QPrintDialog.Accepted:
painter = QPainter(printer)
rect = painter.viewport()
size = self.image.size()
size.scale(rect.size(), Qt.KeepAspectRatio)
painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
painter.setWindow(self.image.rect())
painter.drawImage(0, 0, self.image)
painter.end()
def isModified(self):
return self.modified
def penColor(self):
return self.myPenColor
def penWidth(self):
return self.myPenWidth
"""
Example test.
"""
from hamcrest import (
assert_that,
equal_to,
is_,
)
def test_math():
assert_that(1 + 1, is_(equal_to(2)))
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Config file for automatic testing at travis-ci.org
language: python
python:
- "3.4_with_system_site_packages"
sudo: required
dist: trusty
notifications:
email: false
sudo: required
before_install:
- sudo apt-get update
- sudo apt-get install -y xvfb python3-pyqt5 python3-pyqt5.qtmultimedia
install:
- python setup.py install
- pip install coverage
- pip install coveralls
- pip install pytest
- pip install pytest-cov
- pip install pytest-faulthandler
- pip install pytest-mock
- pip install pytest-qt
- pip install pytest-xvfb
script:
- py.test -s -v --cov=./
after_success:
- coveralls
\ No newline at end of file
This diff is collapsed.
===============================
workshopapp
===============================
.. image:: https://img.shields.io/travis/benjama.eep/ubuworkshop.svg
:target: https://travis-ci.org/benjama.eep/ubuworkshop
Desktop Application
Features
--------
* TODO
Credits
---------
This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
[pytest]
testpaths = workshopapp/tests/
from setuptools import setup
requirements = [
# TODO: put your package requirements here
]
test_requirements = [
'pytest',
'pytest-cov',
'pytest-faulthandler',
'pytest-mock',
'pytest-qt',
'pytest-xvfb',
]
setup(
name='ubuworkshop',
version='0.0.1',
description="Desktop Application",
author="Benjama EEP",
author_email='benjama.eep@benjama.edu',
url='https://github.com/benjama.eep/ubuworkshop',
packages=['workshopapp', 'workshopapp.images',
'workshopapp.tests'],
package_data={'workshopapp.images': ['*.png']},
entry_points={
'console_scripts': [
'BenApp=workshopapp.workshopapp:main'
]
},
install_requires=requirements,
zip_safe=False,
keywords='ubuworkshop',
classifiers=[
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
test_suite='tests',
tests_require=test_requirements
)
import pytest
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QFileDialog
from workshopapp import workshopapp
@pytest.fixture
def window(qtbot):
"""Pass the application to the test functions via a pytest fixture."""
new_window = workshopapp.BenApp()
qtbot.add_widget(new_window)
new_window.show()
return new_window
def test_window_title(window):
"""Check that the window title shows as declared."""
assert window.windowTitle() == 'BenApp'
def test_window_geometry(window):
"""Check that the window width and height are set as declared."""
assert window.width() == 1024
assert window.height() == 768
def test_open_file(window, qtbot, mock):
"""Test the Open File item of the File submenu.
Qtbot clicks on the file sub menu and then navigates to the Open File item. Mock creates
an object to be passed to the QFileDialog.
"""
qtbot.mouseClick(window.file_sub_menu, Qt.LeftButton)
qtbot.keyClick(window.file_sub_menu, Qt.Key_Down)
mock.patch.object(QFileDialog, 'getOpenFileName', return_value=('', ''))
qtbot.keyClick(window.file_sub_menu, Qt.Key_Enter)
def test_about_dialog(window, qtbot, mock):
"""Test the About item of the Help submenu.
Qtbot clicks on the help sub menu and then navigates to the About item. Mock creates
a QDialog object to be used for the test.
"""
qtbot.mouseClick(window.help_sub_menu, Qt.LeftButton)
qtbot.keyClick(window.help_sub_menu, Qt.Key_Down)
mock.patch.object(QDialog, 'exec_', return_value='accept')
qtbot.keyClick(window.help_sub_menu, Qt.Key_Enter)
import sys
import pkg_resources
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (QAction, QApplication, QDesktopWidget, QDialog, QFileDialog,
QHBoxLayout, QLabel, QMainWindow, QToolBar, QVBoxLayout, QWidget)
class BenApp(QMainWindow):
"""Create the main window that stores all of the widgets necessary for the application."""
def __init__(self, parent=None):
"""Initialize the components of the main window."""
super(BenApp, self).__init__(parent)
self.resize(1024, 768)
self.setWindowTitle('BenApp')
window_icon = pkg_resources.resource_filename('workshopapp.images',
'ic_insert_drive_file_black_48dp_1x.png')
self.setWindowIcon(QIcon(window_icon))
self.widget = QWidget()
self.layout = QHBoxLayout(self.widget)
self.menu_bar = self.menuBar()
self.about_dialog = AboutDialog()
self.status_bar = self.statusBar()
self.status_bar.showMessage('Ready', 5000)
self.file_menu()
self.help_menu()
self.tool_bar_items()
def file_menu(self):
"""Create a file submenu with an Open File item that opens a file dialog."""
self.file_sub_menu = self.menu_bar.addMenu('File')
self.open_action = QAction('Open File', self)
self.open_action.setStatusTip('Open a file into BenApp.')
self.open_action.setShortcut('CTRL+O')
self.open_action.triggered.connect(self.open_file)
self.exit_action = QAction('Exit Application', self)
self.exit_action.setStatusTip('Exit the application.')
self.exit_action.setShortcut('CTRL+Q')
self.exit_action.triggered.connect(lambda: QApplication.quit())
self.file_sub_menu.addAction(self.open_action)
self.file_sub_menu.addAction(self.exit_action)
def help_menu(self):
"""Create a help submenu with an About item tha opens an about dialog."""
self.help_sub_menu = self.menu_bar.addMenu('Help')
self.about_action = QAction('About', self)
self.about_action.setStatusTip('About the application.')
self.about_action.setShortcut('CTRL+H')
self.about_action.triggered.connect(lambda: self.about_dialog.exec_())
self.help_sub_menu.addAction(self.about_action)
def tool_bar_items(self):
"""Create a tool bar for the main window."""
self.tool_bar = QToolBar()
self.addToolBar(Qt.TopToolBarArea, self.tool_bar)
self.tool_bar.setMovable(False)
open_icon = pkg_resources.resource_filename('workshopapp.images',
'ic_open_in_new_black_48dp_1x.png')
tool_bar_open_action = QAction(QIcon(open_icon), 'Open File', self)
tool_bar_open_action.triggered.connect(self.open_file)
self.tool_bar.addAction(tool_bar_open_action)
def open_file(self):
"""Open a QFileDialog to allow the user to open a file into the application."""
filename, accepted = QFileDialog.getOpenFileName(self, 'Open File')
if accepted:
with open(filename) as file:
file.read()
class AboutDialog(QDialog):
"""Create the necessary elements to show helpful text in a dialog."""
def __init__(self, parent=None):
"""Display a dialog that shows application information."""
super(AboutDialog, self).__init__(parent)
self.setWindowTitle('About')
help_icon = pkg_resources.resource_filename('workshopapp.images',
'ic_help_black_48dp_1x.png')
self.setWindowIcon(QIcon(help_icon))
self.resize(300, 200)
author = QLabel('Benjama EEP')
author.setAlignment(Qt.AlignCenter)
icons = QLabel('Material design icons created by Google')
icons.setAlignment(Qt.AlignCenter)
github = QLabel('GitHub: benjama.eep')
github.setAlignment(Qt.AlignCenter)
self.layout = QVBoxLayout()
self.layout.setAlignment(Qt.AlignVCenter)
self.layout.addWidget(author)
self.layout.addWidget(icons)
self.layout.addWidget(github)
self.setLayout(self.layout)
def main():
application = QApplication(sys.argv)
window = BenApp()
desktop = QDesktopWidget().availableGeometry()
width = (desktop.width() - window.width()) / 2
height = (desktop.height() - window.height()) / 2
window.show()
window.move(width, height)
sys.exit(application.exec_())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment