PDA

View Full Version : QMainWindow height wrong when menu is global



Exeunt Omnes
13th June 2012, 01:06
I have a QtGui application with a straightforward menu bar. It works fine on Windows (XP/Vista/W7) and on Ubuntu 11.04.

On Ubuntu 12.04 (Unity) the menu bar is automatically moved by the window manager (presumably) to the global menu, where it works correctly, but the window isn't resized to allow for the missing menu bar. Instead, the centralWidget is moved up, leaving a gap at the bottom.

I've been unable to find any way to fix this. I don't seem to be able to find a way to adjust the height of the window programmatically. I've tried QMainWindow::setGeometry(...) and QMainWindow::adjustSize() (at the end of the mainWindow constructor) by way of experiment, but neither seems to make any difference.

Am I missing something obvious?

ChrisW67
13th June 2012, 02:49
I am not sure how Unity does that and whether it's reasonable to expect the QMainWindow to notice and adapt. First, be sure the gap at the bottom is not an empty status bar.

It's possible the window manager probably isn't hijacking the menu bar until the window is shown. Try creating a slot that resizes the window, and arrange to trigger it with a zero-length single shot timer in the constructor.


// end of constructor
QTimer::singleShot(0, this, SLOT(fiddleSize()));
}

void fiddleSize() {
// compute the desired size.
resize(...);
}

Exeunt Omnes
13th June 2012, 12:26
Thanks for that suggestion.

No, it's not an empty status bar. I actually have two main windows (not open at the same time), one with and one without a status bar, and they both have the same problem. In the case of the one without a status bar there's just a gap at the bottom, and in the other case there's a gap between the centralWidget and the status bar.

I tried your suggestion and I'm afraid it didn't work. I even added a 1000 msec delay and it still didn't work.

On the face of it this might suggest that QMainWindow has no knowledge of the fact that the menu bar is missing, but then the gap would be at the top, not the bottom.

Oh well, it's not the end of the world. The product's currently aimed at a Windows market. I develop it in Linux (and then rebuild under Windows) because it makes for much easier communication with the server, but I've no immediate plans for a Linux version so I'll come back to this issue later. Perhaps by then Qt will have adapted QMainWindow to cope with this situation.

Many thanks for your help anyway!

PS One other thing has just occurred to me as possibly relevant. The resize() (or setGeometry(), or whatever) has no effect at all. The initial size of the QMainWindow is set in Qt Creator, after which it seems to be impossible to change it programmatically. This is why I thought I must be missing something. Any thoughts on this?

Exeunt Omnes
13th June 2012, 22:52
I decided in the end simply to over-ride the Unity menu bar handling by adding
CoreApplication::setAttribute(Qt::AA_DontUseNative MenuBar, true);to main() before the QMainWindow is created. It's non-standard for Unity, but it works and it looks right.

ChrisW67
14th June 2012, 01:42
PS One other thing has just occurred to me as possibly relevant. The resize() (or setGeometry(), or whatever) has no effect at all. The initial size of the QMainWindow is set in Qt Creator, after which it seems to be impossible to change it programmatically. This is why I thought I must be missing something. Any thoughts on this?

That sheds a different light: if you are actually unable to resize the window at all then removing the menu bar will move the content up but the lower bound of the window cannot follow. Since a QMainWindow is fully resizable by default then there is something you are doing to constrain your main window itself, or to its central widget or layout.

Does this stand-alone example behave properly when Unity steals the menu bar?


#include <QtGui>

class MainWindow: public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *p = 0): QMainWindow(p) {
QAction *exitAct = new QAction(tr("&Exit"), this);
connect(exitAct, SIGNAL(triggered()), qApp, SLOT(quit()));
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(exitAct);

QFrame *frame = new QFrame(this);
frame->setFrameStyle(QFrame::Box);
setCentralWidget(frame);
}
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow m;
m.show();
return app.exec();
}
#include "main.moc"

Exeunt Omnes
14th June 2012, 13:26
Well, that worked!

I'll see if I can fathom out what is preventing the resizing. If not, I'll be back, but in any case many thanks for your help!

Exeunt Omnes
15th June 2012, 18:20
It looks as though the problem is connected with my using Qt Designer for the QMainWindow. I've adapted the example to use a custom QFrame created using Qt Designer, and that works, but as long as there's a setupUi() call in the mainWindow constructor the QMainWindow size seems to be fixed by the UI and programmatically unchangeable.

If I'm right about this the solution seems to be to decouple the UI for the centralWidget from the mainWindow setup by moving it to a QFrame created in Qt Designer (so I can keep the existing xml code and use Qt Designer for maintenance and updates), but set the menu, centralWidget (and status bar if any) programmatically in the mainWindow constructor. This is a bit of a pain, but it could be a lot worse!