analitics

Pages

Friday, July 7, 2017

Python Qt4 - part 004.

Another tutorial about PyQt4 with QLCDNumber widget displays a number with LCD-like digits.
This tutorial will show you how to deal with this widget.
First, you need to know more about QLCDNumber, so take a look here.
The first example is very simple and will show just one digit, see:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Digit(QWidget):

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle("One digit")
        lcd = QLCDNumber(self)

app = QApplication(sys.argv)
ls = Digit()
ls.show()
sys.exit(app.exec_())
Now, the next step is to send data to this digit.
One good example is with one slider.
The position of the slider will be send to the QLCDNumber.
How can do that? Will need a vbox to put the QLCDNumber and the slider and then using signal and slot.
Let's see the example:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Digit(QWidget):

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        #make widgets
        self.setWindowTitle("One digit with slider")
        lcd = QLCDNumber(self)
        slider = QSlider(Qt.Horizontal, self)
        #set layout variable vbox
        vbox = QVBoxLayout()
        #add widgests
        vbox.addWidget(lcd)
        vbox.addWidget(slider)
        #set the vbox to layout
        self.setLayout(vbox)
        #create signal to slot
        self.connect(slider, SIGNAL("valueChanged(int)"),lcd, SLOT("display(int)"))
        self.resize(200, 170)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ls = Digit()
    ls.show()
    sys.exit(app.exec_())
In the source code in the example, you can see the comments that mark the steps of creating and executing the python script.
Let's try another example with a digital clock:
import sys
from PyQt4 import QtCore, QtGui

class digital_clock(QtGui.QLCDNumber):
    def __init__(self, parent=None):
        super(digital_clock, self).__init__(parent)
        self.setSegmentStyle(QtGui.QLCDNumber.Filled)
        #the defaul is 5 , change to 8 for seconds
        self.setDigitCount(5)
        self.setWindowTitle("Digital Clock")
        self.resize(200, 70)
        timer = QtCore.QTimer(self)
        timer.timeout.connect(self.showTime)
        timer.start(1000)
        self.showTime()

    def showTime(self):
        time = QtCore.QTime.currentTime()
        text = time.toString('hh:mm')
        #if you setDigitsCount to 8
        #uncomment the next line of code
        #text = time.toString('hh:mm:ss')
        if (time.second() % 2) == 0:
            text = text[:2] + ' ' + text[3:]
        self.display(text)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    clock = digital_clock()
    clock.show()
    sys.exit(app.exec_())
