Move a window by clicking an internal widget instead of title bar

后端 未结 2 492
说谎
说谎 2021-01-28 19:02

In Windows when I create a QMainWindow I can move it around the screen by clicking the title bar and dragging it.

In my application I\'ve hidden the title bar by using <

2条回答
  •  天涯浪人
    2021-01-28 19:32

    This is an example on how to implement a fake title bar, that has standard buttons (minimize, maximize, close), and can be dragged to move the whole window (this is based on the approach in @Kevin's answer).

    #include 
    
    
    class FakeTitleBar : public QWidget{
        Q_OBJECT
    public:
        explicit FakeTitleBar(QWidget* parent= nullptr):QWidget(parent){
            label.setSizePolicy(QSizePolicy::Expanding,
                                QSizePolicy::Expanding);
            layout.addWidget(&label);
            layout.addWidget(&buttonMinimize);
            layout.addWidget(&buttonMaximize);
            layout.addWidget(&buttonClose);
            //connecting buttons' signals to slots
            connect(&buttonMinimize, &QPushButton::clicked,
                    this, &FakeTitleBar::MinimizeWindow);
            connect(&buttonMaximize, &QPushButton::clicked,
                    this, &FakeTitleBar::MaximizeWindow);
            connect(&buttonClose, &QPushButton::clicked,
                    this, &FakeTitleBar::CloseWindow);
            //setting vertical fixed size policy
            //so that the title bar does not take up any additional space
            setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
            //a bit of styling
            setStyleSheet("QPushButton {margin:0px; padding:5px;}"
                          "QWidget {background-color:blue; color:white;}");
        }
    
    public slots:
        //slots for corresponding buttons
        void MinimizeWindow(){
            window()->showMinimized();
        }
        void MaximizeWindow(){
            if(!window()->isMaximized())
                window()->showMaximized();
            else
                window()->showNormal();
        }
        void CloseWindow(){
            window()->close();
        }
    
    protected:
        void mousePressEvent(QMouseEvent* event){
            //save the press position (this is relative to the current widget)
            pressPos= event->pos();
            isMoving= true;
        }
        void mouseMoveEvent(QMouseEvent* event){
            //isMoving flag makes sure that the drag and drop event originated
            //from within the titlebar, because otherwise the window shouldn't be moved
            if(isMoving){
                //calculate difference between the press position and the new Mouse position
                //(this is relative to the current widget)
                QPoint diff= event->pos() - pressPos;
                //move the window by diff
                window()->move(window()->pos()+diff);
            }
        }
        void mouseReleaseEvent(QMouseEvent* /*event*/){
            //drag and drop operation end
            isMoving= false;
        }
        //double-clicking on the title bar should maximize the window
        void mouseDoubleClickEvent(QMouseEvent* /*event*/){
            MaximizeWindow();
        }
        //in order for the style sheet to apply on this custom widget
        //see https://doc.qt.io/qt-5/stylesheet-reference.html#qwidget-widget
        void paintEvent(QPaintEvent *)
        {
            QStyleOption opt;
            opt.init(this);
            QPainter p(this);
            style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
        }
    
    private:
        QHBoxLayout layout{this};
        QLabel label{"Fake Title Bar"};
        QPushButton buttonMinimize{"-"};
        QPushButton buttonMaximize{"M"};
        QPushButton buttonClose{"X"};
        QPoint pressPos;
        bool isMoving{false};
    };
    
    //sample usage
    
    class Widget : public QWidget{
    public:
        explicit Widget(QWidget* parent= nullptr):QWidget(parent){
            setWindowFlags(Qt::CustomizeWindowHint);
            layout.addWidget(&titleBar);
            layout.addWidget(&label);
            layout.setContentsMargins(0, 0, 0, 0);
            label.setAlignment(Qt::AlignCenter);
            //default size for the window
            resize(320,240);
        }
        ~Widget(){}
    
    private:
        QVBoxLayout layout{this};
        FakeTitleBar titleBar;
        QLabel label{"this is a sample window"};
    };
    
    int main(int argc, char* argv[]) {
        QApplication app(argc, argv);
    
        Widget w;
        w.show();
    
        return app.exec();
    }
    
    #include "main.moc"
    

提交回复
热议问题