Reply
Thread Tools
Posts: 1,086 | Thanked: 2,964 times | Joined on Jan 2010
#1
The finished app, a list of fart sounds to choose from on the left and a big dangerous red push button on the right..



This is a beginner tutorial in association with the N900 coding competition , running til July 21st. Please get involved

This tutorial covers:

• GUI creation with Qt Designer
• Sound playback with phonon
• Getting around the lack of a switch/case statement in python
• The mystical art of naming fart sounds

Pre-requisites:

If you are a beginner please go through the starter tutorials from MikeC and FatalSaint first, which are both many times more informative and better thought out than this one and will also help get your environments set up.

• MikeC - http://talk.maemo.org/showthread.php?t=43663
• FatalSaint - http://talk.maemo.org/showpost.php?p...8&postcount=59
• Python and PyQt should be installed correctly on your PC and n900
• You should have WinSCP on your PC and OpenSSH client-server on your n900 (or equivalents) for copying the files over.

Caveats

I am also a beginner, this tutorial is put out there in the hope it helps but should not be seen as well written or particularly ‘good’.


Step 1:
Go and grab yourself 5 or 6 fart sounds from the internet. A simple google search should find plenty of .wav farting audible goodness, e.g. http://www.fartgreetings.com/fartwavs.asp might be a start. Or you can use the ones I have attached in the zip file.

Step 2:
Fire up your copy of Qt Designer, from the first dialog choose the Main Window template and set the canvas size to 800*400. We only need two widgets - a List Widget, which is used to select the fart sound, and a Push Button widget to trigger the sound to be played. Drag both widgets onto the canvas, with the list to the left and the button to the right. Space them out and resize them until you’re happy with how they look. For more info on using a layout and use of spacings see FatalSaint’s tutorial linked at the beginning.



Step 3:
Left click on the List Widget, and in the Property Editor change it’s name to ‘soundList’. Then right click on the List Widget and choose “Edit Items” from the mouse’s popup menu. A small window called the “Edit List Widget” will appear, and this is where you enter the fart names that the user will see and click on. Click on the green + symbol on the bottom left corner of the widget and add a name for each of the fart sounds you have gathered from step 1. You can also set the properties for each list item, I have chosen text size 14 and centered. Click OK when finished.



Step 4:
Left click on the Push Button widget, and change it’s name to ‘pushbutton’ in the Property Editor. I have also changed the font size to 33 and the text to read “Fart!”. In addition, by clicking on the styleSheet property you can bring up the Style Sheet Editor widget window to assign a colour to the button, in this case I have chosen a dangerous hue of red.



Step 5:
That is the GUI designed, save (File->Save As) the project as maeFart.ui and close down Qt Designer out of your way. Next we use pyuic4 to generate our python code. Open up a command line prompt, and CD into the folder you have saved the maeFart.ui file. From there, type:

Code:
pyuic4 maeFart.ui -o maeFart.py


Step 6:
We now have our python GUI, we need a main to call it. Create a new python file called main.py and copy in the following code:

Code:
#!/usr/bin/python2.5
import sys
from PyQt4 import QtGui,QtCore
from maeFart import *

class MyForm(QtGui.QMainWindow):
        def __init__(self, parent=None):
                #build parent user interface
                QtGui.QWidget.__init__(self, parent)
                self.ui = Ui_MainWindow()
                self.ui.setupUi(self)
                #set the first item in the soundList as the currently selected fart sound
                self.ui.soundList.setCurrentRow(0)         

if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        myapp = MyForm()
        myapp.show()
        sys.exit(app.exec_())

Step7:
Qt uses the Phonon multimedia framework and can playback most of the common multimedia formats. The architecture of Phonon is that, when playing back audio, you create a media object and connect it via a path to an audio output node, which ouputs audio to the sound card or device.



First step to using phonon is to import it into our project, so at the top add:

Code:
from PyQt4.phonon import Phonon
The we create the media object and the audio output in the initialization, by placing these lines just below the GUI setup commands:

Code:
                self.m_media = Phonon.MediaObject(self)
                audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
                Phonon.createPath(self.m_media, audioOutput)
Step 8:
Connecting the button. We will write a method called playFart(), triggered by the pushButton, that will play the fart sound. First we need to hook up the “clicked()” signal of the button to call the method as so:

Code:
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL('clicked()'), self.playFart)
Step 9:
Implementing the playFart method by adding the following code to the main.py file

Code:
def playFart(self):
	    #get the file name of the selected fart sound
                fart=self.farts[str(self.ui.soundList.currentItem().text())]
           self.m_media.setCurrentSource(Phonon.MediaSource(fart))
                self.m_media.play()
The first line reads the currently selected item from the list menu, converts it to a python string (using str() ), and uses that string as a key to return the file name from a dictionary called ‘farts’.

