View Single Post
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, 622 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: