PyCall on PyQt

667 views
Skip to first unread message

J Luis

unread,
Apr 9, 2013, 5:55:40 PM4/9/13
to juli...@googlegroups.com
Hi,

I'm trying to run the simplest "Hello there" example in PyQy called by PyCall (actually, this http://zetcode.com/tutorials/pyqt4/firstprograms)
So I do:

julia> using PyCall

julia> pyinitialize("python27")

julia> @pyimport PyQt4

julia> @pyimport PyQt4.QtGui as gui

julia> @pyimport sys

julia> app = gui.QApplication(sys.argv)
PyObject <PyQt4.QtGui.QApplication object at 0x0F7D6348>

julia> w = gui.QWidget()
PyObject <PyQt4.QtGui.QWidget object at 0x0F7D6390>

julia> w.resize(250, 150)
ERROR: type PyObject has no field resize


However, doing the equivalent in a python shell

...

In [4]: w = QtGui.QWidget()

In [5]: w.resize(250, 150)

In [6]: w
Out[6]: <PyQt4.QtGui.QWidget at 0x37e7f60>

so the object description is equal from both julia and python, but from julia the the 'resize' method (and the others in the PyQt example) is not visible.

My error?

Joaquim

Isaiah Norton

unread,
Apr 9, 2013, 8:32:03 PM4/9/13
to juli...@googlegroups.com
try w[:resize](250,150)

see the readme section starting with:
 
The biggest diffence from Python is that object attributes/members are accessed with o[:attribute] rather than o.attribute

J Luis

unread,
Apr 9, 2013, 9:05:31 PM4/9/13
to juli...@googlegroups.com
Thanks, that was it. But, there is one more issue. The last command ( w[:show]() ) effectively creates one little window but it comes out in a "Not responding" mode and when I kill it I'm kicked out of julia.

w[:resize](250,150)
w[:move](300,300)
w[:setWindowTitle]("Simple")
w[:show]()

Isaiah Norton

unread,
Apr 9, 2013, 9:38:16 PM4/9/13
to juli...@googlegroups.com
I was afraid of that, the problem is the qt event loop. You could start by looking at how the Tk event loop is integrated with Julia, and try to do something similar. I haven't seen any measurements of PyCall overhead, so not sure if polling would be viable (and there are problems with that in the best circumstances).

It might be worth trying this in IPython, because IP knows about the Qt event loop already (if you use the Qt-enabled version). If I recall correctly, IPython is using a separate Qt thread (there might be some way to pull this off through PyCall...).

jverzani

unread,
Apr 11, 2013, 10:05:43 PM4/11/13
to juli...@googlegroups.com
I followed the pattern in Tk and Gtk with processing the event loop to get this, which works as a start:

using PyCall




@pyimport PyQt4
@pyimport PyQt4.QtGui as Qt
@pyimport sys


app
= Qt.QApplication(sys.argv)


## from gtk_doevent, tk_doevent pattern
qt_doevent
(::Int32) = qt_doevent()
function qt_doevent()
    app
[:processEvents]()
end


global timeout
timeout
= Base.TimeoutAsyncWork(qt_doevent)
Base.start_timer(timeout,int64(20),int64(20))


## test it with a Qt example
w
= Qt.QWidget()
w
[:setWindowTitle]("Example")


lcd
= Qt.QLCDNumber(w)
sld
= Qt.QSlider(w)
btn
= Qt.QPushButton(w); btn[:setText]("click me")


vbox
= Qt.QVBoxLayout()
map
(u -> vbox[:addWidget](u), (lcd, sld, btn))


w
[:setLayout](vbox)


## connect valueChanged signal of sld with display slot of lcd
sld
[:valueChanged][:connect](lcd[:display])


## connect a callback to clicked event
btn
[:clicked][:connect](x -> print("clicked"))


w
[:show]()


J Luis

unread,
Apr 12, 2013, 8:32:30 AM4/12/13
to juli...@googlegroups.com
Thanks

It works ... partially ... on Windows. At the end it raises errors on (but the window is displayed and does not hang)

julia> sld[:valueChanged][:connect](lcd[:display])
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

julia> btn[:clicked][:connect](x -> print("clicked"))
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

jverzani

unread,
Apr 12, 2013, 8:54:38 AM4/12/13
to juli...@googlegroups.com
Interesting, the signal/slot thing worked with my Mac. Does the anonymous callback for the button work? I was thinking there would need to be some wrapper for a callback written in julia, but PyCall magically handles that it seems even distinguishing the number of arguments, though I didn't check if does type checking.

J Luis

unread,
Apr 12, 2013, 9:48:53 AM4/12/13
to juli...@googlegroups.com
No, the callback is not executed. It couldn't because the instruction that connects the callback raises an error too.


