PDA

View Full Version : Can't override the closeEvent()



scot_hansen
5th October 2010, 14:52
I have been trying to override the Windows 'X' button close to save some data with no luck. I am using PyQT 4.7.4 and Python 2.7 on Windows XP. I used Qt Designer to create the following class for the main window. This is part of the class code:

class Ui_MainWin(object):
def setupUi(self, MainWin):

MainWin.setObjectName("MainWin")
MainWin.resize(511, 362)

In another Python module, I setup the window with the following code:

app = QtGui.QApplication(sys.argv)
MainWin = QtGui.QMainWindow()
ui = Ui_MainWin()
ui.setupUi(MainWin)

I've searched on-line on how to override the Window's 'X' button and seen in several examples where people use the closeEvent in their window class that sets up the window:

def closeEvent(self,event):
print "in routine"

When I use this code inside my class, it doesn't capture the window closing. I then thought I needed to try to connect the close event to the function (signal to slot) and use this connect statement:

self.centralwidget.connect(self.menubar.closeEvent (),QtCore.SIGNAL('triggered()'), self.closeEvent())

I get the error:

closeEvent(QCloseEvent), not enough arguments

I have the following questions:

1. I am defining the function incorrectly to capture the closeEvent()?

2. Do I need a connect statement?

I have been using PyQt for only 6 weeks.

wysota
5th October 2010, 14:59
Where are you defining the closeEvent() method?

scot_hansen
5th October 2010, 15:24
Thank you for the quick reply. I define the closeEvent as a member function in my window class called Ui_MainWin.

wysota
5th October 2010, 15:30
closeEvent() is a method of QWidget so it must be defined in a subclass of QWidget.

scot_hansen
5th October 2010, 19:50
Thank you for the suggestion. I wrote code for a new class to override the closeEvent() function. I used it as a nested class inside my window class Ui_MainWin:

class setExit(QtGui.QWidget):
def closeEvent(self,event):
print "in routine"

In my Ui_MainWin class, I create an object for this class:

self.exitEvent = self.setExit()

This still didn't work so I have the following questions:

1. Do I nest my setClass within the Ui_MainWin class or create it as a seperate class?

2. Is it correct to inherit from the QWidget class? If not, what class do I inherit from?

3. Does the setExit class need a constructor? If so, what do I set?

4. The code I use to setup the window is in another module and is generated from Qt designer:

app = QtGui.QApplication(sys.argv)
MainWin = QtGui.QMainWindow()
ui = Ui_MainWin()
ui.setupUi(MainWin)

My problem is that the on-line examples I've seen use QWidget instead of QMainWindow to setup the class. I do realize now from your comment that the QMainWindow() doesn't have a closeEvent().

Also in the window class, setupUi() function, the following code is used to create the cental widget on the window:

self.centralwidget = QtGui.QWidget(MainWin)

I realize that the questions I'm asking are probably stupid. Thank you for the help.

wysota
5th October 2010, 20:21
You still don't understand. You can't expect some arbitrary instance of an arbitrary subclass of QWidget to receive any possible closeEvent. If you click the X button on window "A" it is the object representing the window "A" that will receive the event and not any other. You have to subclass QMainWindow and deploy your Ui_MainWin class on an instance of this subclass. And the event needs to be reimplemented in the exact same class/object.

In C++ it would look like this (my Python is rusty so I won't even try writing Python code now):

class MainWindow : public QMainWindow {
public:
MainWindow(QWidget *parent = 0) : QMainWindow(parent) {
ui = new Ui::MainWin;
ui->setupUi(this);
}
~MainWindow(){ delete ui; }
protected:
void closeEvent(QCloseEvent *event) { event->ignore(); } // always prevent the window from being closed
Ui::MainWin *ui;
};
// ...
MainWindow window;
window.show();

scot_hansen
5th October 2010, 20:57
Thank you for your help

PatchPaper
5th October 2010, 22:47
if you are just trying to capture the close event from a user clicking the 'x' button then


def closeEvent(self, event):
print ("inside the close")

is going to work, it'll run through whatever you've got there, but the window is still going to close on you. You are just intercepting it before it actually closes.

if you need to ask if they really want to close, then you need to interrupt that event being passed in.

so more like:


def closeEvent(self, event):
if checkstatement is True: #(don't really want to close the window
event.ignore()
else:
print ("really closing for real this time!")


as for connecting your actions to the close event, I typically just connect it the action to self.close as it will also call the closeEvent()

Hope that helps.