Code:
self.farts={
                "Little Fart":"fart1.wav", "Brown Fart":"fart2.wav",
                "Wet Fart":"fart3.wav", "Baby Fart":"fart4.wav",
                "Lots of Farts":"fart5.wav"
                 }
In Java or C++ we might have used a CASE or switch statement, however Python does not have this functionality. A series of “if.. else” could have been used, but in this case a dictionary just seemed neater to me.

In this case the dictionary only contains keys and the associated filenames as the sound files will be placed in the same folder as the main.py file, otherwise the path would also need to be added to the filenames.

Step 10:
The completed files maeFart.py and main.py should look as follows, test them out locally and make sure everything is ok.

main.py
Code:
#!/usr/bin/python2.5
import sys
from PyQt4 import QtGui,QtCore
from PyQt4.phonon import Phonon
from maeFart import *

class MyForm(QtGui.QMainWindow):
        def __init__(self, parent=None):
                #build parent user interface
                QtGui.QWidget.__init__(self, parent)
                self.ui = Ui_MainWindow()
                self.ui.setupUi(self)
                self.ui.soundList.setCurrentRow(0)
                self.m_media = Phonon.MediaObject(self)
                audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
                Phonon.createPath(self.m_media, audioOutput)
                #connect buttons
                QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL('clicked()'), self.playFart)
                
                self.farts={
                        "Little Fart":"fart1.wav", "Brown Fart":"fart2.wav",
                        "Wet Fart":"fart3.wav", "Baby Fart":"fart4.wav",
                        "Lots of Farts":"fart5.wav"
                        }
                
        def playFart(self):
                fart=self.farts[str(self.ui.soundList.currentItem().text())]
                self.m_media.setCurrentSource(Phonon.MediaSource(fart))
                self.m_media.play()
                        

if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        myapp = MyForm()
        myapp.show()
        sys.exit(app.exec_())
maeFart.py
Code:
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'maeFart.ui'
#
# Created: Fri May 28 22:49:14 2010
#      by: PyQt4 UI code generator 4.7
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 400)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.frame = QtGui.QFrame(self.centralwidget)
        self.frame.setGeometry(QtCore.QRect(50, 0, 701, 361))
        self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtGui.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.pushButton = QtGui.QPushButton(self.frame)
        self.pushButton.setGeometry(QtCore.QRect(410, 60, 231, 221))
        font = QtGui.QFont()
        font.setPointSize(33)
        self.pushButton.setFont(font)
        self.pushButton.setStyleSheet("background-color: rgb(255, 0, 0);")
        self.pushButton.setObjectName("pushButton")
        self.soundList = QtGui.QListWidget(self.frame)
        self.soundList.setGeometry(QtCore.QRect(60, 10, 256, 341))
        self.soundList.setObjectName("soundList")
        QtGui.QListWidgetItem(self.soundList)
        QtGui.QListWidgetItem(self.soundList)
        QtGui.QListWidgetItem(self.soundList)
        QtGui.QListWidgetItem(self.soundList)
        QtGui.QListWidgetItem(self.soundList)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "maeFart", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton.setText(QtGui.QApplication.translate("MainWindow", "Fart!", None, QtGui.QApplication.UnicodeUTF8))
        __sortingEnabled = self.soundList.isSortingEnabled()
        self.soundList.setSortingEnabled(False)
        self.soundList.item(0).setText(QtGui.QApplication.translate("MainWindow", "Little Fart", None, QtGui.QApplication.UnicodeUTF8))
        self.soundList.item(1).setText(QtGui.QApplication.translate("MainWindow", "Brown Fart", None, QtGui.QApplication.UnicodeUTF8))
        self.soundList.item(2).setText(QtGui.QApplication.translate("MainWindow", "Wet Fart", None, QtGui.QApplication.UnicodeUTF8))
        self.soundList.item(3).setText(QtGui.QApplication.translate("MainWindow", "Baby Fart", None, QtGui.QApplication.UnicodeUTF8))
        self.soundList.item(4).setText(QtGui.QApplication.translate("MainWindow", "Lots of Farts", None, QtGui.QApplication.UnicodeUTF8))
        self.soundList.setSortingEnabled(__sortingEnabled)
Step 11:
Use WinSCP and OpenSSH to transfer the files into your N900’s Opt directory. To run, open Xterm and cd into the opt directory and run the main.py file.

Code:
cd /opt
python main.py
The application will open in a new window...


That's it for now.. happy farting!
Attached Files
File Type: zip maeFart.zip (183.9 KB, 621 views)
__________________
Follow me on my neglected twitter @kojacker

Cybot950 - Control a robot with your N9/N950
SMSPetFeeder - Build a Bluetooth/SMS dog feeder with Qt, N950, and arduino
Nerf950 - Use your N9/N950 to fire a Nerf gun

