Discussion:
[ROOT] RE: PyQt and PyROOT
Fine, Valeri
2007-01-11 16:31:08 UTC
Permalink
Hello Luca,
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
I am forwarding your message to the ROOTTalk and RootDev lists

I am not fluent with Python, sorry. Probably you (or some one from the
roottalk) will need to explain me some basic things about Python and
Python ROOT.
From the first glance your trouble is not caused by QtRoot class like
TQtWidget rather by the "pure" Qt class which is QWidget.

By this reason my first question is, "Does your code work if you remove
the line
self.Canvas = TQtWidget(self.CentralWidget)
and replace it with the "pure" Qt class like

self.Canvas = QWidget(self.CentralWidget);
?

My guess it does work. I did pay an attention to the line
self.CentralWidget = QWidget()
that your python did not complain about.

I did see the Python is aware about TQtWidget as well. However it is
confused with the ctor parameter QWidget.
I do not know how one can "explain" python that this parameter is very
pointer to the QWidget class the python is aware about via
from qt import *
I.e. I did see some confusion with the different dictionaries however my
knowledge is not enough to pinpoint the reason.

May be the only thing you need to do is to build the "qtcint" RootCint
dictionary for the Qt classes
http://root.bnl.gov/QtRoot/htmldoc/src/qtclasses.h.html. However, I am
not sure whether it makes sense for you. It may add the insult to injury
;)

I hope some Python people on list can clarify the issue.

Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Thursday, January 11, 2007 10:32 AM
To: Fine, Valeri
Subject: PyQt and PyROOT
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
it takes some time for my account to be activated.
We are trying to put a ROOT canvas on a qt gui and we would like to be
able to do that from
python with pyROOT and pyQt (ROOT 5.14.00, qt 3.3.3, pyQt 3.17, python
2.5).
Based on the c++ examples, we tried the following
import sys
from qt import *
from ROOT import *
QMainWindow.__init__(self)
self.CentralWidget = QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = QGridLayout(self.CentralWidget)
self.Canvas = TQtWidget(self.CentralWidget)
self.Layout.addWidget(self.Canvas, 0, 0)
application = QApplication(sys.argv)
w = window()
w.show()
application.exec_loop()
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
File "window.py", line 18, in <module>
w = window()
File "window.py", line 12, in __init__
self.Canvas = TQtWidget(self.CentralWidget)
TypeError: TQtWidget::TQtWidget(QWidget* parent = 0) =>
could not convert argument 1
Any suggestion you can give me?
Thanks a lot,
Luca Baldini, INFN Pisa
Fine, Valeri
2007-01-11 20:14:37 UTC
Permalink
Hello Johan
Thanks Valeri for your comments :o)
after some more investigation I am convinced the problem comes from
this
line
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
from python just doing 'from ROOT import TQtWidget' gives this
warning.
looking into the TQtWidget source files, one can see that this classed
is built on QWidget.
so when trying to access this class with python, PyROOT tries to look
for the QWidget class and does not find any information on it ('no
dictionnary') because Qt is only a module of ROOT.
The solution is as you say to build a dictionnary for the Qt classes,
and that's exactly what 'qtcint' does...unfortunately this is only
available under MS Windows now.
Why?? It can be done for any platform.

Did you try (assuming you have installed ROOT with --enable-qt option )
cd $ROOTSYS
make qtcint
So I guess we're stuck here unless we take the job of porting 'qtcint'
under Linux.
It works for me (and for STAR) on Linux too.

But ... I still doubt the loading "qtcint" will help you. It can cause
a clash with "import qt". That's why we need input from the Python
expert.

I fear one can end up with TWO different definitions for the Qt classes
coming from PyQt and ROOT Cint "qtcint" dictionaries.

Can you find someone to clarify this issue.
One hope would be to have PyROOT knowing about QWidget directly via
PyQt, but I am not sure that's possible...
Comments are still welcome :o)
cheers,
Johan Bregeon
--------- some more information ---------
http://root.cern.ch/root/Version511.news.html
CINT has a new build option to generate the dictionary for the Qt
classes. This dictionary is not built by default in the binary
distribution files because the resulting library is quite large (>2
Mbytes).
and
root/cint/lib/qt/README.txt
This directory includes build environment for Qt library access DLL.
Run
'sh setup' to build 'include/qtcint.dll'. You need to modify
setup.bat
script for setting Qt directory in your system. By default, c:\qt is
set.
Basic Qt library can be used in an interpreted code by including
<qtcint.dll>
Windows Visual C++ 6.0
qtcint.dll hasn't been port to Linux/UNIX platforms. Your
contribution will be highly appreciated.
-----------------------------------------------------
Hello Luca,
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
I am forwarding your message to the ROOTTalk and RootDev lists
I am not fluent with Python, sorry. Probably you (or some one from
the
roottalk) will need to explain me some basic things about Python and
Python ROOT.
From the first glance your trouble is not caused by QtRoot class
like
TQtWidget rather by the "pure" Qt class which is QWidget.
By this reason my first question is, "Does your code work if you
remove
the line
self.Canvas = TQtWidget(self.CentralWidget)
and replace it with the "pure" Qt class like
self.Canvas = QWidget(self.CentralWidget);
?
My guess it does work. I did pay an attention to the line
self.CentralWidget = QWidget()
that your python did not complain about.
I did see the Python is aware about TQtWidget as well. However it
is
confused with the ctor parameter QWidget.
I do not know how one can "explain" python that this parameter is
very
pointer to the QWidget class the python is aware about via
from qt import *
I.e. I did see some confusion with the different dictionaries
however my
knowledge is not enough to pinpoint the reason.
May be the only thing you need to do is to build the "qtcint"
RootCint
dictionary for the Qt classes
http://root.bnl.gov/QtRoot/htmldoc/src/qtclasses.h.html. However, I
am
not sure whether it makes sense for you. It may add the insult to
injury
;)
I hope some Python people on list can clarify the issue.
Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Thursday, January 11, 2007 10:32 AM
To: Fine, Valeri
Subject: PyQt and PyROOT
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
it takes some time for my account to be activated.
We are trying to put a ROOT canvas on a qt gui and we would like to
be
able to do that from
python with pyROOT and pyQt (ROOT 5.14.00, qt 3.3.3, pyQt 3.17,
python
2.5).
Based on the c++ examples, we tried the following
import sys
from qt import *
from ROOT import *
QMainWindow.__init__(self)
self.CentralWidget = QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = QGridLayout(self.CentralWidget)
self.Canvas = TQtWidget(self.CentralWidget)
self.Layout.addWidget(self.Canvas, 0, 0)
application = QApplication(sys.argv)
w = window()
w.show()
application.exec_loop()
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
File "window.py", line 18, in <module>
w = window()
File "window.py", line 12, in __init__
self.Canvas = TQtWidget(self.CentralWidget)
TypeError: TQtWidget::TQtWidget(QWidget* parent = 0) =>
could not convert argument 1
Any suggestion you can give me?
Thanks a lot,
Luca Baldini, INFN Pisa
Fine, Valeri
2007-01-12 00:02:42 UTC
Permalink
Hello Johan,
Can you modify your python script as follows:

import sys
from qt import *
from ROOT import *

class window(TQtWidget):
def __init__(self):
TQtWidget.__init__(self)


if __name__ == '__main__':
application = QApplication(sys.argv)
w = window()
w.show()
application.exec_loop()

