It is bit late now. I am going to bed. Before to that few lines what I have learned today.
1. A slot should always be a 'self' member callable
2. To make a treewidgetitem editable, you need to set all the flags
.. too sleepy .. rest tomorrow in detail !
Tuesday, October 9, 2007
Monday, October 8, 2007
Threading !!!
Readers who are following may be surprised I get into threading so soon. Rather than interest it is requirement of the application I have in mind which I am developing in PyQt.Its the first time I am working with threads. Now that I have wrote my mini application I am thinking how easy it is to create a threaded program.The first application is very inspired from this. I found the original example bit difficult since, the application logic of generating stars and painting on to the label all seemed a large my brain can chew now.
Here is the code sample I have created. The application is somewhat like a timer. The ui contains a start button, stop button and a label on which the timer is showed in secs. This is very crude and rely on time.sleep(). But it should be okay for now to understand threading which is more important.
When start button is pressed, it sends a signal to start the thread. When close is pressed it will tell to finish the thread. Also when the start button is pressed, the 'Start' button is disabled and the 'Stop' button is activated. Vice versa when 'Stop' is pressed.
I feel the following are important to the understading.
1. The thread class should inherit from
2. It is important to set the attribute
To my understanding this is how the above code works.
When the Worker.start() is invoked internally the run method is invoked. This keeps on run till we tell the thread to stop. In this code this is done through setting
As the thread is terminated __del__ is called and the Worker object is destroyed.
Here is the code sample I have created. The application is somewhat like a timer. The ui contains a start button, stop button and a label on which the timer is showed in secs. This is very crude and rely on time.sleep(). But it should be okay for now to understand threading which is more important.
When start button is pressed, it sends a signal to start the thread. When close is pressed it will tell to finish the thread. Also when the start button is pressed, the 'Start' button is disabled and the 'Stop' button is activated. Vice versa when 'Stop' is pressed.
import sys,time
from PyQt4 import QtCore, QtGui
class MyForm(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
# Create a start, stop and a line edit to display the times
self.startButton = QtGui.QPushButton(self.tr("&Start"),self)
self.stopButton= QtGui.QPushButton(self.tr("&Close"),self)
self.stopButton.setEnabled(False)
self.label = QtGui.QLabel(self)
# Arrange them in a good layout
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.startButton)
mainLayout.addWidget(self.stopButton)
mainLayout.addWidget(self.label)
self.setLayout(mainLayout)
# start the worker thread
self.thread = Worker(self.label)
# Now create some connection
self.connect(self.startButton, QtCore.SIGNAL("clicked()"), self.startCounter)
self.connect(self.stopButton, QtCore.SIGNAL("clicked()"), self.stopCounter)
self.connect(self.thread, QtCore.SIGNAL("finished()"), self.updateUi)
self.connect(self.thread, QtCore.SIGNAL("terminated()"), self.updateUi)
def startCounter(self):
self.startButton.setEnabled(False)
self.stopButton.setEnabled(True)
self.thread.render()
def stopCounter(self):
self.startButton.setEnabled(True)
self.stopButton.setEnabled(False)
self.thread.exiting = True
def updateUi(self):
self.startButton.setEnabled(True)
self.stopButton.setEnabled(False)
class Worker(QtCore.QThread):
def __init__(self, ctrl,parent = None):
QtCore.QThread.__init__(self, parent)
self.exiting = False
self.ctrl = ctrl
def __del__(self):
self.exiting = True
self.wait()
def render(self):
self.exiting = False
self.start()
def run(self):
i = 0
while not self.exiting:
time.sleep(1)
if i == 1000:
i = 0
self.ctrl.setText("")
self.ctrl.setText(str(i))
i = i + 1
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
I feel the following are important to the understading.
1. The thread class should inherit from
QtCore.QThread2. It is important to set the attribute
self.exiting = False. Its value will decide whether the thread should be run or not.To my understanding this is how the above code works.
When the Worker.start() is invoked internally the run method is invoked. This keeps on run till we tell the thread to stop. In this code this is done through setting
self.exiting = True . Thread can be terminated by other means too. They should be connected as well.As the thread is terminated __del__ is called and the Worker object is destroyed.
Saturday, October 6, 2007
Translating "finddialog"
As my first task; I am currently translating the finddialog source file to python. Currently I have translated the UI part. I have to still enable the signal and slot. Last night I was stuck with the 'emit'. Today after reading through example code, I found an hint with t8.pyw. I am exploring it currently.
UI only code ..
Now I have to enable the signal and slot mechanisms. I am wondering how the c++ pre-processor statements like QOBJECT, signal, slot, emit are supported in python. Let's see ...
I do not know how to translate the following piece of code for time being. I will look at that in the future.
The problem here is I don't know how to use Qt::... For time being I will just check if it is ticked or not.
Yet another problem..
I am not sure how I am going to define the signals as they have done in the header file as
With this also in the TODO list: I am continuing.
Somehow I could make a simple signal-slot work.
I made the following connection in __init__(..)
The above works
The syntax for signal-slot is as follows.
connect (SENDER,SIGNAL,RECEIVER,SLOT)
Assuming the sender is the findButton, and the signal is 'clicked()' and the receiver is not mentioned here. I would assume if noting is specified 'self' will be the receiver. Now look at the implementation of the slot (self.findClicked())
This is just a test code to see if it works or not. Here we extract the lineEdit control from the self and set some value.
So I am surprised why the following doesn't work ?
I get the following error message.
Does that mean I have to explicitly define signal and slot ?
Lets investigate ..
The problem I am really facing is I don't know how to define a custom signal. In the cpp example, they have defined custom signals as
Reading the PyQt3 it seems that we don't have to define signals in the C++ way. It would be enough just to emit the signals. Now we have to see how the slots has to used.
Also, it is not sure how to emit a custom signal in PyQt4. Any hint?
Info : Looking through the examples, it seems while connecting to a C++ signal, it we have to preserve the signature as in C++.
Seems it is clear now..
You can emit any signal. And the slot can be connected as with any C++ slot. We don't require any special syntax for it.
I tried the following example and it works.
UI only code ..
import sys
from PyQt4 import QtCore, QtGui
class MyForm(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.label = QtGui.QLabel("Find what : ",self)
self.lineEdit = QtGui.QLineEdit(self)
self.label.setBuddy(self.lineEdit)
self.caseCheckBox=QtGui.QCheckBox("Match case",self)
self.backwardCheckBox = QtGui.QCheckBox("Search backward",self);
self.findButton = QtGui.QPushButton("Find",self)
self.closeButton = QtGui.QPushButton("Close",self)
topLeftLayout = QtGui.QHBoxLayout()
topLeftLayout.addWidget(self.label)
topLeftLayout.addWidget(self.lineEdit)
leftLayout = QtGui.QVBoxLayout()
leftLayout.addLayout(topLeftLayout)
leftLayout.addWidget(self.caseCheckBox)
leftLayout.addWidget(self.backwardCheckBox)
rightLayout = QtGui.QVBoxLayout()
rightLayout.addWidget(self.findButton);
rightLayout.addWidget(self.closeButton);
rightLayout.addStretch();
mainLayout = QtGui.QHBoxLayout()
mainLayout.addLayout(leftLayout)
mainLayout.addLayout(rightLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Find")
self.setFixedHeight(self.sizeHint().height())
def findClicked(self):
pass
def enableFindButton(self):
pass
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
Now I have to enable the signal and slot mechanisms. I am wondering how the c++ pre-processor statements like QOBJECT, signal, slot, emit are supported in python. Let's see ...
I do not know how to translate the following piece of code for time being. I will look at that in the future.
Qt::CaseSensitivity cs =
caseCheckBox->isChecked() ? Qt::CaseSensitive
: Qt::CaseInsensitive;
The problem here is I don't know how to use Qt::... For time being I will just check if it is ticked or not.
Yet another problem..
I am not sure how I am going to define the signals as they have done in the header file as
signals:
void findNext(const QString &str, Qt::CaseSensitivity cs);
void findPrevious(const QString &str, Qt::CaseSensitivity cs);
With this also in the TODO list: I am continuing.
Somehow I could make a simple signal-slot work.
I made the following connection in __init__(..)
QtCore.QObject.connect(self.findButton, QtCore.SIGNAL("clicked()"),self.findClicked)
The above works
The syntax for signal-slot is as follows.
connect (SENDER,SIGNAL,RECEIVER,SLOT)
Assuming the sender is the findButton, and the signal is 'clicked()' and the receiver is not mentioned here. I would assume if noting is specified 'self' will be the receiver. Now look at the implementation of the slot (self.findClicked())
def findClicked(self):
str = self.lineEdit.setText('aaa')
This is just a test code to see if it works or not. Here we extract the lineEdit control from the self and set some value.
So I am surprised why the following doesn't work ?
QtCore.QObject.connect(self.findButton, QtCore.SIGNAL("clicked()"),self, QtCore.SLOT("self.findClicked()"))
I get the following error message.
Object::connect: No such slot MyForm::self.findClicked()
Does that mean I have to explicitly define signal and slot ?
Lets investigate ..
The problem I am really facing is I don't know how to define a custom signal. In the cpp example, they have defined custom signals as
signals:
void findNext(const QString &str, Qt::CaseSensitivity cs);
void findPrevious(const QString &str, Qt::CaseSensitivity cs);
Reading the PyQt3 it seems that we don't have to define signals in the C++ way. It would be enough just to emit the signals. Now we have to see how the slots has to used.
Also, it is not sure how to emit a custom signal in PyQt4. Any hint?
Info : Looking through the examples, it seems while connecting to a C++ signal, it we have to preserve the signature as in C++.
self.connect(self.fontCombo, QtCore.SIGNAL("activated(const QString &)"),
self.findStyles)
Seems it is clear now..
You can emit any signal. And the slot can be connected as with any C++ slot. We don't require any special syntax for it.
I tried the following example and it works.
import sys
from PyQt4 import QtCore, QtGui
class MyForm(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.label = QtGui.QLabel("Find what : ",self)
self.lineEdit = QtGui.QLineEdit(self)
self.label.setBuddy(self.lineEdit)
self.caseCheckBox=QtGui.QCheckBox("Match case",self)
self.backwardCheckBox = QtGui.QCheckBox("Search backward",self);
self.findButton = QtGui.QPushButton("Find",self)
self.closeButton = QtGui.QPushButton("Close",self)
QtCore.QObject.connect(self.findButton, QtCore.SIGNAL("clicked()"),self.findClicked)
QtCore.QObject.connect(self, QtCore.SIGNAL("enableFindButton()"),self.Test)
topLeftLayout = QtGui.QHBoxLayout()
topLeftLayout.addWidget(self.label)
topLeftLayout.addWidget(self.lineEdit)
leftLayout = QtGui.QVBoxLayout()
leftLayout.addLayout(topLeftLayout)
leftLayout.addWidget(self.caseCheckBox)
leftLayout.addWidget(self.backwardCheckBox)
rightLayout = QtGui.QVBoxLayout()
rightLayout.addWidget(self.findButton);
rightLayout.addWidget(self.closeButton);
rightLayout.addStretch();
mainLayout = QtGui.QHBoxLayout()
mainLayout.addLayout(leftLayout)
mainLayout.addLayout(rightLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Find")
self.setFixedHeight(self.sizeHint().height())
def findClicked(self):
str = self.lineEdit.setText('aaa')
self.emit(QtCore.SIGNAL('enableFindButton()'))
def enableFindButton(self):
#str = self.lineEdit.setText('ttt')
pass
def Test(self):
str = self.lineEdit.setText('ttt')
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
About the blog
For some time I am looking for a GUI toolkit which is flexible and easier to use. WxPython is good. For what ever reasons I don't find is speedy enough for me. During the search for other GUI toolkits I hit upon PyQt. It seems promising. It is just three days; I am into PyQt. My first impression is
1. It is easy to learn
2. It is fast
3. Qt Designer is easy to use.
4. Learning curve is manageable.
On the negative side I found very less reference material. I have seen a PyQt 3 open book. Only few parts of it is really useful if you are starting with PyQt 4. There are couple of small tutorials. Also, there is one forum hosted by riverbankcomputing. I saw one book in making which is scheduled to be released in the next weeks. The 'rough cut' version is already out. I cannot afford to buy it as of now. I will wait till a local edition is available.
In the mean time I have started reading 'C++ GUI Programming with Qt 4' by Jasmin Blanchette & Mark Summerfield. This is pure c++ book. I have to translate to python to make some sense on how to program with PyQt. This it self is a good exercise.
The blog is to share my experience in learning PyQt. I am sure this will be helpful to anyone starting to learn PyQt.
1. It is easy to learn
2. It is fast
3. Qt Designer is easy to use.
4. Learning curve is manageable.
On the negative side I found very less reference material. I have seen a PyQt 3 open book. Only few parts of it is really useful if you are starting with PyQt 4. There are couple of small tutorials. Also, there is one forum hosted by riverbankcomputing. I saw one book in making which is scheduled to be released in the next weeks. The 'rough cut' version is already out. I cannot afford to buy it as of now. I will wait till a local edition is available.
In the mean time I have started reading 'C++ GUI Programming with Qt 4' by Jasmin Blanchette & Mark Summerfield. This is pure c++ book. I have to translate to python to make some sense on how to program with PyQt. This it self is a good exercise.
The blog is to share my experience in learning PyQt. I am sure this will be helpful to anyone starting to learn PyQt.
Subscribe to:
Posts (Atom)