If you want to see seconds, then you need to set the digit count of the LCD to 8 ( it's 5 by default) of setDigitCount.
Also you need to uncomment this line of code: text = time.toString('hh:mm:ss') and comment the old one.
You can solve multiple issues with this widget, like: stopwatch, timer, clock down timer ...

Thursday, July 6, 2017

Python Qt4 - part 003.

Today I've taken a simple example with PyQt4 compared to the other tutorials we have done so far.
The main reason was to understand and use PyQt4 to display an important message.
To make this example I have set the following steps for my python program.
  • importing python modules
  • creating the application in PyQt4 as a tray icon class
  • establishing an exit from the application
  • setting up a message to display
  • display the message over a period of time
  • closing the application
  • running the python application
Let's see my source code of my python application:
#! /usr/bin/env python
import sys
from PyQt4 import QtGui, QtCore

class SystemTrayIcon(QtGui.QSystemTrayIcon):
    def __init__(self, parent=None):
        QtGui.QSystemTrayIcon.__init__(self, parent)
        self.setIcon(QtGui.QIcon("mess.svg"))
        menu = QtGui.QMenu(parent)
        exitAction = menu.addAction("Exit")
        self.setContextMenu(menu)
        QtCore.QObject.connect(exitAction,QtCore.SIGNAL('triggered()'), self.exit)

    def click_trap(self, value):
        if value == self.Trigger: #left click!
            self.left_menu.exec_(QtGui.QCursor.pos())

    def welcome(self):
        self.showMessage("Hello user!", "This is a message from PyQT4")

    def show(self):
        QtGui.QSystemTrayIcon.show(self)
        QtCore.QTimer.singleShot(600, self.welcome)

    def exit(self):
        QtCore.QCoreApplication.exit()

def main():
    app = QtGui.QApplication([])
    tray = SystemTrayIcon()
    tray.show()
    app.exec_()

if __name__ == '__main__':
    main()
I used PyQt4 python module to make the application and sys python module for exit from application.
About running application: the main function will run the application.
The python class SystemTrayIcon will work only if we used QApplication to make like any application.
This is the reason I used the variable app.
The tray variable is used to run it like tray icon application.
Into the SystemTrayIcon class, I put some functions to help me with my issue.
Under __init__ I used all settings for my tray icon application: the icon, the exit menu, signal for the exit.
The next functions come with:
  • click_trap - take the click of the user ;
  • welcome - make a message to display;
  • show - display the welcome message;
  • exit - exit from the application
The result of my python script is this message:

About the showMessage then this helps you:

QSystemTrayIcon.showMessage (self, QString title, QString msg, MessageIcon icon = QSystemTrayIcon.Information, int msecs = 10000)

Shows a balloon message for the entry with the given title, message and icon for the time specified in millisecondsTimeoutHint. title and message must be plain text strings.
The message can be clicked by the user; the messageClicked() signal will be emitted when this occurs.
Note that the display of messages is dependent on the system configuration and user preferences and that messages may not appear at all. Hence, it should not be relied upon as the sole means for providing critical information.
On Windows, the millisecondsTimeoutHint is usually ignored by the system when the application has focus.
On Mac OS X, the Growl notification system must be installed for this function to display messages.
This function was introduced in Qt 4.3.

Tuesday, July 4, 2017

The pdb python interactive debugging - part 001.

This is a short intro tutorial on python debugger to summarize this topic related to Python.
According to the development team, this python module called pdb has the following objectives:
The module pdb defines an interactive source code debugger for Python programs. It supports setting (conditional) breakpoints and single stepping at the source line level, inspection of stack frames, source code listing, and evaluation of arbitrary Python code in the context of any stack frame. It also supports post-mortem debugging and can be called under program control.

Let's start it with some example:
C:\Python27>python
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pdb
>>> pdb.pm()
Traceback (most recent call last):
  File "", line 1, in 
  File "C:\Python27\lib\pdb.py", line 1270, in pm
    post_mortem(sys.last_traceback)
AttributeError: 'module' object has no attribute 'last_traceback'
>>> import os
>>> pdb.pm()
> c:\python27\lib\pdb.py(1270)pm()
-> post_mortem(sys.last_traceback)
(Pdb) ?

Documented commands (type help ):
========================================
EOF    bt         cont      enable  jump  pp       run      unt
a      c          continue  exit    l     q        s        until
alias  cl         d         h       list  quit     step     up
args   clear      debug     help    n     r        tbreak   w
b      commands   disable   ignore  next  restart  u        whatis
break  condition  down      j       p     return   unalias  where

Miscellaneous help topics:
==========================
exec  pdb

Undocumented commands:
======================
retval  rv
As you can see, this module will work correctly with just another python module. In the example presented above is the os python module.
With the argument? we can see the commands that we can execute.
Let's see the list command ( l ):
(Pdb) l
1265        p = Pdb()
1266        p.reset()
1267        p.interaction(None, t)
1268
1269    def pm():
1270 ->     post_mortem(sys.last_traceback)
1271
1272
1273    # Main program for testing
1274
1275    TESTCMD = 'import x; x.main()'
You can see the pm function loaded by pdb python module.
Post-mortem debugging is a method that requires an environment that provides dynamic execution of code.
One of the greatest benefits of post-mortem debugging is that you can use it directly after something has gone wrong.
You can move between frames within the current call stack using up and down.
This moves towards older frames on the stack.
The debugger prints the current location with where, see example:
(Pdb) where
  (1)()
> c:\python27\lib\pdb.py(1270)pm()
-> post_mortem(sys.last_traceback)
To execute the current line and then stop at the next execution point use step.
The until command can be used to step past the end of a loop.
Use break command used for setting breakpoints, example: (Pdb) break 4.
Turning off a breakpoint with disabling tells the debugger not to stop when that line is reached, example: (Pdb) disable 1.
Also, we can have the other breakpoints like conditional breakpoints and temporary breakpoint.
Use clear to delete a breakpoint entirely.
Changing execution flow with the jump command lets you alter the flow of your program.
The jump can be ahead and back and moves the point of execution past the location without evaluating any of the statements in between.
We can also have illegal jumps in and out of certain flow control statements prevented by the debugger.
When the debugger reaches the end of your program, it automatically starts it over.
With run command, the program can be restarted.
We can avoid typing complex commands repeatedly by using alias and unalias to define the shortcuts.
The pdb python module lets you save configuration using text files read and interpreted on startup.

Friday, June 30, 2017

Blender 3D - bpy and scripting - part 001.

The tutorial for today is bpy python module used by Blender 3D software for scripting.
The last Application Programming Interface (A.P.I.) for Blender 3D can be found here.
You need to take a look at the link to see the base of this python module.
The example I will start today is a python script that helps me to deal with Blender 3D.
First I put the script named catafest.py into Blender 3D path: C:\Program Files\Blender Foundation\Blender\2.78\python\lib.
The reason is to be load by Blender 3D application.
Let's start with the script:
First, you need to import the Blender 3D python module named bpy.
This allows us to deal with Blender 3D using python and Application Programming Interface (A.P.I.).
The script is an example not a lib script for Blender 3D.
The goal of this script is to show how to deal with python scripting into Blender 3D.
If you want to make a lib for the Blender 3D then you need to read about Python’s standard library - here.
My script just creates materials. To do that I used functions to make materials - mat, set the material to the object - set_mat and the run function to see how is working.
Let's see the python script:
import bpy

def mat(name,df_col,df_sh,df_int,sp_col,sp_sh,sp_int,alp,amb):
    mat = bpy.data.materials.new(name)
    mat.diffuse_color = df_col
    mat.diffuse_shader = df_sh
    mat.diffuse_intensity = df_int
    mat.specular_color = sp_col
    mat.specular_shader = sp_sh
    mat.specular_intensity = sp_int
    mat.alpha = alp
    mat.ambient = amb
    return mat

def set_mat(ob, mat):
    me = ob.data
    me.materials.append(mat)

def run(origin):
    # create two materials
    red = mat('Red', (1,0,0),'LAMBERT',1.0,(1,1,1),'COOKTORR',0.5, 1,1)
    blue = mat('Green', (0,1,0),'LAMBERT',1.0,(0,0.5,0.5),'COOKTORR',0.5, 1, 0.5)

    # create red cube
    bpy.ops.mesh.primitive_cube_add(location=origin)
    set_mat(bpy.context.object, red)
    # create a green torus
    bpy.ops.mesh.primitive_torus_add(location=origin)
    bpy.ops.transform.translate(value=(1,0,0))
    set_mat(bpy.context.object, blue)

if __name__ == "__main__":
    run((0,0,0))
To run this script put the script into the lib path of Blender 3D software.
Open the Blender 3D and go to the scripting area:

Now about the source code of this script.
As you know the Blender 3D interface let you add and change objects and materials.
Each material comes with a name, colors with a diffuse and specular property, alpha color, ambient color, etc. see the documentation.
Some values come like strings and can get it from Blender 3D interface, see:
diffuse_shader 

and the
specular_shader
.
The set_mat function just load one object using: me = ob.data
Then put the material to object using append function.
The run function is used to show the result with how to make materials, create objects with this materials.
I run into Blender 3D - Console area:
YTHON INTERACTIVE CONSOLE 3.5.2 (default, Dec  1 2016, 20:58:16) [MSC v.1800 64 bit (AMD64)]

Command History:     Up/Down Arrow
Cursor:              Left/Right Home/End
Remove:              Backspace/Delete
Execute:             Enter
Autocomplete:        Ctrl-Space
Zoom:                Ctrl +/-, Ctrl-Wheel
Builtin Modules:     bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bpy.utils, bgl, blf, mathutils
Convenience Imports: from mathutils import *; from math import *
Convenience Variables: C = bpy.context, D = bpy.data

>>> import catafest 
>>> dir(catafest)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__',
 'bpy', 'mat', 'run', 'set_mat']

