Using qui rather than rbuic for qtdesigner .ui files

Discussion in 'Ruby' started by David Brunell, Jan 14, 2009.

  1. I'm trying to load .ui files at runtime using the qui extension and
    WidgetFactory rather than pre-translating the .ui XML file to ruby with
    rbuic. Here's a simple program:

    require 'Qt'
    require 'qui'
    a = Qt::Application.new(ARGV)
    w = QUI::WidgetFactory.create "sampledialog.ui"
    w.show()
    a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
    a.exec()

    This works just fine in that it dynamically loads and presents the .ui
    file as a window. However, how do I connect signals and slots? I
    understand the process of method override when doing it the rbuic way,
    but this doesn't seem to be working with WidgetFactory. The signals and
    slots (but not their handling) are defined in the .ui file. Could
    someone give this noob an example of how to implement a slot method? I
    tried looking at some C++ examples, but I'm just not making the
    connection to ruby. The .ui file is below. It just has two buttons,
    Test and Close.

    Thanks,

    David


    <!DOCTYPE UI><UI version="3.3" stdsetdef="1">
    <class>SampleDialogUI</class>
    <widget class="QDialog">
    <property name="name">
    <cstring>SampleDialogUI</cstring>
    </property>
    <property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>155</width>
    <height>45</height>
    </rect>
    </property>
    <property name="caption">
    <string>Sample Dialog</string>
    </property>
    <property name="modal">
    <bool>true</bool>
    </property>
    <grid>
    <property name="name">
    <cstring>unnamed</cstring>
    </property>
    <widget class="QPushButton" row="1" column="2">
    <property name="name">
    <cstring>closeButton</cstring>
    </property>
    <property name="text">
    <string>Close</string>
    </property>
    <property name="toolTip" stdset="0">
    <string>Close this dialog</string>
    </property>
    </widget>
    <widget class="QPushButton" row="1" column="1">
    <property name="name">
    <cstring>testButton</cstring>
    </property>
    <property name="text">
    <string>Test</string>
    </property>
    <property name="toolTip" stdset="0">
    <string>Test command execution</string>
    </property>
    </widget>
    </grid>
    </widget>
    <connections>
    <connection>
    <sender>testButton</sender>
    <signal>clicked()</signal>
    <receiver>SampleDialogUI</receiver>
    <slot>testButton_clicked()</slot>
    </connection>
    <connection>
    <sender>closeButton</sender>
    <signal>clicked()</signal>
    <receiver>SampleDialogUI</receiver>
    <slot>closeButton_clicked()</slot>
    </connection>
    </connections>
    <slots>
    <slot>testButton_clicked()</slot>
    <slot>closeButton_clicked()</slot>
    </slots>
    <layoutdefaults spacing="6" margin="11"/>
    </UI>
    --
    Posted via http://www.ruby-forum.com/.
     
    David Brunell, Jan 14, 2009
    #1
    1. Advertising

  2. Alle mercoled=C3=AC 14 gennaio 2009, David Brunell ha scritto:
    > I'm trying to load .ui files at runtime using the qui extension and
    > WidgetFactory rather than pre-translating the .ui XML file to ruby with
    > rbuic. Here's a simple program:
    >
    > require 'Qt'
    > require 'qui'
    > a =3D Qt::Application.new(ARGV)
    > w =3D QUI::WidgetFactory.create "sampledialog.ui"
    > w.show()
    > a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
    > a.exec()
    >
    > This works just fine in that it dynamically loads and presents the .ui
    > file as a window. However, how do I connect signals and slots? I
    > understand the process of method override when doing it the rbuic way,
    > but this doesn't seem to be working with WidgetFactory. The signals and
    > slots (but not their handling) are defined in the .ui file. Could
    > someone give this noob an example of how to implement a slot method? I
    > tried looking at some C++ examples, but I'm just not making the
    > connection to ruby. The .ui file is below. It just has two buttons,
    > Test and Close.
    >
    > Thanks,
    >
    > David


    Not tested, because I'm using Qt 4 while, I think, you're using Qt 3. The i=
    dea=20
    is to create a custom widget class and to add the widget returned by=20
    WidgetFactory.create as child widget. You shouldn't define custom slots in =
    the=20
    ui file, since there's no way to implement them. Any custom slot you'd defi=
    ne=20
    in the ui file is instead defined in the custom widget. Here's a simple=20
    example which should work:

    require 'Qt'
    require 'qui'

    class MainWidget < Qt::Widget
    =20
    slots 'test()'
    =20
    def initialize
    @widget =3D QUI::WidgetFactory.create "sampledialog.ui"
    self.layout =3D Qt::VBoxLayout.new
    self.layout.add_widget @widget
    connect @widget.child('testButton'), SIGNAL('clicked()'), self,=20
    SLOT('test()')
    end
    =20
    def test
    puts "test button clicked"
    end
    =20
    end

    app =3D Qt::Application.new ARGV
    w =3D MainWidget.new=20
    w.show
    a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
    a.exec


    I hope this helps

    Stefano
     
    Stefano Crocco, Jan 14, 2009
    #2
    1. Advertising

  3. Stefano Crocco wrote:
    > require 'Qt'
    > require 'qui'
    >
    > class MainWidget < Qt::Widget
    >
    > slots 'test()'
    >
    > def initialize
    > @widget = QUI::WidgetFactory.create "sampledialog.ui"
    > self.layout = Qt::VBoxLayout.new
    > self.layout.add_widget @widget
    > connect @widget.child('testButton'), SIGNAL('clicked()'), self,
    > SLOT('test()')
    > end
    >
    > def test
    > puts "test button clicked"
    > end
    >
    > end
    >
    > app = Qt::Application.new ARGV
    > w = MainWidget.new
    > w.show
    > a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
    > a.exec


    Many thanks for your kind reply. I get the following error when running
    your suggested code:

    quitest2.rb:10:in `method_missing': undefined method `layout=' for
    :MainWidget (NoMethodError)

    I somewhat understand this error, but upon commenting out the two
    self.layout lines, I then get the following error:

    quitest2.rb:12:in `method_missing': super: no superclass method
    `connect'(NoMethodError)

    If I change "connect" to "Qt::Object.connect" (this is what the rbuic
    compiler would generate) the error persists. Any ideas?

    Thanks,

    David
    --
    Posted via http://www.ruby-forum.com/.
     
    David Brunell, Jan 15, 2009
    #3
  4. Alle gioved=C3=AC 15 gennaio 2009, David Brunell ha scritto:
    > Stefano Crocco wrote:
    > > require 'Qt'
    > > require 'qui'
    > >
    > > class MainWidget < Qt::Widget
    > >
    > > slots 'test()'
    > >
    > > def initialize
    > > @widget =3D QUI::WidgetFactory.create "sampledialog.ui"
    > > self.layout =3D Qt::VBoxLayout.new
    > > self.layout.add_widget @widget
    > > connect @widget.child('testButton'), SIGNAL('clicked()'), self,
    > > SLOT('test()')
    > > end
    > >
    > > def test
    > > puts "test button clicked"
    > > end
    > >
    > > end
    > >
    > > app =3D Qt::Application.new ARGV
    > > w =3D MainWidget.new
    > > w.show
    > > a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
    > > a.exec

    >
    > Many thanks for your kind reply. I get the following error when running
    > your suggested code:
    >
    > quitest2.rb:10:in `method_missing': undefined method `layout=3D' for
    >
    > :MainWidget (NoMethodError)
    >
    > I somewhat understand this error, but upon commenting out the two
    > self.layout lines, I then get the following error:
    >
    > quitest2.rb:12:in `method_missing': super: no superclass method
    > `connect'(NoMethodError)


    Sorry, I forgot one line. The initialize method should be:

    def initialize
    super # this is the new part
    @widget =3D QUI::WidgetFactory.create "sampledialog.ui"
    self.layout =3D Qt::VBoxLayout.new
    self.layout.add_widget @widget
    connect @widget.child('testButton'), SIGNAL('clicked()'), self,=20
    SLOT('test()')
    end

    This will solve the second problem and most likely also the first. If the f=
    irs=20
    remains, try replacing

    self.layout =3D

    set_layout

    Stefano
     
    Stefano Crocco, Jan 15, 2009
    #4
  5. Stefano Crocco wrote:

    > Sorry, I forgot one line. The initialize method should be:
    >
    > def initialize
    > super # this is the new part


    Well, now I get no errors. However, the dialog which appears is a blank
    dialog, not the one which I designed with Qt designer. Any thoughts? I
    can always go back to the rbuic compiler if I have to. Here is my code
    at this point:

    ########################
    require 'Qt'
    require 'qui'

    class MainWidget < Qt::Widget

    slots 'test()'

    def initialize
    super
    @widget = QUI::WidgetFactory.create "sampledialog.ui"
    set_layout = Qt::VBoxLayout.new
    set_layout.add_widget @widget
    connect @widget.child('testButton'), SIGNAL('clicked()'), self,
    SLOT('test()')
    end

    def test
    puts "test button clicked"
    end

    end

    a = Qt::Application.new ARGV
    w = MainWidget.new
    w.show
    a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
    a.exec
    ################################

    Many thanks,

    David
    --
    Posted via http://www.ruby-forum.com/.
     
    David Brunell, Jan 18, 2009
    #5
  6. Ok, I got it working. Here is my code:

    ##########################################
    require 'Qt'
    require 'qui'

    class MainWidget < Qt::Widget

    slots 'test()', 'close()'

    def initialize(app)
    super()
    @app = app
    @widget = QUI::WidgetFactory.create "sampledialog.ui"
    connect @widget.child('testButton'), SIGNAL('clicked()'), self,
    SLOT('test()')
    connect @widget.child('closeButton'), SIGNAL('clicked()'), self,
    SLOT('close()')
    @widget.show
    end

    def test
    puts "test button clicked"
    end

    def close
    @app.exit(0)
    end

    end

    app = Qt::Application.new ARGV
    dialog = MainWidget.new(app)
    app.exec
    ######################################

    The .ui file is the same as in the original post. I'm not sure this is
    the most elegant way to make it work, so if you have any ideas on how to
    clean it up, I'm open to suggestions.

    One other question...what about Qt4? I think I need rbuic4 if I am
    going to pre-compile the ui. Is there a qui4 for dynamic loading?

    Kind regards,

    David

    --
    Posted via http://www.ruby-forum.com/.
     
    David Brunell, Jan 19, 2009
    #6
  7. Alle luned=C3=AC 19 gennaio 2009, David Brunell ha scritto:
    > One other question...what about Qt4? =C2=A0I think I need rbuic4 if I am
    > going to pre-compile the ui. =C2=A0Is there a qui4 for dynamic loading?


    The following should work using a recent svn revision from kdebindings.=20
    However, it doesn't because findChild fails. I think it's a bug and I'll tr=
    y=20
    to contact the developers to=20

    require 'Qt4'
    require 'qtuitools'

    class Dlg < Qt::Dialog
    =20
    slots 'test()'
    =20
    def initialize parent =3D nil
    super
    file =3D Qt::File.new File.expand_path('~/temp/test_ui.ui')
    file.open(Qt::File::ReadOnly)
    loader =3D Qt::UiLoader.new
    @widget =3D loader.load file, self
    file.close
    self.layout =3D Qt::VBoxLayout.new self
    layout.add_widget @widget
    @close_btn =3D @widget.findChild(Qt::pushButton, 'close_btn')
    @test_btn =3D @widget.findChild(Qt::pushButton, 'test_btn')
    connect @close_btn, SIGNAL('clicked()'), Qt::Application.instance,=20
    SLOT('close()')
    connect @test_btn, SIGNAL('clicked()'), self, SLOT('test()')
    end
    =20
    def test
    puts "testing"
    end
    =20
    end

    app =3D Qt::Application.new ARGV
    dlg =3D Dlg.new
    dlg.exec
    app.exec

    Stefano
     
    Stefano Crocco, Jan 21, 2009
    #7
  8. Alle mercoled=C3=AC 21 gennaio 2009, Stefano Crocco ha scritto:
    > Alle luned=C3=AC 19 gennaio 2009, David Brunell ha scritto:
    > > One other question...what about Qt4? =C2=A0I think I need rbuic4 if I am
    > > going to pre-compile the ui. =C2=A0Is there a qui4 for dynamic loading?

    >
    > The following should work using a recent svn revision from kdebindings.
    > However, it doesn't because findChild fails. I think it's a bug and I'll
    > try to contact the developers to
    >
    > require 'Qt4'
    > require 'qtuitools'
    >
    > class Dlg < Qt::Dialog
    >
    > slots 'test()'
    >
    > def initialize parent =3D nil
    > super
    > file =3D Qt::File.new File.expand_path('~/temp/test_ui.ui')
    > file.open(Qt::File::ReadOnly)
    > loader =3D Qt::UiLoader.new
    > @widget =3D loader.load file, self
    > file.close
    > self.layout =3D Qt::VBoxLayout.new self
    > layout.add_widget @widget
    > @close_btn =3D @widget.findChild(Qt::pushButton, 'close_btn')
    > @test_btn =3D @widget.findChild(Qt::pushButton, 'test_btn')
    > connect @close_btn, SIGNAL('clicked()'), Qt::Application.instance,
    > SLOT('close()')
    > connect @test_btn, SIGNAL('clicked()'), self, SLOT('test()')
    > end
    >
    > def test
    > puts "testing"
    > end
    >
    > end
    >
    > app =3D Qt::Application.new ARGV
    > dlg =3D Dlg.new
    > dlg.exec
    > app.exec
    >
    > Stefano


    My previous code contained an error: the clicked() signal of @close_btn sho=
    uld=20
    be connected to the quit() slot of Qt::Application.instance, not to the=20
    close() signal (which it doesn't exist).

    Also, to work around the bug I spoke about, it's enough to replace=20
    Qt::pushButton with Qt::Object in the two calls to findChild.

    Stefano
     
    Stefano Crocco, Jan 21, 2009
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christopher Grinde

    pyuic for qtdesigner 3.3

    Christopher Grinde, Apr 30, 2004, in forum: Python
    Replies:
    2
    Views:
    489
    David Boddie
    Apr 30, 2004
  2. Siraj Kutlusan

    Qtdesigner and python

    Siraj Kutlusan, Dec 27, 2005, in forum: Python
    Replies:
    2
    Views:
    687
  3. Lloyd Sheen

    Using .js files rather than embedded js

    Lloyd Sheen, Dec 10, 2007, in forum: ASP .Net
    Replies:
    6
    Views:
    346
    Mark Rae [MVP]
    Dec 10, 2007
  4. Nigel Wilkinson

    Using qtruby with qtdesigner query

    Nigel Wilkinson, Nov 9, 2006, in forum: Ruby
    Replies:
    2
    Views:
    119
    Nigel Wilkinson
    Nov 9, 2006
  5. Richard
    Replies:
    0
    Views:
    112
    Richard
    Mar 5, 2005
Loading...

Share This Page