0

i need a string from the main window to be displayed on a dialog and im having some issues...

heres my code:

class Ui_MainWindow(QtGui.QMainWindow):
    drive_signal = QtCore.pyqtSignal(str)

    def setupUi(self, MainWindow):
       MainWindow.setObjectName(_fromUtf8("MainWindow"))
       MainWindow.resize(459, 280)
       ..... #non relevant code
       .....

       drives = win32api.GetLogicalDriveStrings()
       drives = drives.split('\000')[:-1][1:]
       self.drive_combo.clear()
       self.drive_combo.addItems(drives)
       self.drive_signal.emit(self.drive_combo.currentText())
       ..... 
       .....

class SubDialog(QtGui.QDialog):
    def setupUi(self, Dialog):
       Dialog.setWindowTitle(Ui_MainWindow.drive_signal.connect())
       Dialog.resize(532, 285)
       ..... 
       .....

but i get this error:

AttributeError: 'PyQt4.QtCore.pyqtSignal' object has no attribute 'connect'

any help?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Hairo
  • 2,062
  • 5
  • 27
  • 33

3 Answers3

2

There are two errors on this line:

Dialog.setWindowTitle(Ui_MainWindow.drive_signal.connect())

Firstly, the two method calls are round the wrong way, and secondly, you are attempting to connect an unbound signal to a slot, which can't work.

For the code to work, it would need to look something like this:

window.drive_signal.connect(dialog.setWindowTitle)

where window is an instance of Ui_MainWindow, and dialog is an instance of SubDialog.

Given the way the rest of the code is written, there may also be potential issues with the way the classes are initialized.

The code below shows one way to get the signal working correctly. Take careful note of the order in which things are done before starting the event loop:

from PyQt4 import QtGui, QtCore

class Ui_MainWindow(QtGui.QMainWindow):
    drive_signal = QtCore.pyqtSignal(str)

    def setupUi(self, MainWindow):
        MainWindow.resize(459, 280)
        MainWindow.setWindowTitle('MainWindow: Foo')
        self.drive_signal.emit('Dialog: Bar')

class SubDialog(QtGui.QDialog):
    def setupUi(self, Dialog):
        Dialog.resize(532, 285)

if __name__ == '__main__':

    import sys

    app = QtGui.QApplication(sys.argv)

    window = Ui_MainWindow()
    dialog = SubDialog()

    window.drive_signal.connect(dialog.setWindowTitle)

    window.setupUi(window)
    dialog.setupUi(dialog)

    window.show()
    dialog.show()

    sys.exit(app.exec_())
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
1

I would make it so that the Ui_MainWindow emits the signal:

self.emit(SIGNAL("something_happened"), self.drive_combo.currentText())

And then connect it the old fashioned way in the other object:

mainWindow.something_happened.connect(self.change_windowTitle)

def change_window_title(self, text):
    dialog.setWindowTitle(text)

This may help: http://www.saltycrane.com/blog/2008/01/pyqt-how-to-pass-arguments-while/

RodericDay
  • 1,266
  • 4
  • 20
  • 35
  • connecting the old way is something like: `mainWindow.connect(self, SIGNAL("something_happened"), self.change_windowTitle)` – Hairo Sep 10 '12 at 19:46
  • I'm emitting the old way and connecting the new way... I guess I'm not quite ready to contribute solutions yet. Good luck! – RodericDay Sep 10 '12 at 19:50
  • This is what i get with that method: `AttributeError: type object 'Ui_MainWindow' has no attribute 'drive_signal'` – Hairo Sep 10 '12 at 19:56
1

Ah, the famous 'has no attribute connect'… In fact, in SubDialog, UI_MainWindow.drive_signal is a pyqtSignal, the generic class. You need to use an instance in order to be able to connect it to a function, and this instanciation has to be done at runtime (as far as I understand it). The way PyQt and PySide know how to do that is to look in the class attributes of your PyQt objects. In other terms, you have to define the signal not only where you want to emit it, but also where you want to catch it.

class SubDialog(QtGui.QDialog):
    drive_signal = QtCore.pyqtSignal(str)

    def setupUi(self, Dialog):
        self.dialog_ui = Dialog
        self.drive_signal.connect(self.on_drive_signal))
        …

    def on_drive_signal(self, str_):
        self.dialog_ui.setWindowTitle(str_)

That should work. Please note that you need to connect your signal with something, as illustrated above…

You might also be interested in this question.

Community
  • 1
  • 1
Pierre GM
  • 19,809
  • 3
  • 56
  • 67
  • i did this (defined `drive_signal` in both classes, connected it with something that prints the string on the signal), but it doesn't do anything, it doesn't print anything... :/ – Hairo Sep 10 '12 at 20:37
  • Mmh... So, debug mode (1): try to connect your signal to a method in `UI_MainWindow` and see whether it's emitted (2) try to make `UI_MainWindow` the parent of `SubDialog`, and see whether you could access the signal from `UI_MainWindow` from `SubDialog` without using the `UI_MainWindow.signal` approach that cannot work. – Pierre GM Sep 10 '12 at 21:16
  • it does emit fine on `UI_MainWindow`, i'm trying to avoid using a global variable... but i think i'll end up using it anyway and check if it doesn't break something... i knew pyqt was a bad idea from the start... next time i'll go with wxWidgets... – Hairo Sep 10 '12 at 22:08
  • PyQt/PySide is a bit finicky but quite performant, don't lose hope. I still think that a `self.parent().drive_signal.connect(self.on_drive_signal)` is worth a shot (once you have set the parent of `SubDialog` to `UI_MainWindow`) – Pierre GM Sep 10 '12 at 22:11