and let me know whether it makes any difference?

Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Thursday, January 11, 2007 2:22 PM
To: Fine, Valeri
Cc: Luca Baldini; ROOT Talk
Subject: Re: PyQt and PyROOT
Thanks Valeri for your comments :o)
after some more investigation I am convinced the problem comes from
this
line
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
from python just doing 'from ROOT import TQtWidget' gives this
warning.
looking into the TQtWidget source files, one can see that this classed
is built on QWidget.
so when trying to access this class with python, PyROOT tries to look
for the QWidget class and does not find any information on it ('no
dictionnary') because Qt is only a module of ROOT.
The solution is as you say to build a dictionnary for the Qt classes,
and that's exactly what 'qtcint' does...unfortunately this is only
available under MS Windows now.
So I guess we're stuck here unless we take the job of porting 'qtcint'
under Linux.
One hope would be to have PyROOT knowing about QWidget directly via
PyQt, but I am not sure that's possible...
Comments are still welcome :o)
cheers,
Johan Bregeon
--------- some more information ---------
http://root.cern.ch/root/Version511.news.html
CINT has a new build option to generate the dictionary for the Qt
classes. This dictionary is not built by default in the binary
distribution files because the resulting library is quite large (>2
Mbytes).
and
root/cint/lib/qt/README.txt
This directory includes build environment for Qt library access DLL.
Run
'sh setup' to build 'include/qtcint.dll'. You need to modify
setup.bat
script for setting Qt directory in your system. By default, c:\qt is
set.
Basic Qt library can be used in an interpreted code by including
<qtcint.dll>
Windows Visual C++ 6.0
qtcint.dll hasn't been port to Linux/UNIX platforms. Your
contribution will be highly appreciated.
-----------------------------------------------------
Hello Luca,
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
I am forwarding your message to the ROOTTalk and RootDev lists
I am not fluent with Python, sorry. Probably you (or some one from
the
roottalk) will need to explain me some basic things about Python and
Python ROOT.
From the first glance your trouble is not caused by QtRoot class
like
TQtWidget rather by the "pure" Qt class which is QWidget.
By this reason my first question is, "Does your code work if you
remove
the line
self.Canvas = TQtWidget(self.CentralWidget)
and replace it with the "pure" Qt class like
self.Canvas = QWidget(self.CentralWidget);
?
My guess it does work. I did pay an attention to the line
self.CentralWidget = QWidget()
that your python did not complain about.
I did see the Python is aware about TQtWidget as well. However it
is
confused with the ctor parameter QWidget.
I do not know how one can "explain" python that this parameter is
very
pointer to the QWidget class the python is aware about via
from qt import *
I.e. I did see some confusion with the different dictionaries
however my
knowledge is not enough to pinpoint the reason.
May be the only thing you need to do is to build the "qtcint"
RootCint
dictionary for the Qt classes
http://root.bnl.gov/QtRoot/htmldoc/src/qtclasses.h.html. However, I
am
not sure whether it makes sense for you. It may add the insult to
injury
;)
I hope some Python people on list can clarify the issue.
Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Thursday, January 11, 2007 10:32 AM
To: Fine, Valeri
Subject: PyQt and PyROOT
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
it takes some time for my account to be activated.
We are trying to put a ROOT canvas on a qt gui and we would like to
be
able to do that from
python with pyROOT and pyQt (ROOT 5.14.00, qt 3.3.3, pyQt 3.17,
python
2.5).
Based on the c++ examples, we tried the following
import sys
from qt import *
from ROOT import *
QMainWindow.__init__(self)
self.CentralWidget = QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = QGridLayout(self.CentralWidget)
self.Canvas = TQtWidget(self.CentralWidget)
self.Layout.addWidget(self.Canvas, 0, 0)
application = QApplication(sys.argv)
w = window()
w.show()
application.exec_loop()
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
File "window.py", line 18, in <module>
w = window()
File "window.py", line 12, in __init__
self.Canvas = TQtWidget(self.CentralWidget)
TypeError: TQtWidget::TQtWidget(QWidget* parent = 0) =>
could not convert argument 1
Any suggestion you can give me?
Thanks a lot,
Luca Baldini, INFN Pisa
Fine, Valeri
2007-01-12 00:57:36 UTC
Permalink
Hello Johan,
The information provided by Version511.news.html
http://root.cern.ch/root/Version511.news.html
CINT has a new build option to generate the dictionary for the Qt
classes. This dictionary is not built by default in the binary
distribution files because the resulting library is quite large (>2
Mbytes).
is correct. ( The size of the qtcint DLL under Windows is 1.5 Mgb and
it is included into the QtRoot windows binary distribution from
http://root.bnl.gov )

However, the README.txt below contains the information about
qt-interface provided by CINT (by Masa Goto from Japan) rather by ROOT
(since version 5.11)
----------------------------------------------------->
root/cint/lib/qt/README.txt
This directory includes build environment for Qt library access DLL.
Run
'sh setup' to build 'include/qtcint.dll'. You need to modify
setup.bat
script for setting Qt directory in your system. By default, c:\qt is
set.
Basic Qt library can be used in an interpreted code by including
<qtcint.dll>
Windows Visual C++ 6.0
qtcint.dll hasn't been port to Linux/UNIX platforms. Your
contribution will be highly appreciated.
-----------------------------------------------------
The up-to-date information about qtcint package provided by ROOT can
be found http://root.cern.ch/root/doc/RootDoc.html "User's guide 5.14"
"ROOT / Qt Integration Interfaces"
ftp://root.cern.ch/root/doc/chapter27.pdf
section "Using Qt Class Library from the ROOT C++ Interpreter" page 514.

See the two examples under $ROOTSYS/tutorials:
gui/QtFileDialog.C
and
gui/QtMultiFileDialog.C

http://root.cern.ch/viewcvs/tutorials/gui/QtFileDialog.C?rev=1.1&content
-type=text/vnd.viewcvs-markup

#ifndef __CINT__
# include <qfiledialog.h>
# include <qstring.h>
#endif

TString QtFileDialog() {

#ifdef __CINT__
// Load the qt cint dictionary.
// One is recommended to do that at once somewhere.
// For example from his/her custom rootlogon.C script
gSystem->Load("$ROOTSYS/cint/include/qtcint");
#endif
QString fileName = QFileDialog::getOpenFileName ();
return TString((const char *)fileName);
}

This simple example must work on any platform. If it is not please file
a bug report ASAP.

Thank you.
Valeri

---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Thursday, January 11, 2007 2:22 PM
To: Fine, Valeri
Cc: Luca Baldini; ROOT Talk
Subject: Re: PyQt and PyROOT
Thanks Valeri for your comments :o)
after some more investigation I am convinced the problem comes from
this
line
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
from python just doing 'from ROOT import TQtWidget' gives this
warning.
looking into the TQtWidget source files, one can see that this classed
is built on QWidget.
so when trying to access this class with python, PyROOT tries to look
for the QWidget class and does not find any information on it ('no
dictionnary') because Qt is only a module of ROOT.
The solution is as you say to build a dictionnary for the Qt classes,
and that's exactly what 'qtcint' does...unfortunately this is only
available under MS Windows now.
So I guess we're stuck here unless we take the job of porting 'qtcint'
under Linux.
One hope would be to have PyROOT knowing about QWidget directly via
PyQt, but I am not sure that's possible...
Comments are still welcome :o)
cheers,
Johan Bregeon
--------- some more information ---------
http://root.cern.ch/root/Version511.news.html
CINT has a new build option to generate the dictionary for the Qt
classes. This dictionary is not built by default in the binary
distribution files because the resulting library is quite large (>2
Mbytes).
and
root/cint/lib/qt/README.txt
This directory includes build environment for Qt library access DLL.
Run
'sh setup' to build 'include/qtcint.dll'. You need to modify
setup.bat
script for setting Qt directory in your system. By default, c:\qt is
set.
Basic Qt library can be used in an interpreted code by including
<qtcint.dll>
Windows Visual C++ 6.0
qtcint.dll hasn't been port to Linux/UNIX platforms. Your
contribution will be highly appreciated.
-----------------------------------------------------
Hello Luca,
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
I am forwarding your message to the ROOTTalk and RootDev lists
I am not fluent with Python, sorry. Probably you (or some one from
the
roottalk) will need to explain me some basic things about Python and
Python ROOT.
From the first glance your trouble is not caused by QtRoot class
like
TQtWidget rather by the "pure" Qt class which is QWidget.
By this reason my first question is, "Does your code work if you
remove
the line
self.Canvas = TQtWidget(self.CentralWidget)
and replace it with the "pure" Qt class like
self.Canvas = QWidget(self.CentralWidget);
?
My guess it does work. I did pay an attention to the line
self.CentralWidget = QWidget()
that your python did not complain about.
I did see the Python is aware about TQtWidget as well. However it
is
confused with the ctor parameter QWidget.
I do not know how one can "explain" python that this parameter is
very
pointer to the QWidget class the python is aware about via
from qt import *
I.e. I did see some confusion with the different dictionaries
however my
knowledge is not enough to pinpoint the reason.
May be the only thing you need to do is to build the "qtcint"
RootCint
dictionary for the Qt classes
http://root.bnl.gov/QtRoot/htmldoc/src/qtclasses.h.html. However, I
am
not sure whether it makes sense for you. It may add the insult to
injury
;)
I hope some Python people on list can clarify the issue.
Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Thursday, January 11, 2007 10:32 AM
To: Fine, Valeri
Subject: PyQt and PyROOT
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
it takes some time for my account to be activated.
We are trying to put a ROOT canvas on a qt gui and we would like to
be
able to do that from
python with pyROOT and pyQt (ROOT 5.14.00, qt 3.3.3, pyQt 3.17,
python
2.5).
Based on the c++ examples, we tried the following
import sys
from qt import *
from ROOT import *
QMainWindow.__init__(self)
self.CentralWidget = QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = QGridLayout(self.CentralWidget)
self.Canvas = TQtWidget(self.CentralWidget)
self.Layout.addWidget(self.Canvas, 0, 0)
application = QApplication(sys.argv)
w = window()
w.show()
application.exec_loop()
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
File "window.py", line 18, in <module>
w = window()
File "window.py", line 12, in __init__
self.Canvas = TQtWidget(self.CentralWidget)
TypeError: TQtWidget::TQtWidget(QWidget* parent = 0) =>
could not convert argument 1
Any suggestion you can give me?
Thanks a lot,
Luca Baldini, INFN Pisa
Fine, Valeri
2007-01-12 02:27:33 UTC
Permalink
Hello Johan,
I am begging the pardon for the "sliced" response.
after some more investigation I am convinced the problem comes from
this
line
Your explanation of the problem is not correct, sorry.
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
from python just doing 'from ROOT import TQtWidget' gives this
warning.

