Reply
Thread Tools
helex's Avatar
Posts: 543 | Thanked: 802 times | Joined on Apr 2010 @ Germany
#1
Hello,

I guess this is a totally noob question. But I stuck and don't know how to handle...
I've had to reebot my N900 to often (made a not cancelable modal Dialog by accident) and hope now here for help for my initial problem.

Here a example of my problem:

I created a Main Window and a Menu to call a Test Dialog (want to place some widgets there)

I know I have to close the Dialog after the accept or rejected event. But I don't know how. Dialog.close doesn't work.

DialogTest.py:
Code:
import sys
from PyQt4 import QtGui,QtCore
from Ui_frmDialog import *
from Ui_frmMain import *

class frmDialog(QtGui.QDialog):
  def __init__(self, parent=None):
    QtGui.QWidget.__init__(self, parent)
    self.ui = Ui_Dialog()
    self.ui.setupUi(self)

  def reject(self):
    print "reject"

  def accept(self):
    print "accept"

class frmMain(QtGui.QMainWindow):
  def __init__(self, parent=None):
    QtGui.QWidget.__init__(self, parent)
    self.ui = Ui_MainWindow()
    self.ui.setupUi(self)

    QtCore.QObject.connect(self.ui.actionTest, QtCore.SIGNAL('triggered()'), self.actionTest)

  def actionTest(self):
    print "actionSettings"
    Dialog = frmDialog(self)
    Dialog.show()
    ret = Dialog.exec_()

if __name__ == "__main__":
  app = QtGui.QApplication(sys.argv)
  MainWindow = frmMain()
  MainWindow.show()
  sys.exit(app.exec_())