Last edited by kojacker; 2010-05-29 at 09:02.
 

The Following 79 Users Say Thank You to kojacker For This Useful Post:
Posts: 428 | Thanked: 226 times | Joined on Dec 2010 @ Philippines
#2
Nice. I'd like to learn how to do that kind of stuff.
 

The Following User Says Thank You to topet2k12001 For This Useful Post:
Dave999's Avatar
Posts: 7,074 | Thanked: 9,069 times | Joined on Oct 2009 @ Moon! It's not the East or the West side... it's the Dark Side
#3
Great app. Even better than you last ones for n9

Great start if anyone trying to start a PyQt career.

Do you want me to port it n9?
__________________
Do something for the climate today! Anything!

I don't trust poeple without a Nokia n900...

Last edited by Dave999; 2013-02-04 at 12:49.
 

The Following User Says Thank You to Dave999 For This Useful Post:
stickymick's Avatar
Posts: 1,079 | Thanked: 1,019 times | Joined on Mar 2010
#4
Originally Posted by Dave999 View Post
Do you want me to port it n9?
Don't you mean fart it across?

Might give this a go, might put some wind into my sails to start developing on a small scale.
__________________
Mick has just punched the cr@p out of the "Unlike" button on the Official Nokia Facebook Page.
 
Posts: 1,269 | Thanked: 3,961 times | Joined on May 2011 @ Brazil
#5
Originally Posted by Dave999 View Post
Great start if anyone trying to start a PyQt career.
PyQt (with QtWidgets) don't work* on MeeGo Harmattan. Use Qt/Qt Quick (with C/C++ or Python) instead.

(*) : no vkb, small fonts, etc.
__________________
Python, C/C++, Qt and CAS developer. For Maemo/MeeGo/Sailfish :
Integral, Derivative, Limit - calculating mathematical integrals, derivatives and limits. SymPy - Computer Algebra System.
MatPlotLib - 2D & 3D plots in Python. IPython - Python interactive shell.
-- My blog about mobile & scientific computing ---
Sailfish : Sony Xperia X, Gemini, Jolla, Jolla C, Jolla Tablet, Nexus 4. Nokia N9, N900, N810.
 
Posts: 1,548 | Thanked: 7,510 times | Joined on Apr 2010 @ Czech Republic
#6
Originally Posted by rcolistete View Post
PyQt (with QtWidgets) don't work* on MeeGo Harmattan. Use Qt/Qt Quick (with C/C++ or Python) instead.

(*) : no vkb, small fonts, etc.
Actually, there is only PySide available for Harmattan so far & it supports writing both classic QtWidget & QtQuick applications.

And yes, you should use QtQuick if possible, due to the issues QtWidgets have as mentioned by rcolistete.
__________________
modRana: a flexible GPS navigation system
Mieru: a flexible manga and comic book reader
Universal Components - a solution for native looking yet component set independent QML appliactions (QtQuick Controls 2 & Silica supported as backends)
 

The Following User Says Thank You to MartinK For This Useful Post:
nokiabot's Avatar
Posts: 1,974 | Thanked: 1,834 times | Joined on Mar 2013 @ india
#7
Wow with the help of kojackers nobel ideas and his innovative coding skills my n900 now can fart wish it could produce pleasent aromatic feeling also just a feature request : using the front camera or back camera to fart. So that i can keep the phone on sofa and when somebody sits beside it would fart
 

The Following User Says Thank You to nokiabot For This Useful Post:
Posts: 1,086 | Thanked: 2,964 times | Joined on Jan 2010
#8
Originally Posted by nokiabot View Post
Wow with the help of kojackers nobel ideas and his innovative coding skills my n900 now can fart wish it could produce pleasent aromatic feeling also just a feature request : using the front camera or back camera to fart. So that i can keep the phone on sofa and when somebody sits beside it would fart
Oh gosh, I wish this old thread would die! lol

Using a camera would need a bunch of image processing, I guess, to detect the person moving past. Even easier might be to leave the phone on the sofa and use the accelerometer code from maeHammer (part 2 of the tutorial here - 'rt2 - adding sound and accelerometer with maeHammer') to play back the noise when the phone is moved/jolted when the victim sits down. Just make sure you don't hide the phone too well or the person may sit down on top of it
__________________
Follow me on my neglected twitter @kojacker

Cybot950 - Control a robot with your N9/N950
SMSPetFeeder - Build a Bluetooth/SMS dog feeder with Qt, N950, and arduino
Nerf950 - Use your N9/N950 to fire a Nerf gun
 

The Following User Says Thank You to kojacker For This Useful Post:
Reply

Thread Tools

 
Forum Jump


All times are GMT. The time now is 13:50.