The message above is provided by ROOT rather by Python. It is the
"warning". It should cause no problem unless one wants to create an
instance of the very QWidget class from the ROOT prompt. However there
is no obstacle to create the TQtWidget instance with the default
constructor (This is what we really want to do)
looking into the TQtWidget source files, one can see that this classed
is built on QWidget.
so when trying to access this class with python, PyROOT tries to look
for the QWidget class and does not find any information on it ('no
dictionnary') because Qt is only a module of ROOT.
No, it is not correct. The problem comes from another place.
Problem is not cause by the base class of TQtWidget as you suggested.
The problem is caused by first parameter of that class constructor.

Pay your attention, the first parameter of the TQtWidget ctor is the
pointer to QWidget.
self.Canvas = TQtWidget(self.CentralWidget)
I believe there is no problem to create the TQtWidget via ctor, but . .
. there is the problem to PASS the pointer of the PyQT created
CentralWidget object to the TQtWidget ctor as its first parameter.

By some reason, PyQt is not aware that the type of the first parameter
of the TQtWidget and type of the CentralWidget object are the same.
THIS IS THE PROBLEM. I believe some Python guru can quickly explain us
what should be done if any. I can not, sorry.
The solution is as you say to build a dictionnary for the Qt classes,
I do not think (I have to repeat) this may have helped.
The PyQt is already has the QWidget definition. Bringing in the second
one should lead to some sort of the clash between two different
definitions of one and the same class, namely QWidget.

In fact as soon as you load qtcint you do not need any PyQt at all. It
should work (well, in theory only. It can be done but ... nobody tried
that yet ;)
One hope would be to have PyROOT knowing about QWidget directly via
PyQt, but I am not sure that's possible...
As soon as qtcint is loaded, PyROOT should "know" about QWidget and ...
no PyQt is needed at all. But, see my remark above, nobody has tried
that yet ;)
Comments are still welcome :o)
Try to

1. build the qtcint (say "make qtcint" from $ROOTSYS)
2. activate QtRoot plugin via ".rootrc" file (How? See "ROOT Manual")
3. Start PyROOT. ( No PyQt !!!)
4. Try to execute the ROOT macro from
$ROOTSYS/tutorials/gui/QtFileDialog.C from your Python.

let me know the outcome.

Best regards, Valeri
cheers,
Johan Bregeon
--------- some more information ---------
http://root.cern.ch/root/Version511.news.html
CINT has a new build option to generate the dictionary for the Qt
classes. This dictionary is not built by default in the binary
distribution files because the resulting library is quite large (>2
Mbytes).
and
root/cint/lib/qt/README.txt
This directory includes build environment for Qt library access DLL.
Run
'sh setup' to build 'include/qtcint.dll'. You need to modify
setup.bat
script for setting Qt directory in your system. By default, c:\qt is
set.
Basic Qt library can be used in an interpreted code by including
<qtcint.dll>
Windows Visual C++ 6.0
qtcint.dll hasn't been port to Linux/UNIX platforms. Your
contribution will be highly appreciated.
-----------------------------------------------------
Hello Luca,
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
I am forwarding your message to the ROOTTalk and RootDev lists
I am not fluent with Python, sorry. Probably you (or some one from
the
roottalk) will need to explain me some basic things about Python and
Python ROOT.
From the first glance your trouble is not caused by QtRoot class
like
TQtWidget rather by the "pure" Qt class which is QWidget.
By this reason my first question is, "Does your code work if you
remove
the line
self.Canvas = TQtWidget(self.CentralWidget)
and replace it with the "pure" Qt class like
self.Canvas = QWidget(self.CentralWidget);
?
My guess it does work. I did pay an attention to the line
self.CentralWidget = QWidget()
that your python did not complain about.
I did see the Python is aware about TQtWidget as well. However it
is
confused with the ctor parameter QWidget.
I do not know how one can "explain" python that this parameter is
very
pointer to the QWidget class the python is aware about via
from qt import *
I.e. I did see some confusion with the different dictionaries
however my
knowledge is not enough to pinpoint the reason.
May be the only thing you need to do is to build the "qtcint"
RootCint
dictionary for the Qt classes
http://root.bnl.gov/QtRoot/htmldoc/src/qtclasses.h.html. However, I
am
not sure whether it makes sense for you. It may add the insult to
injury
;)
I hope some Python people on list can clarify the issue.
Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Thursday, January 11, 2007 10:32 AM
To: Fine, Valeri
Subject: PyQt and PyROOT
Hi Valeri,
I apologize for not writing on the root talk forum, but I just
registered and it seems like
it takes some time for my account to be activated.
We are trying to put a ROOT canvas on a qt gui and we would like to
be
able to do that from
python with pyROOT and pyQt (ROOT 5.14.00, qt 3.3.3, pyQt 3.17,
python
2.5).
Based on the c++ examples, we tried the following
import sys
from qt import *
from ROOT import *
QMainWindow.__init__(self)
self.CentralWidget = QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = QGridLayout(self.CentralWidget)
self.Canvas = TQtWidget(self.CentralWidget)
self.Layout.addWidget(self.Canvas, 0, 0)
application = QApplication(sys.argv)
w = window()
w.show()
application.exec_loop()
Warning in <TClass::TClass>: no dictionary for class QWidget is
available
File "window.py", line 18, in <module>
w = window()
File "window.py", line 12, in __init__
self.Canvas = TQtWidget(self.CentralWidget)
TypeError: TQtWidget::TQtWidget(QWidget* parent = 0) =>
could not convert argument 1
Any suggestion you can give me?
Thanks a lot,
Luca Baldini, INFN Pisa
W***@lbl.gov
2007-01-12 05:51:03 UTC
Permalink
Dear all,

couple of minor points: the warning about the missing QWidget dictionary
can come from PyROOT, as it will attempt to create classes for all bases
when a derived class is created (a class is not complete without its list
of bases, as each (may) bring(s) in more functions, members, etc.).
Further, a QWidget from a CINT dictionary and bound by PyROOT will not clash
with one from PyQt. As far as python is concerned, these are two completely
different classes. It will, however also consider them completely unrelated
and you can't pass one where the other is expected. In concrete terms, one
will be known as "ROOT.QWidget" and the other as "qt.QWidget" and occupy
different places in memory.

