Max Frai
Max Frai

Reputation: 64286

Activate window

i have a QMainWindow. It has this parameters:

this->setWindowFlags(Qt::Tool);
this->setFocusPolicy(Qt::StrongFocus);
this->setAttribute(Qt::WA_QuitOnClose,true);

After showEvent calles my window is shown but unactivated. I tried to overload show function:

...    
QMainWindow::showEvent(event);
this->activateWindow();
...

But it doesn't help me.

EDIT: When i commented line

this->setWindowFlags(Qt::Tool);

everything worked fine, but i need in tool-flag. Any ideas?

EDIT:

Upvotes: 14

Views: 17249

Answers (7)

stephan
stephan

Reputation: 10265

The Windows Manager Decides

Before I start: As pointed out by elcuco and Javier, focus policy and other aspects of the windows layout (e.g. the title bar) belongs to a substantial extend to the respective windows manager, and Qt might have limited control. To see this, just look at a user interface that has a "focus follows mouse" policy. In these cases, the windows manager might ignore Qt's focus request. For this reasons, the Qt documentation calls many of the respective flags "hints". Consequently, some of the suggested solutions might or might not work for you.

QApplication::setActiveWindow()

This not withstanding, e.tadeu's solution to use QApplication::setActiveWindow() works for me for both Windows and Ubuntu with Gnome. I tested it with the following code. Apologies that it is Python using PyQt (I use questions like these to learn a bit about PyQt). It should be fairly easy for you to read it and translate it into C++.

import sys

from PyQt4 import QtGui
from PyQt4 import QtCore

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self)

        # main window
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Test')

        # text editor
        self.textEdit = QtGui.QTextEdit()
        self.setCentralWidget(self.textEdit)

    def closeEvent(self, event):
        QtGui.QApplication.instance().quit()

#main
app = QtGui.QApplication(sys.argv)
testWindow = MainWindow()
testWindow.setWindowFlags(QtCore.Qt.Tool)
testWindow.show()
app.setActiveWindow(testWindow)
app.exec_()

Note that you have to add some handling of the close event of the testWindow, because the app does not exit automatically if you close a Qt::Tool window.

The grabKeyboard() Hack

If this does not work for you, the following hack might. I assume that you have a window in your application that is active. You can then use grabKeyboard() to redirect the input. The Qt::Tool window doesn't get the focus, but receives the input. The following main code demonstrates it (the other code remains unchanged).

#main
app = QtGui.QApplication(sys.argv)
testWindow = MainWindow()
testWindow.setWindowFlags(QtCore.Qt.Tool)
testWindow2 = MainWindow()   # second window which is active
testWindow2.show()
testWindow.show()
testWindow.textEdit.grabKeyboard()
app.exec_()

Basically, while the window testWindow2 is the active one, all text entered shows up in testWindow.textEdit. It is not nice, I know...

Creating Your Own Window

You gain the most flexibility (and create the most work for yourself) by rolling out your own window layout. The idea is described in the following FAQ.

Other "Solutions"

You could directly call the respective window manager's API function to get the desired result (clearly against the very reason for using Qt in the first place). You could also hack the Qt source code. For example, on Windows, Qt uses the ShowWindow() function with a SW_SHOWNOACTIVATE flag, to show a window with style WS_EX_TOOLWINDOW if you set the Qt::Tool flag. You could easily replace the SW_SHOWNOACTIVATE with whatever you want. Linux should be the same. Clearly also not recommended.

Upvotes: 14

user314394
user314394

Reputation:

Just call show() after setWindowFlags().

Upvotes: 0

rocknroll
rocknroll

Reputation: 1120

Regarding Qt::Tool WindowFlags To quote Qt documentation

Indicates that the widget is a tool window. A tool window is often a small window with a smaller than usual title bar and decoration, typically used for collections of tool buttons. It there is a parent, the tool window will always be kept on top of it. If there isn't a parent, you may consider using Qt::WindowStaysOnTopHint as well. If the window system supports it, a tool window can be decorated with a somewhat lighter frame. It can also be combined with Qt::FramelessWindowHint

It seems the flags is a problem and using Qt::WindowStaysOnTopHint should solve your problem.

Upvotes: 0

Javier
Javier

Reputation: 62603

The original apple Human Interface Guidelines(*) said that toolbox windows were "always on top but never activated". It also advises against using text boxes on them, precisely because the lack of activation-state feedback.

Check how other 'toolbox heavy' apps behave. I faintly recall that at least GIMP and InkScape seem very different in this aspect.

As elcuco said, the window manager can do whatever it wants with Qt's flags. Also, it sure would be different under KDE, Gnome, fluxbox, whatever.

(*):great document! somewhat outdated; but tool windows were already used and considered

Upvotes: 4

e.tadeu
e.tadeu

Reputation: 5328

Try to use QApplication::setActiveWindow()

Upvotes: 4

Troubadour
Troubadour

Reputation: 13421

Does the same thing happen if you just make it a regular QWidget instead of a QMainWindow?

Also, perhaps you might be better trying to achieve whatever effect you need Qt::Tool for by other means if that's possible?

Upvotes: 0

elcuco
elcuco

Reputation: 9208

Which operating system? Which Qt4?

On Linux you are doomed, the window manager can ignore what you are telling him. Keep it under consideration.

Upvotes: 1

Related Questions