julia> btn[:clicked][:connect](x -> print("clicked"))
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous


Steven G. Johnson

unread,
Apr 12, 2013, 2:38:33 PM4/12/13
to juli...@googlegroups.com


On Friday, April 12, 2013 9:48:53 AM UTC-4, J Luis wrote:
No, the callback is not executed. It couldn't because the instruction that connects the callback raises an error too.

julia> btn[:clicked][:connect](x -> print("clicked"))
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

That sounds like it could be a Julia bug if it is occurring on Windows but not on Mac; are you using an up-to-date git version?

A bit hard to track down since the error message does not indicate which line of PyCall triggered the message.  You could try breaking it into pieces: does btn[:clicked] work?  btn[:clicked][:connect]?   

J Luis

unread,
Apr 12, 2013, 8:17:37 PM4/12/13
to juli...@googlegroups.com
Yes, I'm using a fairly recent version (actually I just rebuilt it) and (this error comes first than the one at "btn[:clicked][:connect](x -> print("clicked"))"):

julia> sld[:valueChanged][:connect]
# methods for generic function fn
fn(args...)

julia> lcd[:display]
# methods for generic function fn
fn(args...)


julia> sld[:valueChanged][:connect](lcd[:display])
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous



Steven G. Johnson

unread,
Apr 13, 2013, 8:36:37 AM4/13/13
to juli...@googlegroups.com


On Friday, April 12, 2013 8:17:37 PM UTC-4, J Luis wrote:
Yes, I'm using a fairly recent version (actually I just rebuilt it) and (this error comes first than the one at "btn[:clicked][:connect](x -> print("clicked"))"):

julia> sld[:valueChanged][:connect]
# methods for generic function fn
fn(args...)

julia> lcd[:display]
# methods for generic function fn
fn(args...)

julia> sld[:valueChanged][:connect](lcd[:display])
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

How about  sld[:valueChanged][:connect](lcd["display"])  (which passes the lcd.display Python object directly, rather than converting it to a Julia function and then back to Python)?   Or how about PyObject(lcd[:display]) (which only exercises the Julia function -> Python code)?

Also try running (via include(....)) the .julia/PyCall/test/test.jl script to see if PyCall's self-tests pass.

Steven

J Luis

unread,
Apr 13, 2013, 9:54:27 AM4/13/13
to juli...@googlegroups.com

How about  sld[:valueChanged][:connect](lcd["display"])  (which passes the lcd.display Python object directly, rather than converting it to a Julia function and then back to Python)?   Or how about PyObject(lcd[:display]) (which only exercises the Julia function -> Python code)?

Ah, a little better


julia> sld[:valueChanged][:connect](lcd["display"])

julia> PyObject(lcd[:display])

ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous
 

 
Also try running (via include(....)) the .julia/PyCall/test/test.jl script to see if PyCall's self-tests pass.

To run that test I had to add the line with
pyinitialize("python27")

and

ERROR: test error during :((pycall(PyObject(x->begin  # C:\j\.julia\PyCall\test\test.jl, line 26:
                        +(x,1)
                    end),PyAny,314158)==314159))

error compiling anonymous: unsupported or misplaced expression & in function anonymous
 in PyTypeObject at C:\j\.julia\PyCall\src\pytype.jl:218
 in pyjlwrap_type at C:\j\.julia\PyCall\src\pytype.jl:384
 in pycallback_initialize at C:\j\.julia\PyCall\src\callback.jl:65
 in pycallback at C:\j\.julia\PyCall\src\callback.jl:80
 in PyObject at C:\j\.julia\PyCall\src\callback.jl:85
 in anonymous at test.jl:50
 in do_test at test.jl:34
 in include_from_node1 at loading.jl:88
 in reload_path at loading.jl:111
 in require at loading.jl:46
at C:\j\.julia\PyCall\test\test.jl:26

Joaquim

Steven G. Johnson

unread,
Apr 13, 2013, 10:06:50 AM4/13/13
to juli...@googlegroups.com
Okay, it looks like the problem is the & in the function argument of:

function pyjlwrap_type(name::String, init::Function)
    pyjlwrap_init()
    PyTypeObject(name,
                 sizeof(Py_jlWrap) + sizeof(PyPtr), # must be > base type      
                 t::PyTypeObject -> begin
                     t.tp_base = ccall(:jl_value_ptr, Ptr{Void},
                                       (Ptr{PyTypeObject},),
                                       &(jlWrapType::PyTypeObject))
                     init(t)
                 end)
end