Then, what I think is what you really want, is convincing either extension
to take a class from the other by pointer. Unfortunately, I'm not that well
import sip
addr = sip.unwrapinstance(my_widget)
You'll get a Python integer that can either be passed as it is, or you
ptr = sip.voidptr(addr)
cobj = ptr.ascobject()
where module sip is from SIP, which is used to build PyQt, so I presume
that you have it available (just give it a try, and let me know if it
fails, and I'll install things myself to get some more info as needed).

That final "cobj" from your original widget is a so-called python CObject,
aka opaque C pointer, aka "void*". PyROOT accepts these as drop-in for any
interface that accepts pointers, so it should work for your TQtWidget ctor
as well. PyROOT does not accept integers as drop-in for pointers, not even
for void* (with the exception of the integer 0). Thus, something like:

import sip
cobj = sip.voidptr(sip.unwrapinstance(self.CentralWidget)).ascobject()
self.Canvas = TQtWidget(cobj)

is what I'd expect to work. It may be that the unwrapping is unnecessary
and that the 'ascobject' method is directly available on the widget.

The converse would go with something like (this code is non-sensical, it's
just for the idea how you'd do it, if so desired):

import sip
foo = sip.wrapinstance( ROOT.AddressOf(self.Canvas)[0], qt.QWidget )

Where the original TQtWidget is now seen as a qt.QWidget. (Code again from
Google, haven't actually tried it out.)

What is going on is the following: AddressOf() returns a buffer object (I
choose that b/c it's somewhat wider accepted than the CObject, and it is
more easily to work with in python) that contains the address as a long.
Thus, indexing it with [0], gives the void* value as a long integer. Then,
wrapinstance does the inverse of unwrapinstances and binds this address to
the qt.QWidget extension type.

Note that passing pointers around like this, is passing void*'s around in
a way that is morally equivalent to reinterpret_cast<>. Consequently, there
are no casts done (i.e. no pointer offsets for base classes). This is ok,
if the type expected and the type that you have, have 0 offset (e.g. when
they are the same time, or when they have a simple inheritance structure).
Otherwise, if both the base and the derived class have a CINT dictionary,
you can use TClass to perform the casting, though.

Hope that helps. Please let me know if any part requires any further
clarification, or if you don't have module sip available.

Best regards,
Wim
--
***@cern.ch -- ***@lbl.gov -- www.lavrijsen.net

"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Johan Bregeon
2007-01-12 15:25:08 UTC
Permalink
Hello all,
Thanks to your comments, we were able to make a step forward.
We actually had to use both 'qtcint' and sip to have something working.
Here is the piece of code :
------------------------------------------------------------------------------------
import sys
import qt
import ROOT
import sip
ROOT.gSystem.Load('qtcint')

class window(qt.QMainWindow):
def __init__(self):
# Init the main window.
qt.QMainWindow.__init__(self)
self.resize(350, 350)

# Create the central widget.
self.CentralWidget = qt.QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = qt.QGridLayout(self.CentralWidget)

# Create a root histogram.
self.hist = ROOT.TH1F("pipo","pipo", 100, 0, 100)

# Create the main TQtWidget (using sip to get the pointer to the
central widget).
self.Address = sip.unwrapinstance(self.CentralWidget)
self.Canvas = ROOT.TQtWidget(sip.voidptr(self.Address).ascobject())
self.Canvas.resize(300, 300)

# Place the TQtWidget in the main grid layout and draw the histogram.

self.Layout.addWidget(sip.wrapinstance(ROOT.AddressOf(self.Canvas)[0],
qt.QWidget), 0, 0)
self.Canvas.show()
self.Canvas.cd()
self.hist.Draw()
self.Canvas.Refresh()

if __name__ == '__main__':
application = qt.QApplication(sys.argv)
qt.QObject.connect(application, qt.SIGNAL("lastWindowClosed()"),
application, qt.SLOT("quit()"))
w = window()
w.show()
application.exec_loop()
------------------------------------------------------------------------------------

It's almost doing what we want to...meaning, that it's running but
ultimately the Histogram does not show up on the GUI.
Notes :
+ If we add the histogram directly to the 'MainWindow' it's working,
but we obviously need the 'layout' step to work.

We also have these warnings :
$ python pyqtroot.py
** $Id: TGQt.cxx,v 1.35 2006/12/12 20:12:47 brun Exp $ this=0x9fc8d90
Error in <TUnixSystem::DynamicPathName>: QtGui[.so | .sl | .dl | .a |
.dll] does not exist in
$(ROOTSYS)/cint/include:.:/usr/local/root/v5.14.00/lib:/usr/local/root/v5.14.00/lib:/usr/local/python2.5/lib:/usr/local/lib
QApplication: There should be max one application object
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available

1) Where does this QtGui library comes from ? (there seems to be one in
qt4 but we do not have any in qt3)
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
3) We're now loading the 'qtcint' dictionnary, so why some Qt class
dictionaries are still missing ?

Thanks for comments,
cheers
Johan
Fine, Valeri
2007-01-12 18:08:37 UTC
Permalink
Hello Johan,
Post by Johan Bregeon
1) Where does this QtGui library comes from ? (there seems to be one in
qt4 but we do not have any in qt3)
** $Id: TGQt.cxx,v 1.35 2006/12/12 20:12:47 brun Exp $ this=0x9fc8d90
Error in <TUnixSystem::DynamicPathName>: QtGui[.so | .sl | .dl | .a |
.dll] does not exist in
The library in question is QtRoot library rather one from Qt4.

The simplest solution is to create a simlink between libQtRootGui.so and
libQtGui.so.

I did choose the name "QtGui" for ROOT Qt extension a while ago, well
BEFORE I learned about Qt 4 :((

Later on, I had to change the name of the library from QtGui to
QtRootGui to be "Qt4 compliant". It looks like I missed some place to be
fixed. I'll re-check things.
Post by Johan Bregeon
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
It is YOUR script !!! at the time your script calls "main". I guess
there is another "real main" in Python,
Post by Johan Bregeon
application = qt.QApplication(sys.argv)
ROOT had been started (QApplication was created too via ROOT Qt
plug-in). May be, Wim can explain us at which point the PyROOT
instantiates ROOT.

This means QtRoot "thinks" you (PyRoot application) are "Qt-based ROOT
application" rather "ROOT-based Qt application" (see:
ftp://root.cern.ch/root/doc/chapter27.pdf Section "Application" p 416).


Anyway, this merely means you should simplify your script to use qApp

( See: http://doc.trolltech.com/3.3/qapplication.html#QApplication
"The QApplication object is accessible through the global pointer qApp")


instead of QApplication(sys.argv) and you must NOT enter the Qt Event
loop at all.

Instead of your
Post by Johan Bregeon
application = qt.QApplication(sys.argv)
qt.QObject.connect(application, qt.SIGNAL("lastWindowClosed()"),
application, qt.SLOT("quit()"))
w = window()
w.show()
application.exec_loop()
you need something like this

if __name__ == '__main__':
application = qt.qApp
qt.QObject.connect(application, qt.SIGNAL("lastWindowClosed()"),
application, qt.SLOT("quit()"))
w = window()
w.show()
Post by Johan Bregeon
+ If we add the histogram directly to the 'MainWindow' it's working,
but we obviously need the 'layout' step to work.
----------
Post by Johan Bregeon
3) We're now loading the 'qtcint' dictionary, so why some Qt class
dictionaries are still missing ?
This library does not provide the dictionary for ALL Qt classes.
See the Web page again
http://root.bnl.gov/QtRoot/htmldoc/src/qtclasses.h.html

It does provide the dictionary for the "Main classes", those I think one
would want to use on the script (ROOT macro) level. I think this
assertion is still correct for the Python scripts. Anyway the list of
the Qt classes the RootCint dictionary built for is defined by the file
http://root.cern.ch/viewcvs/cint/lib/qt/qtclasses.h?rev=1.9&content-type
=text/vnd.viewcvs-markup

In fact, I think, the creating and loading qtcint.dll to make PyQt +
PyROOT work together is unnecessary heavy solution.

What, I think one needs, is, in fact, some sort of the 4 automatic
"cast" (a'la C++ cast operator ) operators,
To map "automatically":

qt.QWidget <--> root.QWidget
qt.QPixmap <--> root.QPixmap
qt.QImage <--> root.QImage
qt.QWidget <--> root.TQtWidget

This should be sufficient and I hope it can be achieved with no qtcint.

In fact I do not think one needs any QWidget, QPixmap etc ROOT
dictionaries either.
For example, if one wants to invoke some TQtWidget methods inherited
from the base QWidget he/she can do "cast"

qt.QWidget = root.TQtWidget

and then invoke all QWidget methods via qt.QWidget. The same should be
true for all other Qt classes.

Alas, I do not know Python and can not suggest the technical solution
for this idea.

I hope I have answered all you current questions.

I am waiting for the next one ;)

Have a nice day, Valeri Fine

-----------------------------------------------
Post by Johan Bregeon
Hello all,
Thanks to your comments, we were able to make a step forward.
We actually had to use both 'qtcint' and sip to have something
working.
------------------------------------------------------------------------
--
Post by Johan Bregeon
----------
import sys
import qt
import ROOT
import sip
ROOT.gSystem.Load('qtcint')
# Init the main window.
qt.QMainWindow.__init__(self)
self.resize(350, 350)
# Create the central widget.
self.CentralWidget = qt.QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = qt.QGridLayout(self.CentralWidget)
# Create a root histogram.
self.hist = ROOT.TH1F("pipo","pipo", 100, 0, 100)
# Create the main TQtWidget (using sip to get the pointer to the
central widget).
self.Address = sip.unwrapinstance(self.CentralWidget)
self.Canvas =
ROOT.TQtWidget(sip.voidptr(self.Address).ascobject())
Post by Johan Bregeon
self.Canvas.resize(300, 300)
# Place the TQtWidget in the main grid layout and draw the
histogram.
Post by Johan Bregeon
self.Layout.addWidget(sip.wrapinstance(ROOT.AddressOf(self.Canvas)[0],
qt.QWidget), 0, 0)
self.Canvas.show()
self.Canvas.cd()
self.hist.Draw()
self.Canvas.Refresh()
application = qt.QApplication(sys.argv)
qt.QObject.connect(application, qt.SIGNAL("lastWindowClosed()"),
application, qt.SLOT("quit()"))
w = window()
w.show()
application.exec_loop()
------------------------------------------------------------------------
--
Post by Johan Bregeon
----------
It's almost doing what we want to...meaning, that it's running but
ultimately the Histogram does not show up on the GUI.
+ If we add the histogram directly to the 'MainWindow' it's working,
but we obviously need the 'layout' step to work.
$ python pyqtroot.py
** $Id: TGQt.cxx,v 1.35 2006/12/12 20:12:47 brun Exp $ this=0x9fc8d90
Error in <TUnixSystem::DynamicPathName>: QtGui[.so | .sl | .dl | .a |
.dll] does not exist in
$(ROOTSYS)/cint/include:.:/usr/local/root/v5.14.00/lib:/usr/local/root/v
5.
Post by Johan Bregeon
14.00/lib:/usr/local/python2.5/lib:/usr/local/lib
QApplication: There should be max one application object
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available
1) Where does this QtGui library comes from ? (there seems to be one in
qt4 but we do not have any in qt3)
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
3) We're now loading the 'qtcint' dictionnary, so why some Qt class
dictionaries are still missing ?
Thanks for comments,
cheers
Johan
W***@lbl.gov
2007-01-13 00:43:54 UTC
Permalink
Dear all,
Post by Johan Bregeon
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
well, some gApplication will need to exist at some point: both ROOT GUI (e.g.
your histo display) as well as Qt (buttons, frame, etc.) will need to receive
notifications from the OS, which are dispatched in a mainloop. If not, parts
of your GUI will freeze. You can either dispatch to both systems yourself, by
writing your own mainloop, or let QtRoot take care of it, following Valeri's
instructions.
Post by Johan Bregeon
ROOT had been started (QApplication was created too via ROOT Qt
plug-in). May be, Wim can explain us at which point the PyROOT
instantiates ROOT.
For ROOT 5.14, you can actually override gApplication, as long as you do it
between "import ROOT" and the first use of ROOT.<anything other than gROOT>.
Of course, some calls on gROOT trigger the creation of a default gApplication.