Ui_frmMain.py:
Code:
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'E:\Handy\PyProgramme\DialogTest\frmMain.ui'
#
# Created: Sat May 01 18:43:51 2010
#      by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(416, 292)
        self.centralWidget = QtGui.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        MainWindow.setCentralWidget(self.centralWidget)
        self.menuBar = QtGui.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 416, 20))
        self.menuBar.setObjectName("menuBar")
        self.menuAbout = QtGui.QMenu(self.menuBar)
        self.menuAbout.setObjectName("menuAbout")
        MainWindow.setMenuBar(self.menuBar)
        self.actionTest = QtGui.QAction(MainWindow)
        self.actionTest.setObjectName("actionTest")
        self.menuAbout.addAction(self.actionTest)
        self.menuBar.addAction(self.menuAbout.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
        self.menuAbout.setTitle(QtGui.QApplication.translate("MainWindow", "Test", None, QtGui.QApplication.UnicodeUTF8))
        self.actionTest.setText(QtGui.QApplication.translate("MainWindow", "Test", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Ui_frmDialog.py:
Code:
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'E:\Handy\PyProgramme\DialogTest\frmDialog.ui'
#
# Created: Sat May 01 18:43:51 2010
#      by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(400, 300)
        self.layoutWidget = QtGui.QWidget(Dialog)
        self.layoutWidget.setGeometry(QtCore.QRect(20, 250, 351, 33))
        self.layoutWidget.setObjectName("layoutWidget")
        self.hboxlayout = QtGui.QHBoxLayout(self.layoutWidget)
        self.hboxlayout.setMargin(0)
        self.hboxlayout.setSpacing(6)
        self.hboxlayout.setObjectName("hboxlayout")
        spacerItem = QtGui.QSpacerItem(71, 31, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.hboxlayout.addItem(spacerItem)
        self.okButton = QtGui.QPushButton(self.layoutWidget)
        self.okButton.setObjectName("okButton")
        self.hboxlayout.addWidget(self.okButton)
        self.cancelButton = QtGui.QPushButton(self.layoutWidget)
        self.cancelButton.setObjectName("cancelButton")
        self.hboxlayout.addWidget(self.cancelButton)
        spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.hboxlayout.addItem(spacerItem1)

        self.retranslateUi(Dialog)
        QtCore.QObject.connect(self.okButton, QtCore.SIGNAL("clicked()"), Dialog.accept)
        QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL("clicked()"), Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
        self.okButton.setText(QtGui.QApplication.translate("Dialog", "&OK", None, QtGui.QApplication.UnicodeUTF8))
        self.cancelButton.setText(QtGui.QApplication.translate("Dialog", "&Cancel", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Dialog = QtGui.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())
I'm a python an Qt beginner.
Before I post here some examples of my stupid fault trys... Could someone please help me and post the solution?
 
mikec's Avatar
Posts: 1,366 | Thanked: 1,185 times | Joined on Jan 2006
#2
Do something like this in your dialog

Code:
def on_backButton_clicked(self):
        #emit custom signal and pass some parameters back in self.config
     
        self.writeConfig()
        self.emit(SIGNAL("dialog closed"), self.config)
        self.close()
__________________
N900_Email_Options Wiki Page

Last edited by mikec; 2010-05-01 at 18:18.
 
Posts: 70 | Thanked: 39 times | Joined on Mar 2010
#3
You might want to call QDialog.accept() after your print statement when overriding the accept method. Same for reject().
 
helex's Avatar
Posts: 543 | Thanked: 802 times | Joined on Apr 2010 @ Germany
#4
Thanks for your fast answer. :-)

Originally Posted by mikec View Post
Do something like this in your dialog

Code:
def on_backButton_clicked(self):
        #emit custom signal and pass some parameters back in self.config
     
        self.writeConfig()
        self.emit(SIGNAL("dialog closed"), self.config)
        self.close()
I guess I'm missing the point. :-(

The self.close() is the argument to close the Dialog, is that correct?

But with this minimalistic code in DialogTest.py it doesn't work:

Code:
class frmDialog(QtGui.QDialog):
  def __init__(self, parent=None):
    QtGui.QWidget.__init__(self, parent)
    self.ui = Ui_Dialog()
    self.ui.setupUi(self)

  def reject(self):
    print "reject"
    self.close()
    
  def accept(self):
    print "accept"
    self.close()
I get only "reject" or "accept" on the command line. But the Window is still open.
 
mikec's Avatar
Posts: 1,366 | Thanked: 1,185 times | Joined on Jan 2006
#5
You should not have to re-implement those events just for a close.

here some code that works, generated from qt designer.
it opens a main window, with a big button that shows the dialog.
dialog has two buttons that accept and reject then closes the dialog.

main.py
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4 import QtCore
from PyQt4.QtGui import QApplication
from winstub import MainWindow

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    ui = MainWindow()
    ui.show()
    sys.exit(app.exec_())
Ui_win.py
Code:
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '/home/mikec/python/Memo UI examples/Dialog/win.ui'
#
# Created: Sun May  2 18:50:13 2010
#      by: PyQt4 UI code generator 4.6.1
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralWidget = QtGui.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        self.showButton = QtGui.QPushButton(self.centralWidget)
        self.showButton.setGeometry(QtCore.QRect(280, 250, 201, 71))
        self.showButton.setObjectName("showButton")
        MainWindow.setCentralWidget(self.centralWidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
        self.showButton.setText(QtGui.QApplication.translate("MainWindow", "Show Doalog", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
Ui_dialog.py
Code:
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '/home/mikec/python/Memo UI examples/Dialog/dialog.ui'
#
# Created: Sun May  2 18:50:13 2010
#      by: PyQt4 UI code generator 4.6.1
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

class Ui_myDialog(object):
    def setupUi(self, myDialog):
        myDialog.setObjectName("myDialog")
        myDialog.resize(400, 300)
        self.acceptButton = QtGui.QPushButton(myDialog)
        self.acceptButton.setGeometry(QtCore.QRect(300, 150, 84, 51))
        self.acceptButton.setObjectName("acceptButton")
        self.rejectButton = QtGui.QPushButton(myDialog)
        self.rejectButton.setGeometry(QtCore.QRect(300, 220, 84, 51))
        self.rejectButton.setObjectName("rejectButton")

        self.retranslateUi(myDialog)
        QtCore.QMetaObject.connectSlotsByName(myDialog)

    def retranslateUi(self, myDialog):
        myDialog.setWindowTitle(QtGui.QApplication.translate("myDialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
        self.acceptButton.setText(QtGui.QApplication.translate("myDialog", "Accept", None, QtGui.QApplication.UnicodeUTF8))
        self.rejectButton.setText(QtGui.QApplication.translate("myDialog", "Reject", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    myDialog = QtGui.QDialog()
    ui = Ui_myDialog()
    ui.setupUi(myDialog)
    myDialog.show()
    sys.exit(app.exec_())
winstub.py (this bit does what you want)
Code:
# -*- coding: utf-8 -*-

"""
Module implementing MainWindow and Dialog
"""

from PyQt4.QtGui import QMainWindow, QDialog
from PyQt4.QtCore import pyqtSignature

from Ui_win import Ui_MainWindow
from Ui_dialog import Ui_myDialog

class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, parent = None):
        QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.popDialog=myDialog()
    
    def on_showButton_clicked(self):
        self.popDialog.show()
        
class myDialog(QDialog, Ui_myDialog):
    def __init__(self, parent = None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        
    def on_acceptButton_clicked(self):
        self.close()
        
    def on_rejectButton_clicked(self):
        self.close()
__________________
N900_Email_Options Wiki Page
 

The Following 2 Users Say Thank You to mikec For This Useful Post:
helex's Avatar
Posts: 543 | Thanked: 802 times | Joined on Apr 2010 @ Germany
#6
Originally Posted by mikec View Post
You should not have to re-implement those events just for a close.

here some code that works, generated from qt designer.
it opens a main window, with a big button that shows the dialog.
dialog has two buttons that accept and reject then closes the dialog.
Oh jeah, thanks a lot!

Your example worked just simple and easy. On my N900 and on my PC. I compared it with my code step by step and now I spent over 1 hour trying and fiddle out because of what part of the code my example and also my main project was not working.

And now it was the LAST thing I had suspected.

I used this in my Main program:

Code:
def reject(self):
    self.close()
and the code was called because of this, created by QtDesigner:

Code:
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL("clicked()"), Dialog.reject)
I don't understand why it won't close after calling the sub function. The function itself was called correctly.

But now using your function from your code and from your fist example it works perfect:
Code:
def on_backButton_clicked(self):
Actually for me still a total mystery. But okay, I'm learning qt and python since 2 Weeks in my rare spare time. So I've many to learn...

And I have to apologise myself... I'm not a big contributor at maemo talk. I'm a interested reader since November. But I hope while learning Python, Qt and how to deploy the one or other nice application to Maemo Extras I can help the comunity more than simply speculating about the next firmware relase.
 
Posts: 118 | Thanked: 26 times | Joined on Jun 2008
#7
Just connect the accepted() signal to a function in your class that does whatever work you need to do. It's pretty simple, as the dialog automatically closes. If you want to do some stuff in the event that the dialog is rejected, just connect the rejected() signal to a different function. Here's an example that subclasses the Qt Designer created classes:

Code:
class settingsDialog(QDialog, Ui_settingsDialog):
    def __init__(self, parent, gconfClient):
        self.parent = parent
        QDialog.__init__(self, parent)
        self.gconfClient = gconfClient
        self.setupUi(self)
        
        self.googlePasswordLineEdit.setEchoMode(QLineEdit.Password)
        googlename = self.gconfClient.get_string('/apps/event2gcal/googlename')
        if googlename != None:
            self.googleUsernameLineEdit.setText(googlename)
        googlepass = self.gconfClient.get_string('/apps/event2gcal/googlepass')
        if googlepass != None:
            self.googlePasswordLineEdit.setText(googlepass)
        dbuslisten = self.gconfClient.get_bool('/apps/event2gcal/dbuslisten')
        if dbuslisten != None:
            self.dBusListenerCheckBox.setChecked(self.gconfClient.get_bool('/apps/event2gcal/dbuslisten'))
        
        if googlename != None and googlepass != None:
            calDict = self.parent.googleCalendar.getCalendars()    
            self.populateCalendar(calDict)
            
        self.connect(self.buttonBox, SIGNAL("accepted()"), self.saveSettings)
        
        self.exec_()
        
    def saveSettings(self):
        # Read values of widgets and save in GConf
        # We should probably sanity check the values at some point..
        self.gconfClient.set_string('/apps/event2gcal/googlename', str(self.googleUsernameLineEdit.text()))
        self.gconfClient.set_string('/apps/event2gcal/googlepass', str(self.googlePasswordLineEdit.text()))
        self.gconfClient.set_string('/apps/event2gcal/googlecal', 
                                    str(self.calendarComboBox.itemData(self.calendarComboBox.currentIndex()).toString()))
        self.parent.googleEditUri = str(self.calendarComboBox.itemData(self.calendarComboBox.currentIndex()).toString())
        print "Saving edit uri: " + str(self.calendarComboBox.itemData(self.calendarComboBox.currentIndex()).toString()) + "\n"
        self.gconfClient.set_bool('/apps/event2gcal/dbuslisten', self.dBusListenerCheckBox.isChecked())

    def populateCalendar(self, calDict):
        for calName in calDict:
            self.calendarComboBox.addItem(calName, calDict[calName])
Ironically, too much thinking has been what gets me in trouble with Qt.
 

The Following User Says Thank You to wierdo For This Useful Post:
mikec's Avatar
Posts: 1,366 | Thanked: 1,185 times | Joined on Jan 2006
#8
signals and slots is great, but Qtdesigner does much for you, as does IDE like eric. Try and stay with Designer as your interfaces get more complex, as it allows you to tweak layout much easier

anyway you get much pleasure for pyqt as you learn more.
__________________
N900_Email_Options Wiki Page
 

The Following User Says Thank You to mikec For This Useful Post:
helex's Avatar
Posts: 543 | Thanked: 802 times | Joined on Apr 2010 @ Germany
#9
Originally Posted by wierdo View Post
Just connect the accepted() signal to a function in your class that does whatever work you need to do. It's pretty simple, as the dialog automatically closes. If you want to do some stuff in the event that the dialog is rejected, just connect the rejected() signal to a different function. Here's an example that subclasses the Qt Designer created classes:

[...]

Ironically, too much thinking has been what gets me in trouble with Qt.
Okay. Strange... my next fault was to call my functions reject and accept.
So to connect the accepted() signal to my function have also not worked. Simply renamed "accept" to "storesetting" and now it works.

I guess I overrided with "reject" and "accept" other functions. Hmm...
How can I see if I override a existing function?


Originally Posted by mikec View Post
signals and slots is great, but Qtdesigner does much for you, as does IDE like eric. Try and stay with Designer as your interfaces get more complex, as it allows you to tweak layout much easier

anyway you get much pleasure for pyqt as you learn more.
Can I see somewhere in the QtDesinger the name of the implemented Qt functions?

I'm acctually trying with Eric and QtDesigner... but as a Windows .NET Framework developer I'm very cosseted.
I miss the auto completion the most. I mean real auto completion, with the full knowledge of the full framework, all api's and the full namespace. Easy to search and click. Simple to know if you override a function, you want to see what events are provided or to find the exact name of a rarely used function.
 
mikec's Avatar
Posts: 1,366 | Thanked: 1,185 times | Joined on Jan 2006
#10
In Eric click on generate dialog code, and it will show you all of the functions to connect to. Just click on the actions you want to react to and it will generate the stub code for you. You can then cut and paste it as you need.
__________________
N900_Email_Options Wiki Page
 

The Following User Says Thank You to mikec For This Useful Post:
Reply


 
Forum Jump


All times are GMT. The time now is 02:04.