I have a qt application, window with several child widgets that are Qt::Tool windows.
When I minimize window and then restore on windows 7 child widgets appear immediately, but parent window not because of animation.
Is there any way to prevent this behavior and make child windows appear after main window?
Why don't you hide the tool windows while the main window is restoring? You can use this piece of code and adapt it to your needs:
void MainWindow::changeEvent( QEvent* e )
{
if ( e->type() == QEvent::WindowStateChange )
{
QWindowStateChangeEvent* event =
static_cast< QWindowStateChangeEvent* >( e );
if ( event->oldState() & Qt::WindowMinimized ) {
qDebug() << "The Window has been restored!";
}
else if ( (event->oldState() == Qt::WindowNoState) &&
(this->windowState() == Qt::WindowMaximized) ) {
qDebug() << "the window has been Maximized!";
}
}
}
For example, you can start a timer for a certain amount of time, and have the slot connected to your child tool windows, making them appear as you wish.
You can also play with transparency in the child tool windows, and emulate the main window effects.
As I recall, something like this will do:
setStyleSheet("background:transparent;");
setAttribute(Qt::WA_TranslucentBackground);
setWindowFlags(Qt::FramelessWindowHint);
Hope that helped!
Related
I'm trying to implement a feature that changes the color of a child window when the user hovers over it. To do this, I need to receive EnterNotify events for specific child windows. I'm getting the EnterNotify events with no problem, but I can't figure out how to distinguish between which child window the EnterNotify event is coming from. How do I get the event window from an event?
if (event.type == EnterNotify && event.xcrossing.window == w11) {
std::cout << "ENTER WINDOW" << std::endl;
}
This is what I have tried with w11 being the child window. Nothing is sent to output when the EnterNotify events come in, but if I change the event.xcrossing.window equivalency to win (the parent window), as shown below, it will produce output as the EnterNotify events roll in. Thanks.
if (event.type == EnterNotify && event.xcrossing.window == win) {
std::cout << "ENTER WINDOW" << std::endl;
}
It turns out that when you create a child window using XCreateSimpleWindow, the parent window's mask input is not carried over to the child window. All I had to do was update each child window to receive EnterWindowMask events.
I'm trying to open a gtk file dialog window with a GLFW window.
Now since GLFW is a pretty low level API it only exposes the X11 window and display, because it just creates a window without any GUI stuff.
The problem I'm having is that gtk_file_chooser_dialog_new() expects a parent window to be passed on, but since I only have an X11 handle I'm not quite sure how to create a GTK handle from it.
I followed this tutorial which resulted in the following code:
glfwSetKeyCallback(windowHandle1, [](GLFWwindow *window, int keyCode, int scanCode, int action, int mods) {
if (action == GLFW_PRESS)
{
if (keyCode == GLFW_KEY_O && mods == (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL))
{
GtkWidget *dialog;
GtkFileChooserAction fileAction = GTK_FILE_CHOOSER_ACTION_OPEN;
gint res;
// Window x11Window = glfwGetX11Window(window);
// Display *x11Display = glfwGetX11Display();
int argc = 0;
gtk_init(&argc, nullptr); // TODO: don't do this every time
dialog = gtk_file_chooser_dialog_new("Open File",
nullptr, // should be _GtkWindow of the GLFWwindow
fileAction,
_("_Cancel"),
GTK_RESPONSE_CANCEL,
_("_Open"),
GTK_RESPONSE_ACCEPT,
nullptr);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT)
{
char *filename;
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
filename = gtk_file_chooser_get_filename(chooser);
std::cout << filename << std::endl;
g_free(filename);
}
gtk_widget_destroy(dialog);
std::cout << "destroyed file dialog" << std::endl;
}
}
});
This opens an open file dialog, but because I didn't specify a parent window the main window can still be focused, and another problem is that the dialog doesn't close for some reason even though I call gtk_widget_destroy(dialog).
I already took a look at this post, but the only answer seems to be getting the xid of the file dialog window, which is not what I want to do.
This google search result doesn't seem to help either, as it creates a completely new gdk (not gtk) window on the default display.
I've got the same problem and found hackish way to fix this. Null parent is not really problem here, but lack of event dispatching, so I've added:
gtk_widget_destroy(dialog);
while (g_main_context_iteration(nullptr, false));
How do I track move event for all the windows?
Like if user moves window "Pluma" my daemon would receive window name and new coordinates.
if(XCheckMaskEvent(display, -1, &event))
{
if(event.type == ConfigureNotify)
{
moved += event.xmotion.x + event.xmotion.y;
//qDebug << moved;
}
}
I tried tracking it like this, but it does not work...
You need t select SubstructureNotify mask on the root window first:
XSelectInput(display, XDefaultRootWindow(display), SubstructureNotifyMask );
This way you are telling X server "I'm interested in root window childrens move/resize/delete/create events"
I have a QGraphicsView and a QGraphicsScene and I enabled
this->setDragMode(QGraphicsView::RubberBandDrag);
for a Rubberband selection. However, in my application it would make sense that you need to press the CTRL key and then move the mouse to start the rubberband selection. Can I accomplish this without making my own QRubberBand? If not, how can I reimplement it?
If you have say a QMainWindow that contains your QGraphicsView and Scene, one way to do this would be to overload the keyPressEvent and keyReleaseEvent methods of QMainWindow like this:
void MyMainWindow::keyPressEvent( QKeyEvent * event )
{
if( event->key() == Qt::Key_Control ) {
graphicsView->setDragMode(QGraphicsView::RubberBandDrag);
}
QMainWindow::keyPressEvent(event);
}
void MyMainWindow::keyReleaseEvent( QKeyEvent * event )
{
if( event->key() == Qt::Key_Control ) {
graphicsView->setDragMode(QGraphicsView::NoDrag);
}
QMainWindow::keyReleaseEvent(event);
}
This will set the selection mode to RubberBandDrag as long as CTRL is being pressed. When the key is released again, the drag mode is set back to the default NoDrag and no selection is performed.
In both cases the event is also forwarded to the QMainWindow base class implementation which may or may not be of relevance for you.
Erik's answer didn't work well for me. If I release the key while still dragging, the rubber band is not cleared and remains visible on the screen until the next selection.
Because QT only clears the rubber band on mouse release, my workaround was to force an artificial mouse release event while still in Rubberband mode to have it properly cleared:
void MyQGraphisView::keyReleaseEvent( QKeyEvent * event )
{
if( event->key() == Qt::Key_Control ) {
if(QApplication::mouseButtons() & Qt::LeftButton)
mouseReleaseEvent(new QMouseEvent(QApplicationStateChangeEvent::MouseButtonRelease, mousePosOnScene, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
setDragMode(QGraphicsView::NoDrag);
}
QMainWindow::keyReleaseEvent(event);
}
Update: Qt fixed this bug (https://bugreports.qt.io/browse/QTBUG-65186) and will be deployed in 5.15
I open QDialog window from QMainWindow. Now when I press the QDialog window
its not always closing in the first press - I need to press few times (3-4) to close it .
I have closeEvent slot that has simple event->accept(); inside it.
This is how I call the QDialog from the main window:
void MyManager::DialogContainerOpen(type t)
{
if(pMyDialogContainer == NULL)
{
pMyDialogContainer = new MyDialogContainer();
}
int returnVal = QDialog::Rejected;
if(!m_bContainer)
{
m_bContainer = true;
int returnVal = pMyDialogContainer->exec();
if(returnVal != QDialog::Accepted ) {
m_bContainer = false;
}
}
}
This is the first problem.
The second problem is how do i set the QDialog windows NOT to be allays on top? (I don’t want it to block the parent window.
UPDATE
well i found out that the function from the MainWindow that showing the contexMenu
and inside it has the connect single/slot is keeps to invoke so i just used the disconnect
i dont know if its the best sulotion but its working.
now i juat have the final problem .
here is the code i hope its ok
void MainWindowContainer::ShowContextMenu(const QPoint& pos) // this is a slot
{
QModelIndex modelIndx;
QPoint globalPos = ui.treeView_mainwindow->mapToGlobal(pos);
bool b1 = connect(OpenAction, SIGNAL(triggered()),m_SignalMapper, SLOT(map()) );
m_SignalMapper->setMapping(OpenAction,voidID);
bool b2 = connect(m_SignalMapper, SIGNAL(mapped(QString)), this, SLOT(OpenWin(QString)));
QAction* selectedItem = ContextMenu.exec(globalPos);
}
void MainWindowContainer::OpenWin(QString gid)
{
//disconnect(sender0, SIGNAL(overflow()),receiver1, SLOT(handleMathError()));
disconnect(m_SignalMapper, SIGNAL(mapped(QString)),this, SLOT(OpenWin(QString)));
disconnect(OpenAction,SIGNAL(triggered()),m_SignalMapper, SLOT(map()));
....
....
}
For your second question, the term you are looking for is modal vs modeless dialogs. The QDialog documentation tells exactly how you create non-modal dialogs:
Modeless dialogs are displayed using show(), which returns control to the caller immediately.
i.e. don't use exec() as that will make a modal dialog (which blocks the parent).
You should not connect the same signal/slot more than once unless you want the action run multiple times. All you need to do is to connect the QAction's signal to the slot once. This is usually done in the constructor (or a dedicated function called from the constructor) where you create the action.