In your script, application creation is done later, and a TPyROOTApplication
is created by that time (PyROOT does a simple check if ( ! gApplication ) on
the first access to anything other than gROOT in the ROOT module, to see if it
should create an application). I.e., this line: "ROOT.gSystem.Load('qtcint')".

Note that TPyROOTApplication is nothing but a trivial TApplication derived,
where the real work is done.

HTH,
Wim
--
***@cern.ch -- ***@lbl.gov -- www.lavrijsen.net

"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Johan Bregeon
2007-01-15 17:41:42 UTC
Permalink
Thanks all for your help,
we were able to solve a couple of more problems following your advice,
but unfortunately we couldn't have something stable working.
but we actually do not have the time / man power /knowledge to go
further with building up a ROOT application with a Qt gui, using pyroot
and pyqt, so we decided to stop here on that point.

Our new idea is to use only pyRoot for this purpose, so let me start
another trade...
cheers,
Johan
Post by W***@lbl.gov
Dear all,
Post by Johan Bregeon
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
well, some gApplication will need to exist at some point: both ROOT GUI (e.g.
your histo display) as well as Qt (buttons, frame, etc.) will need to receive
notifications from the OS, which are dispatched in a mainloop. If not, parts
of your GUI will freeze. You can either dispatch to both systems yourself, by
writing your own mainloop, or let QtRoot take care of it, following Valeri's
instructions.
Post by Johan Bregeon
ROOT had been started (QApplication was created too via ROOT Qt
plug-in). May be, Wim can explain us at which point the PyROOT
instantiates ROOT.
For ROOT 5.14, you can actually override gApplication, as long as you do it
between "import ROOT" and the first use of ROOT.<anything other than gROOT>.
Of course, some calls on gROOT trigger the creation of a default gApplication.
In your script, application creation is done later, and a TPyROOTApplication
is created by that time (PyROOT does a simple check if ( ! gApplication ) on
the first access to anything other than gROOT in the ROOT module, to see if it
should create an application). I.e., this line: "ROOT.gSystem.Load('qtcint')".
Note that TPyROOTApplication is nothing but a trivial TApplication derived,
where the real work is done.
HTH,
Wim
--
"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Fine, Valeri
2007-01-16 04:25:24 UTC
Permalink
Hi Johan,
Can you upload (attach) your last version of PyQt + PyROOT script to start with?
I am willing to try it myself to see what is going on?
Thank you.

________________________________

From: Johan Bregeon [mailto:***@pi.infn.it]
Sent: Mon 1/15/2007 12:41 PM
To: ***@lbl.gov
Cc: Fine, Valeri; Luca Baldini; ROOT Talk
Subject: Re: [ROOT] RE: PyQt and PyROOT



Thanks all for your help,
we were able to solve a couple of more problems following your advice,
but unfortunately we couldn't have something stable working.
but we actually do not have the time / man power /knowledge to go
further with building up a ROOT application with a Qt gui, using pyroot
and pyqt, so we decided to stop here on that point.

Our new idea is to use only pyRoot for this purpose, so let me start
another trade...
cheers,
Johan
Post by W***@lbl.gov
Dear all,
Post by Johan Bregeon
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
well, some gApplication will need to exist at some point: both ROOT GUI (e.g.
your histo display) as well as Qt (buttons, frame, etc.) will need to receive
notifications from the OS, which are dispatched in a mainloop. If not, parts
of your GUI will freeze. You can either dispatch to both systems yourself, by
writing your own mainloop, or let QtRoot take care of it, following Valeri's
instructions.
Post by Johan Bregeon
ROOT had been started (QApplication was created too via ROOT Qt
plug-in). May be, Wim can explain us at which point the PyROOT
instantiates ROOT.
For ROOT 5.14, you can actually override gApplication, as long as you do it
between "import ROOT" and the first use of ROOT.<anything other than gROOT>.
Of course, some calls on gROOT trigger the creation of a default gApplication.
In your script, application creation is done later, and a TPyROOTApplication
is created by that time (PyROOT does a simple check if ( ! gApplication ) on
the first access to anything other than gROOT in the ROOT module, to see if it
should create an application). I.e., this line: "ROOT.gSystem.Load('qtcint')".
Note that TPyROOTApplication is nothing but a trivial TApplication derived,
where the real work is done.
HTH,
Wim
--
"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Fine, Valeri
2007-01-16 05:32:42 UTC
Permalink
Hello Johan,

I could not understand your Qt layout idea.
Does it work without ROOT ?
For example, can you replace the TQtWidget with some QLabel and re-run your script with NO (!!!) PyROOT at all?
application.exec_loop()
QtRoot does this and the second event loop may cause the problem
self.Canvas.resize(300, 300)
because the size is to be set by layout
self.Canvas.Refresh()
No need to refresh, because TCanvas is embedded and it is to be refreshed by the parent widget.
self.resize(350, 350)
is called too earlier. You should define the final widget size after you create its layout. i.e. from your main

Anyway the main question is still persisting. What do you want your widget looks like?

To separate things, can you show this by replacing TQtWidget with the regular QWidget (for example QLabel), with neither PyROOT nor QtRoot? I.e. with PyQt alone?

(Attention, To run PyQt with no QtRoot you do need application.exec_loop())

Thank you.

My best regards, Valeri

________________________________

From: Johan Bregeon [mailto:***@pi.infn.it]
Sent: Mon 1/15/2007 12:41 PM
To: ***@lbl.gov
Cc: Fine, Valeri; Luca Baldini; ROOT Talk
Subject: Re: [ROOT] RE: PyQt and PyROOT



Thanks all for your help,
we were able to solve a couple of more problems following your advice,
but unfortunately we couldn't have something stable working.
but we actually do not have the time / man power /knowledge to go
further with building up a ROOT application with a Qt gui, using pyroot
and pyqt, so we decided to stop here on that point.

Our new idea is to use only pyRoot for this purpose, so let me start
another trade...
cheers,
Johan
Dear all,
Post by Johan Bregeon
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
well, some gApplication will need to exist at some point: both ROOT GUI (e.g.
your histo display) as well as Qt (buttons, frame, etc.) will need to receive
notifications from the OS, which are dispatched in a mainloop. If not, parts
of your GUI will freeze. You can either dispatch to both systems yourself, by
writing your own mainloop, or let QtRoot take care of it, following Valeri's
instructions.
Post by Johan Bregeon
ROOT had been started (QApplication was created too via ROOT Qt
plug-in). May be, Wim can explain us at which point the PyROOT
instantiates ROOT.
For ROOT 5.14, you can actually override gApplication, as long as you do it
between "import ROOT" and the first use of ROOT.<anything other than gROOT>.
Of course, some calls on gROOT trigger the creation of a default gApplication.
In your script, application creation is done later, and a TPyROOTApplication
is created by that time (PyROOT does a simple check if ( ! gApplication ) on
the first access to anything other than gROOT in the ROOT module, to see if it
should create an application). I.e., this line: "ROOT.gSystem.Load('qtcint')".
Note that TPyROOTApplication is nothing but a trivial TApplication derived,
where the real work is done.
HTH,
Wim
--
"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Fine, Valeri
2007-01-16 06:15:15 UTC
Permalink
Hello Johan,

