Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt 5.13.2 Keep all windows on same screen



  • So, I have an app that may display any one of several (more than 20) different forms. I also have more than one display. Not too uncommon right? The problem is that when I place the MainWindow on another screen and call a function that re-displays it, the form is not displayed on the same window, it goes back to the screen where it was launched.

    How do I keep it on the same window where displayed? Or determine where it is displayed by choice or by default?

    This may be a newbie question but it is one that has me perplexed so far. I only found this problem when I got the new screen. Of course it is not a problem for single screen systems. But for me and my alpha tester it is very frustrating because we have multiple screens.


  • Lifetime Qt Champion

    Hi,

    What OS are you running ?
    If Linux, what distribution ? Desktop Environment ? Window manager ?



  • I am not sure what the OS has to do with it but I will include my environment if it is needed:

    Linux Mint 19.2 Cinnamon 4.2.4
    Kernel 5.3.0-24-generic
    Qt 5.13.2



  • @ad5xj

    Have a look at https://doc.qt.io/qt-5/qguiapplication.html#screens

    and QGuiApplication::primaryScreen()

    It may solve your problem.
    (You could check on which screen a Window was shown and save this state somewhere, so that you can put it back on this screen + coordinates, when this Window gets re-opened)



  • This is all well and good if the window is created as a QWindow. However for QMainWindow and QDialog windows (the normal in my application) there are no available functions to get or set the screen in those classes nor the inherited ones.



  • @ad5xj

    I think, it will work for all QWidgets

    @ad5xj said in Qt 5.13.2 Keep all windows on same screen:

    there are no available functions to get or set the screen in those classes nor the inherited ones

    I wasn`t talking about existing, ready-to-use functions. I just wanted to point in the right / a possible direction ;-)
    Ofc you have to try what will work for you.

    QGuiApplication::screens() will return a QList of all QScreens that are connected to your system.
    QGuiApplication::screenAt(const QPoint &point) will return the QScreen to a given point.

    You can work with that, even if you dont have QWindows.

    @ad5xj said in Qt 5.13.2 Keep all windows on same screen:

    The problem is that when I place the MainWindow on another screen and call a function that re-displays it, the form is not displayed on the same window, it goes back to the screen where it was launched

    Form = Your MainWindow or the child dialogs?

    If it's just the MainWindow (in fact all child dialogs / windows should open on top of parent, on the same screen), you could save the current position or screen in your MainWindow-class on MainWindow-moveEvent or before you call that specific function and restore it back to these coordinates. Then you should have all your dialogs on the screen, where your Mainwindow was moved.

    You could also work with screen geometry to determine on which screen your Widget can be found.



  • I can appreciate that QGuiApplication::screens() returns the list of screens. And that QGuiApplication::screenAt(const QPoint &point) returns the screen for a given point.

    My difficulty is understanding how to cause any new form to be created or moved to the screen who's handle is captured by these functions. I can find no association to QScreen in QMainWindow nor QDialog.

    Suppose I was working on Screen 2 and the cursor is displayed on Screen 2 when the application opens on Screen 1. The splash screen displays on Screen 2. But the rest of the application displays on Screen 1. Even if I go to Screen 1 and call a function that displays a new dialog, it does not stay on Screen 1.

    I know it sounds confusing. It is a confusing situation for me too. Since I am new to having multiple screens this is the first encounter with this problem.

    The QMainWindow:->geometry() function does not include the screen as a parameter so I am not familiar with what you mean by "work with screen geometry" on a QMainWindow or QDialog class in terms of saving or manipulating the screen identity. Nor does it have any function that returns the screen number or a function to set the screen number. So saving the screen is not something I am familiar with. Need much more information.



  • @ad5xj said in Qt 5.13.2 Keep all windows on same screen:

    I can find no association to QScreen in QMainWindow nor QDialog.

    I guess because there is none :-)

    As I said, you have to manage it on your own. Unfortunately there isn't any setting or function in Qt that manages the first screen, where new QWidgets appear.

    @ad5xj said in Qt 5.13.2 Keep all windows on same screen:

    Suppose I was working on Screen 2 and the cursor is displayed on Screen 2 when the application opens on Screen 1. The splash screen displays on Screen 2. But the rest of the application displays on Screen 1. Even if I go to Screen 1 and call a function that displays a new dialog, it does not stay on Screen 1.

    Can you provide an example to show how you create these windows / forms, especially the splash screen?

    So your primaryScreen is Screen 1, but you are working on Screen 2 and starting the App from there?! Splash is shown on S2, and the rest on S1?!

    What is your expected behavior there? All on Screen 1 or all on Screen 2?
    What are your screen resolutions from 1 and 2?

    @ad5xj said in Qt 5.13.2 Keep all windows on same screen:

    Need much more information

    For example:
    I used this to make sure a QDialog inherited custom class window is always centered (independ from screen resolution or size and parent position). Works even on multiple screen systems, as long as there is a primaryScreen, which should be the case every time.

    QScreen *screen = QGuiApplication::primaryScreen();
    this->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, this->size(), screen->geometry()));
    

    You dont need associations in Qt classes to make it work

    EDIT:

    One thing that came to my mind after posting this:
    Does your "splash" screen have a parent window / widget?



  • I think I can answer your questions (at least partly) by saying, the splash screen is a QDialog started from main.cpp with no parent. The application QMainWindow is also started from main.cpp with no parent...why would they have a parent? As to the reasons for the splash screen appearing on the Screen 2 I have no idea other than the cursor position is there and unrelated work is being done there. The app would have been started prior to moving the cursor from Screen 1 to Screen 2 during the application startup period. I had expected all screens to display on the Screen where the app was launched. That does not happen.

    Your example is completely foreign to me since I have never had the need to go to these lengths to insure a window always opens in the right place. Just saving and restoring the geometry has been sufficient. I have to assume (I know...dangerous right? ... since your narritive does not say so) that the QGuiApplication::primaryScreen() is the pointer to the application QMainWindow screen. I will have to try this to see if that bears out. It does not help with the splash screen since it is the first window displayed and does not have a parent. Still many questions in my feeble mind.


  • Moderators

    @ad5xj
    you do know, that you can move Windows and Dialogs around via the move() function ?

    You can use that + primary screen to position the Dialog where you want to
    for example a new BaseDialog Class that always centers the Dialog in the Primary screen

    #ifndef CENTEREDDIALOG_H
    #define CENTEREDDIALOG_H
    
    #include <QDialog>
    
    #include <QGuiApplication>
    #include <QScreen>
    #include <QShowEvent>
    
    class CenteredDialog : public QDialog
    {
        Q_OBJECT
    public:
        explicit CenteredDialog(QWidget *parent = nullptr) : QDialog(parent){ }
    
    protected:
        virtual void showEvent(QShowEvent *event) override
        {
            QScreen *primeScreen = QGuiApplication::primaryScreen();
            
            QRect geo = primeScreen->geometry();
            
            int newX= (geo.width() - width()) / 2 + geo.x();
            int newY= (geo.height() - height()) /2 +  geo.y();
            this->move(newX, newY);
            
            QDialog::showEvent(event);
        }
    
    };
    
    #endif // CENTEREDDIALOG_H
    


  • Alright! This seems to have tamed the wild and woolley screen appearance. Thanks to all who contributed especially J.Hilk for the hints. I will consider this solved.


  • Moderators

    @ad5xj alright great :)
    Don't forget to use the topic tools to set the topic to solved


Log in to reply