>>> catafest.run((0,0,0))
This is the result of the script:





Wednesday, June 28, 2017

The Google API Client Library python module.

This python module named Google API Client Library for Python is a client library for accessing the Plus, Moderator, and many other Google APIs, according to the official link.
C:\Python27\Scripts>pip install --upgrade google-api-python-client
Collecting google-api-python-client
  Downloading google_api_python_client-1.6.2-py2.py3-none-any.whl (52kB)
    100% |################################| 61kB 426kB/s
...
Successfully installed google-api-python-client-1.6.2 ...
The example I used is this:
from oauth2client.client import flow_from_clientsecrets
import httplib2
import apiclient
from apiclient.discovery import build
from oauth2client.file import Storage
import webbrowser

def get_credentials():
    scope = 'https://www.googleapis.com/auth/blogger'
    flow = flow_from_clientsecrets(
        'client_id.json', scope,
        redirect_uri='urn:ietf:wg:oauth:2.0:oob')
    storage = Storage('credentials.dat')
    credentials = storage.get()

    if  not credentials or credentials.invalid:
        auth_uri = flow.step1_get_authorize_url()
        webbrowser.open(auth_uri)
        auth_code = raw_input('Enter the auth code: ')
        credentials = flow.step2_exchange(auth_code)
        storage.put(credentials)
    return credentials