Your script did not work because you did not use Qt properly. (That has nothing to do with ROOT /QtRoot)
Please, follow my previous message those advices are still valid and . . .
To fix
there was no canvas in the main window,
meaning we still have a problem with the layout."
you have to replace your
self.CentralWidget = qt.QWidget()
with

self.CentralWidget = qt.QWidget(self)

To fix
but the application was hanging up somewhere
application.exec_loop()
Hope this helps, Valeri

I am begging a pardon with some delay . . . you see your script is the first Python script I am dealing with ;)
and I still have to install PyQt to try it myself.

PS. Please find the working equivalent of your Python script in C++ ( I did test on lxplus, it does work)
#include <TRint.h>

#include <qmainwindow.h>

#include <qlayout.h>

#include <TH1.h>

#include <TQtWidget.h>



QMainWindow *window()

{

// Create the main window

QMainWindow *self = new QMainWindow();



// Create the central widget.

QWidget *CentralWidget = new QWidget(self); // This was wrong !!!

self->setCentralWidget(CentralWidget);

QGridLayout *Layout = new QGridLayout(CentralWidget);



// Create a root histogram

TH1F *hist = new TH1F("pipo","pipo", 100, 0, 100);



// Create the main TQtWidget (using sip to get the pointer to the central widget).

TQtWidget *Canvas = new TQtWidget(CentralWidget);



// Place the TQtWidget in the main grid layout and draw the histogram.

Layout->addWidget(Canvas,0,0);

hist->Draw();



return self;

}

int main( int argc, char **argv )

{

// Create an interactive ROOT application

// This portion is to be done by PyROOT for you

TRint *theApp = new TRint("Rint", &argc, argv); // This portion is to be done by PyROOT for you



// Create Qt object within ROOT application

QMainWindow *w = window();

w->resize(350,350);

w->show();



// and enter the ROOT event loop...

// This portion is to be done by PyROOT for you

theApp->Run(); // This portion is to be done by PyROOT for you



printf(" Goob bye ROOT !\n");

}


________________________________

From: Johan Bregeon [mailto:***@pi.infn.it]
Sent: Mon 1/15/2007 12:41 PM
To: ***@lbl.gov
Cc: Fine, Valeri; Luca Baldini; ROOT Talk
Subject: Re: [ROOT] RE: PyQt and PyROOT



Thanks all for your help,
we were able to solve a couple of more problems following your advice,
but unfortunately we couldn't have something stable working.
but we actually do not have the time / man power /knowledge to go
further with building up a ROOT application with a Qt gui, using pyroot
and pyqt, so we decided to stop here on that point.

Our new idea is to use only pyRoot for this purpose, so let me start
another trade...
cheers,
Johan
Dear all,
Post by Johan Bregeon
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
well, some gApplication will need to exist at some point: both ROOT GUI (e.g.
your histo display) as well as Qt (buttons, frame, etc.) will need to receive
notifications from the OS, which are dispatched in a mainloop. If not, parts
of your GUI will freeze. You can either dispatch to both systems yourself, by
writing your own mainloop, or let QtRoot take care of it, following Valeri's
instructions.
Post by Johan Bregeon
ROOT had been started (QApplication was created too via ROOT Qt
plug-in). May be, Wim can explain us at which point the PyROOT
instantiates ROOT.
For ROOT 5.14, you can actually override gApplication, as long as you do it
between "import ROOT" and the first use of ROOT.<anything other than gROOT>.
Of course, some calls on gROOT trigger the creation of a default gApplication.
In your script, application creation is done later, and a TPyROOTApplication
is created by that time (PyROOT does a simple check if ( ! gApplication ) on
the first access to anything other than gROOT in the ROOT module, to see if it
should create an application). I.e., this line: "ROOT.gSystem.Load('qtcint')".
Note that TPyROOTApplication is nothing but a trivial TApplication derived,
where the real work is done.
HTH,
Wim
--
"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Fine, Valeri
2007-01-16 14:26:09 UTC
Permalink
Hello Luca,



This looks good, Thank you very much. Nice progress.
otherwise the window get closed immediately.
That has nothing to do with PyROOT/PyQt/QtROOT. I think this the correct (!!!) behavior of your script. I do not know Python. However, from the first glance your "main" does create the object of the class "window" and this object is to be DESTROYED as soon as your code leaves the "main" scope. You should ask someone who knows Python to find the correct way to preserve the Python object beyond the method scope.
I still don't get that, it looks like the application main loop is not running...
I had made an assumption that event loop is started for us by PyROOT. May be this is not correct.
We need the Wim's clarification again. I did not find anything on "Event loop" on his Web page http://wlav.web.cern.ch/wlav/pyroot <http://wlav.web.cern.ch/wlav/pyroot> yet. I need digging his code now. I need to know how and where PyROOT manages the ROOT event loop to avoid the guess job.



May be Wim can look up the C++ code sent last time to tell us where, how, and when the PyROOT implements the

TRint *theApp = new TRint("Rint", &argc, argv);

and

theApp->Run();

May be the only thing you should do is to call

gApplication.Run()

instead of your "raw_input()". However, to avoid the guess job one needs to know precisely where gApplication is coming from and how. I'll investigate this today and let you know hot to proceed further.

My best regards, Valeri




________________________________

From: Luca Baldini [mailto:***@pi.infn.it]
Sent: Tue 1/16/2007 3:30 AM
To: Fine, Valeri
Cc: Johan Bregeon; ***@lbl.gov; Luca Baldini; ROOT Talk
Subject: Re: [ROOT] RE: PyQt and PyROOT



Hi Valeri,
this is the best we could do, so far, following your suggestions.
The script works, except for the fact that it needs the last raw_input()
stuff, otherwise the window get closed
immediately. I still don't get that, it looks like the application main
loop is not running...
Also, we would like to be able to close the application by clicking on
the window, rather than pressing a
key on the prompt.


#!/bin/env python

import sip
from qt import QMainWindow, QWidget, QGridLayout
from ROOT import TH1F, TQtWidget, gSystem, AddressOf

gSystem.Load('qtcint')

class window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.CentralWidget = QWidget(self)
self.setCentralWidget(self.CentralWidget)
self.Layout = QGridLayout(self.CentralWidget)
self.Histogram = TH1F("histogram", "histogram", 100, 0, 100)
self.Address = sip.unwrapinstance(self.CentralWidget)
self.Canvas = TQtWidget(sip.voidptr(self.Address).ascobject())

self.Layout.addWidget(sip.wrapinstance(AddressOf(self.Canvas)[0],
QWidget), 0, 0)
self.Histogram.Draw()

if __name__ == '__main__':
w = window()
w.resize(350, 350)
w.show()
raw_input('Press return to exit...')
Fine, Valeri
2007-01-16 15:27:43 UTC
Permalink
Hi Luca, Thank you very much for your update.

I'll investigate how PyROOT manages the ROOT event loop today to provide you the further assistance.

Mean time I need to know whether you did customize your $ROOTSYS/etc/system.rootrc or provide your custom ".rootrc" somewhere. Can you send me these files? May be we should discuss the QtRoot issue via http://lists.bnl.gov/mailman/listinfo/qt-root-l <http://lists.bnl.gov/mailman/listinfo/qt-root-l> to avoid the ROOTTALK pollution.
Post by Johan Bregeon
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
and proposed the "way" to eliminate it. We need a Python's guru advice to avoid "qtcint" shared library usage. Please, let me know whether I should elaborate further.

Have a nice day, Valeri


________________________________

From: Luca Baldini [mailto:***@pi.infn.it]
Sent: Tue 1/16/2007 9:53 AM
To: Fine, Valeri
Cc: Luca Baldini; Johan Bregeon; ***@lbl.gov; ROOT Talk
Subject: Re: [ROOT] RE: PyQt and PyROOT



Hi all,
adding some more entropy...
If we modify our "main" like this:

if __name__ == '__main__':
qt.QObject.connect(qt.qApp, qt.SIGNAL("lastWindowClosed()"), qt.qApp,
qt.SLOT("quit()"))
w = MainWindow()
w.resize(350, 350)
w.show()
qt.qApp.exec_loop()

i.e. adding the qt.qApp stuff, the windows behaves like we expect...
sometimes! Often it hangs up without
the histogram inside, but once in a while it looks ok and we're able to
get the shell back by closing the window.
Also note that we made a fresh ROOT installation with the qtFullRoot
package, as suggested by Valeri.
We don't have any error, anymore; just a couple of warnings:

[***@pcglast23 test]$ ./pyqtroot.py
** $Id: TGQt.cxx,v 1.146 2007/01/15 07:30:32 fine Exp $ this=0x89fb928
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available

Thanks a lot for your patience, hope that helps.

P.S. We also tried the ROOT.gApplication.Run(), and that does not help.
Note that by putting in the "main":

if __name__ == '__main__':
w = MainWindow()
w.resize(350, 350)
w.show()
print qt.qApp
print ROOT.gApplication

what we get is:

[***@pcglast23 test]$ ./pyqtroot.py
** $Id: TGQt.cxx,v 1.146 2007/01/15 07:30:32 fine Exp $ this=0x93078e8
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available
<qt.QApplication object at 0xb7ed302c>
<ROOT.TApplication* object ("PyROOT::TPyROOTApplication") at 0x16d7f90>

meaning that both qt.qApp and ROOT.gApplication seem to exist, at that
point.
I guess I'm confused, now.

Cheers,
Johan, Luca
Fine, Valeri
2007-01-16 15:32:04 UTC
Permalink
. . .
Post by Fine, Valeri
print qt.qApp
print ROOT.gApplication
. . .
. . .
Post by Fine, Valeri
<qt.QApplication object at 0xb7ed302c>
<ROOT.TApplication* object ("PyROOT::TPyROOTApplication") at 0x16d7f90>
. . .
Post by Fine, Valeri
meaning that both qt.qApp and ROOT.gApplication seem to exist, at that point.
I guess I'm confused, now.
Yes, this is correct both of them MUST be present.

Cheers, Valeri


________________________________

From: qt-root-l-***@lists.bnl.gov on behalf of Qt-Root integration project
Sent: Tue 1/16/2007 10:27 AM
To: Luca Baldini; qt-root-***@lists.bnl.gov
Cc: ***@lbl.gov; Johan Bregeon; ROOT Talk
Subject: Re: [Qt-root-l] [ROOT] RE: PyQt and PyROOT



Hi Luca, Thank you very much for your update.

I'll investigate how PyROOT manages the ROOT event loop today to provide you the further assistance.

Mean time I need to know whether you did customize your $ROOTSYS/etc/system.rootrc or provide your custom ".rootrc" somewhere. Can you send me these files? May be we should discuss the QtRoot issue via http://lists.bnl.gov/mailman/listinfo/qt-root-l <http://lists.bnl.gov/mailman/listinfo/qt-root-l> to avoid the ROOTTALK pollution.
Post by Fine, Valeri
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
and proposed the "way" to eliminate it. We need a Python's guru advice to avoid "qtcint" shared library usage. Please, let me know whether I should elaborate further.

Have a nice day, Valeri


________________________________

From: Luca Baldini [mailto:***@pi.infn.it]
Sent: Tue 1/16/2007 9:53 AM
To: Fine, Valeri
Cc: Luca Baldini; Johan Bregeon; ***@lbl.gov; ROOT Talk
Subject: Re: [ROOT] RE: PyQt and PyROOT



Hi all,
adding some more entropy...
If we modify our "main" like this:

if __name__ == '__main__':
qt.QObject.connect(qt.qApp, qt.SIGNAL("lastWindowClosed()"), qt.qApp,
qt.SLOT("quit()"))
w = MainWindow()
w.resize(350, 350)
w.show()
qt.qApp.exec_loop()

i.e. adding the qt.qApp stuff, the windows behaves like we expect...
sometimes! Often it hangs up without
the histogram inside, but once in a while it looks ok and we're able to
get the shell back by closing the window.
Also note that we made a fresh ROOT installation with the qtFullRoot
package, as suggested by Valeri.
We don't have any error, anymore; just a couple of warnings:

[***@pcglast23 test]$ ./pyqtroot.py
** $Id: TGQt.cxx,v 1.146 2007/01/15 07:30:32 fine Exp $ this=0x89fb928
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available

Thanks a lot for your patience, hope that helps.

P.S. We also tried the ROOT.gApplication.Run(), and that does not help.
Note that by putting in the "main":

if __name__ == '__main__':
w = MainWindow()
w.resize(350, 350)
w.show()
print qt.qApp
print ROOT.gApplication

what we get is:

[***@pcglast23 test]$ ./pyqtroot.py
** $Id: TGQt.cxx,v 1.146 2007/01/15 07:30:32 fine Exp $ this=0x93078e8
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available
<qt.QApplication object at 0xb7ed302c>
<ROOT.TApplication* object ("PyROOT::TPyROOTApplication") at 0x16d7f90>

meaning that both qt.qApp and ROOT.gApplication seem to exist, at that
point.
I guess I'm confused, now.

Cheers,
Johan, Luca
Fine, Valeri
2007-01-16 22:44:31 UTC
Permalink
Hello Luca,
From the first glance the main trouble to run GUI (it doesn't matter
which one Root or Qt at this point) application from PyROOT comes from
the PyROOT code:

# root thread, if needed, to prevent GUIs from starving, as needed
if not self.keeppolling and not _root.gROOT.IsBatch():
import threading
self.__dict__[ 'keeppolling' ] = 1
self.__dict__[ 'thread' ] = \
threading.Thread( None, _processRootEvents, None, ( self, )
)
self.thread.setDaemon( 1 )
self.thread.start()


Therefore, can you check whether PyROOT is capable to run the standard
ROOT "guitest.cxx" example with no crash? Sorry, I had no time to check
this myself.

Can you

1. comment out the line of $ROOTSYS/pyroot/ROOT.py:

self.thread.start()

2. Start your main with the line

print ROOT.gApplication

3. add the line

ROOT.gApplication.Run()

as the very last line of your main

4. Re-run your script.


I.e. do something like this:

if __name__ == '__main__':
print ROOT.gApplication
application = qt.qApp
qt.QObject.connect(application,. . . )
w = MainWindow()
w.show()
w.resize(350, 350)
w.show()
ROOT.gApplication.Run()


Thank you,

Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Tuesday, January 16, 2007 10:28 AM
Subject: Re: [Qt-root-l] [ROOT] RE: PyQt and PyROOT
Hi Luca, Thank you very much for your update.
I'll investigate how PyROOT manages the ROOT event loop today to
provide
you the further assistance.
Mean time I need to know whether you did customize your
$ROOTSYS/etc/system.rootrc or provide your custom ".rootrc" somewhere.
Can
you send me these files? May be we should discuss the QtRoot issue via
http://lists.bnl.gov/mailman/listinfo/qt-root-l
<http://lists.bnl.gov/mailman/listinfo/qt-root-l> to avoid the
ROOTTALK
pollution.
Post by Johan Bregeon
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
and proposed the "way" to eliminate it. We need a Python's guru advice
to
avoid "qtcint" shared library usage. Please, let me know whether I
should
elaborate further.
Have a nice day, Valeri
________________________________
Sent: Tue 1/16/2007 9:53 AM
To: Fine, Valeri
Subject: Re: [ROOT] RE: PyQt and PyROOT
Hi all,
adding some more entropy...
qt.QObject.connect(qt.qApp, qt.SIGNAL("lastWindowClosed()"), qt.qApp,
qt.SLOT("quit()"))
w = MainWindow()
w.resize(350, 350)
w.show()
qt.qApp.exec_loop()
i.e. adding the qt.qApp stuff, the windows behaves like we expect...
sometimes! Often it hangs up without
the histogram inside, but once in a while it looks ok and we're able to
get the shell back by closing the window.
Also note that we made a fresh ROOT installation with the qtFullRoot
package, as suggested by Valeri.
** $Id: TGQt.cxx,v 1.146 2007/01/15 07:30:32 fine Exp $ this=0x89fb928
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available
Thanks a lot for your patience, hope that helps.
P.S. We also tried the ROOT.gApplication.Run(), and that does not help.
w = MainWindow()
w.resize(350, 350)
w.show()
print qt.qApp
print ROOT.gApplication
** $Id: TGQt.cxx,v 1.146 2007/01/15 07:30:32 fine Exp $ this=0x93078e8
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available
<qt.QApplication object at 0xb7ed302c>
<ROOT.TApplication* object ("PyROOT::TPyROOTApplication") at
0x16d7f90>
meaning that both qt.qApp and ROOT.gApplication seem to exist, at that
point.
I guess I'm confused, now.
Cheers,
Johan, Luca
_______________________________________________
Qt-Root-l mailing list
http://lists.bnl.gov/mailman/listinfo/qt-root-l
W***@lbl.gov
2007-01-17 04:17:58 UTC
Permalink
Valeri,
Post by Fine, Valeri
May be Wim can look up the C++ code sent last time to tell us where, how,
and when the PyROOT implements the
TRint *theApp = new TRint("Rint", &argc, argv);
and
theApp->Run();
May be the only thing you should do is to call
gApplication.Run()
there is no such call b/c it would interfere with the normal python command
line interpreter processing (the call doesn't return until done, so all that
time no python code will be executed). The way PyROOT is implemented means
that ROOT is invoked from Python, not the other way around; if you want just
the opposite, you can start with CINT, then call python:

$ cat runpython.C
{
gSystem->Load( "libPyROOT" );
TPython::Prompt();
}
$ root -l -q runpython.C
root [0]
Processing runpython.C...
Or similarly TPython::ExecScript() to start a python script from CINT (still
in-process). That way, you can do any normal setup the RINT way, as you like,
and f'up with running python.

Best regards,
Wim
--
***@cern.ch -- ***@lbl.gov -- www.lavrijsen.net

"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Fine, Valeri
2007-01-17 04:59:13 UTC
Permalink
Hi Wim, I think the poor guys will welcome your comments and kind assistance.
if you want just the opposite,
I hope these guys will explain you better what they want ;)
What about me.
I am very sorry, but I still have to write my first Python script yet :)

My best regards, Valeri

________________________________

From: ***@lbl.gov [mailto:***@lbl.gov]
Sent: Tue 1/16/2007 11:17 PM
To: Fine, Valeri
Cc: Luca Baldini; Johan Bregeon; ROOT Talk
Subject: RE: [ROOT] RE: PyQt and PyROOT



Valeri,
May be Wim can look up the C++ code sent last time to tell us where, how,
and when the PyROOT implements the
TRint *theApp = new TRint("Rint", &argc, argv);
and
theApp->Run();
May be the only thing you should do is to call
gApplication.Run()
there is no such call b/c it would interfere with the normal python command
line interpreter processing (the call doesn't return until done, so all that
time no python code will be executed). The way PyROOT is implemented means
that ROOT is invoked from Python, not the other way around; if you want just
the opposite, you can start with CINT, then call python:

$ cat runpython.C
{
gSystem->Load( "libPyROOT" );
TPython::Prompt();
}
$ root -l -q runpython.C
root [0]
Processing runpython.C...
Or similarly TPython::ExecScript() to start a python script from CINT (still
in-process). That way, you can do any normal setup the RINT way, as you like,
and f'up with running python.

Best regards,
Wim
--
***@cern.ch -- ***@lbl.gov -- www.lavrijsen.net

"Stop making excuses for your software." --first step towards quality
"GIGO is not a valid design pattern." --corollary
Johan Bregeon
2007-01-17 15:35:07 UTC
Permalink
Hello all again,
I have tried to build an example of a Root GUI with a couple of buttons
with pyroot only (no qt here).
I managed to have it almost working :
+ the window shows up with the canvas inside and I can close it safely
with the cross
+ the window can be resized or moved with no problems

The problem is that I cannot make the "Connect" between a button and a
function, a the connect methode ask for a void pointer (usually 'this'
in c++) that I cannot provide (using 'self' gives a seg. fault).

Here is the main :
tgwindow = ROOT.gClient.GetRoot()
window = gMainWindow(tgwindow, 200, 200)
ROOT.gClient.WaitFor(window.MainFrame)

The last line is the trick I found, not to have the application hanging
up...
See the script attached and comments inside,
Best Regards,
Johan
Fine, Valeri
2007-01-16 04:37:42 UTC
Permalink
Hello Johan,
I have re-read your message.
Did I understand you properly that you did not remove the line

application.exec_loop()

from your script? Why ?

________________________________

From: Johan Bregeon [mailto:***@pi.infn.it]
Sent: Fri 1/12/2007 10:25 AM
To: ***@lbl.gov
Cc: Fine, Valeri; Luca Baldini; ROOT Talk
Subject: Re: [ROOT] RE: PyQt and PyROOT



Hello all,
Thanks to your comments, we were able to make a step forward.
We actually had to use both 'qtcint' and sip to have something working.
Here is the piece of code :
------------------------------------------------------------------------------------
import sys
import qt
import ROOT
import sip
ROOT.gSystem.Load('qtcint')

class window(qt.QMainWindow):
def __init__(self):
# Init the main window.
qt.QMainWindow.__init__(self)
self.resize(350, 350)

# Create the central widget.
self.CentralWidget = qt.QWidget()
self.setCentralWidget(self.CentralWidget)
self.Layout = qt.QGridLayout(self.CentralWidget)

# Create a root histogram.
self.hist = ROOT.TH1F("pipo","pipo", 100, 0, 100)

# Create the main TQtWidget (using sip to get the pointer to the
central widget).
self.Address = sip.unwrapinstance(self.CentralWidget)
self.Canvas = ROOT.TQtWidget(sip.voidptr(self.Address).ascobject())
self.Canvas.resize(300, 300)

# Place the TQtWidget in the main grid layout and draw the histogram.

self.Layout.addWidget(sip.wrapinstance(ROOT.AddressOf(self.Canvas)[0],
qt.QWidget), 0, 0)
self.Canvas.show()
self.Canvas.cd()
self.hist.Draw()
self.Canvas.Refresh()

if __name__ == '__main__':
application = qt.QApplication(sys.argv)
qt.QObject.connect(application, qt.SIGNAL("lastWindowClosed()"),
application, qt.SLOT("quit()"))
w = window()
w.show()
application.exec_loop()
------------------------------------------------------------------------------------

It's almost doing what we want to...meaning, that it's running but
ultimately the Histogram does not show up on the GUI.
Notes :
+ If we add the histogram directly to the 'MainWindow' it's working,
but we obviously need the 'layout' step to work.

We also have these warnings :
$ python pyqtroot.py
** $Id: TGQt.cxx,v 1.35 2006/12/12 20:12:47 brun Exp $ this=0x9fc8d90
Error in <TUnixSystem::DynamicPathName>: QtGui[.so | .sl | .dl | .a |
.dll] does not exist in
$(ROOTSYS)/cint/include:.:/usr/local/root/v5.14.00/lib:/usr/local/root/v5.14.00/lib:/usr/local/python2.5/lib:/usr/local/lib
QApplication: There should be max one application object
Warning in <TClass::TClass>: no dictionary for class Qt is available
Warning in <TClass::TClass>: no dictionary for class QPaintDevice is
available

1) Where does this QtGui library comes from ? (there seems to be one in
qt4 but we do not have any in qt3)
2) What is creating the 'other' QApplication ? (we instance only one in
the main !)
3) We're now loading the 'qtcint' dictionnary, so why some Qt class
dictionaries are still missing ?

Thanks for comments,
cheers
Johan
Fine, Valeri
2007-01-18 22:55:18 UTC
Permalink
Hello Luca,

I have installed PyQt and tested it with the simple script involving

"Python + PyQt + Sim + PyROOT + QtRoot"

( uhh !!! ) the scaring number of the layers (Rene is right !)

Anyway

1. I was not able to reproduce your troubles (ROOT 5.14, Python 2.5).
It works.

2. No need for "qtcint.dll" was found (as one expected).
It works fine without this dll. (One component less to care about).

The working version of the python script was included into QtRoot CVS
(see:
http://www.star.bnl.gov/cgi-bin/cvsweb.cgi/QtRoot/qtExamples/HelloPython
/
and some extra details were posted via the Qt-root mail list
Please, use this mail list to communicate your future QtRoot related
questions.

Best Regards
Valeri Fine
---------------
Brookhaven National Laboratory
Upton, NY 11973, USA
Phone: +1 631 344 7806
Fax: +1 631 344 4206
-----Original Message-----
Sent: Tuesday, January 16, 2007 3:31 AM
To: Fine, Valeri
Subject: Re: [ROOT] RE: PyQt and PyROOT
Hi Valeri,
this is the best we could do, so far, following your suggestions.
The script works, except for the fact that it needs the last
raw_input()
stuff, otherwise the window get closed
immediately. I still don't get that, it looks like the application
main
loop is not running...
Also, we would like to be able to close the application by clicking on
the window, rather than pressing a
key on the prompt.
#!/bin/env python
import sip
from qt import QMainWindow, QWidget, QGridLayout
from ROOT import TH1F, TQtWidget, gSystem, AddressOf
gSystem.Load('qtcint')
QMainWindow.__init__(self)
self.CentralWidget = QWidget(self)
self.setCentralWidget(self.CentralWidget)
self.Layout = QGridLayout(self.CentralWidget)
self.Histogram = TH1F("histogram", "histogram", 100, 0, 100)
self.Address = sip.unwrapinstance(self.CentralWidget)
self.Canvas =
TQtWidget(sip.voidptr(self.Address).ascobject())
self.Layout.addWidget(sip.wrapinstance(AddressOf(self.Canvas)[0],
QWidget), 0, 0)
self.Histogram.Draw()
w = window()
w.resize(350, 350)
w.show()
raw_input('Press return to exit...')
Loading...