(This code is just using the jl_value_ptr function as an identity function in order to get the address of the struct data, since & can't be used outside of ccall; it should become unnecessary once #2818 is merged.)

Can you try:

     type Foo; bar::Int; end
     foo = Foo(1)
     ccall(:jl_value_ptr, Ptr{Void}, (Ptr{Foo},), &(foo::Foo))

?  It works fine for me on MacOS and GNU/Linux.

J Luis

unread,
Apr 13, 2013, 10:19:42 AM4/13/13
to juli...@googlegroups.com


Sábado, 13 de Abril de 2013 15:06:50 UTC+1, Steven G. Johnson escreveu:
Okay, it looks like the problem is the & in the function argument of:

function pyjlwrap_type(name::String, init::Function)
    pyjlwrap_init()
    PyTypeObject(name,
                 sizeof(Py_jlWrap) + sizeof(PyPtr), # must be > base type      
                 t::PyTypeObject -> begin
                     t.tp_base = ccall(:jl_value_ptr, Ptr{Void},
                                       (Ptr{PyTypeObject},),
                                       &(jlWrapType::PyTypeObject))
                     init(t)
                 end)
end

(This code is just using the jl_value_ptr function as an identity function in order to get the address of the struct data, since & can't be used outside of ccall; it should become unnecessary once #2818 is merged.)

Can you try:

     type Foo; bar::Int; end
     foo = Foo(1)
     ccall(:jl_value_ptr, Ptr{Void}, (Ptr{Foo},), &(foo::Foo))

?  It works fine for me on MacOS and GNU/Linux.


You found it. Same error

julia> ccall(:jl_value_ptr, Ptr{Void}, (Ptr{Foo},), &(foo::Foo))
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

Steven G. Johnson

unread,
Apr 13, 2013, 10:31:44 AM4/13/13
to juli...@googlegroups.com
On Saturday, April 13, 2013 10:19:42 AM UTC-4, J Luis wrote:
Can you try:

     type Foo; bar::Int; end
     foo = Foo(1)
     ccall(:jl_value_ptr, Ptr{Void}, (Ptr{Foo},), &(foo::Foo))

?  It works fine for me on MacOS and GNU/Linux.


You found it. Same error

julia> ccall(:jl_value_ptr, Ptr{Void}, (Ptr{Foo},), &(foo::Foo))
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

Can you please file a Julia issue for this?  I don't see why this should fail on Windows only, so it seems like a Julia bug.

J Luis

unread,
Apr 13, 2013, 10:49:51 AM4/13/13
to juli...@googlegroups.com

You found it. Same error

julia> ccall(:jl_value_ptr, Ptr{Void}, (Ptr{Foo},), &(foo::Foo))
ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

Can you please file a Julia issue for this?  I don't see why this should fail on Windows only, so it seems like a Julia bug.

OK, I did but just not sure if I gave it a sufficiently good description of the problem

jverzani

unread,
Apr 13, 2013, 9:09:14 PM4/13/13
to juli...@googlegroups.com
In case anyone is interested, I wrapped this event loop setup and some other conveniences into a package PySide. (I used PySide instead of PyQt, as the installation was really easy and it did a better job with some conversions.)



If there is any interest it can be added to METADATA.

While it doesn't have a cairo canvas to draw Winston graphics to, this way to get at a graphical toolkit seems much better than either Tk or Gtk despite the intermediate hop through python via the excellent PyCall package.

Tim Holy

unread,
Apr 14, 2013, 5:21:02 AM4/14/13
to juli...@googlegroups.com
On Saturday, April 13, 2013 06:09:14 PM jverzani wrote:
> If there is any interest it can be added to METADATA.
>
> While it doesn't have a cairo canvas to draw Winston graphics to, this way
> to get at a graphical toolkit seems much better than either Tk or Gtk
> despite the intermediate hop through python via the excellent PyCall
> package.

I definitely think that access to Qt is interesting, although currently I lack
the time to do anything with that opportunity. There have been several times
in the past where I've wondered whether it would be wiser to skip the
alternatives and go straight for Qt, despite the massive up-front cost of
figuring out how to interact with a huge C++ library.

--Tim

J Luis

unread,
Apr 15, 2013, 9:55:34 AM4/15/13
to juli...@googlegroups.com
Thank you, but still no luck for me on Windows
I still get that error (this time from within the call of  "qconnect(btn, :clicked)" )


ERROR: error compiling anonymous: unsupported or misplaced expression & in function anonymous

Joaquim

jverzani

unread,
Apr 15, 2013, 10:29:33 AM4/15/13
to juli...@googlegroups.com
Until this issue: https://github.com/JuliaLang/julia/issues/2850 gets sorted out I'm not sure this will work out for windows users.
Reply all
Reply to author
Forward
0 new messages