def get_service():
    """Returns an authorised blogger api service."""
    credentials = get_credentials()
    http = httplib2.Http()
    http = credentials.authorize(http)
    service = apiclient.discovery.build('blogger', 'v3', http=http)
    return service

if __name__ == '__main__':
    served = get_service()
    print dir(served.blogs)
    users = served.users()

    # Retrieve this user's profile information
    thisuser = users.get(userId='self').execute()
    print('This user\'s display name is: %s' % thisuser['displayName'].encode('utf-8'))

    blogs = served.blogs()

    # Retrieve the list of Blogs this user has write privileges on
    thisusersblogs = blogs.listByUser(userId='self').execute()
    for blog in thisusersblogs['items']:
        print('The blog named \'%s\' is at: %s' % (blog['name'], blog['url']))
The result of this script is this:
C:\Python27>python.exe google_001.py
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__func__', 
'__get__', '__getattribute__', '__hash__', '__init__', '__is_resource__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', 
'__str__', '__subclasshook__', 'im_class', 'im_func', 'im_self']
This user's display name is: Cătălin George Feștilă
The blog named 'python-catalin' is at: http://python-catalin.blogspot.com/
The blog named 'graphics' is at: http://graphic-3d.blogspot.com/
The blog named 'About me and my life ...' is at: http://catalin-festila.blogspot.com/
The blog named 'pygame-catalin' is at: http://pygame-catalin.blogspot.com/
About google settings then you need to have a google account to use Google’s API.
The first step for accessing the Google Developer’s Console.
Then navigate to the Developer Console’s projects page and create a new project for our application by clicking the Create project button and then enable blogger API.
Enter your projects name and hit create.
Click the Go to Credentials button with these settings like in the next image:

Download this credential information in JSON format, in this case, is the client_id.json file.
When you run for the first time this script you will see an open HTML page with your auth code.
The script example named google_001.py will come with this message:
C:\Python27>python.exe google_001.py
C:\Python27\lib\site-packages\oauth2client\_helpers.py:255: UserWarning: Cannot access credentials.dat: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))
Enter the auth code:
Put this auth code and allow the script using the open page and your google account using Allow button.
Now you can run the example.