通过单击内部窗口小部件而不是标题栏来移动窗口

时间:2016-10-02 14:50:12

标签: c++ qt window mousemove titlebar

在我创建QMainWindow的Windows中,我可以通过单击标题栏并拖动它来在屏幕上移动它。

在我的应用程序中,我使用./ec2.py --list --profile personal 隐藏了标题栏,我正在尝试使用窗口小部件构建自定义标题栏并使用setWindowFlags(Qt::CustomizeWindowHint)在菜单空间中设置它。

现在我想要重现原始行为:我想点击QMainWindow中的setMenuWidget(myWidget)小部件,并且在按下鼠标时,拖动鼠标会移动窗口。

有办法吗?

2 个答案:

答案 0 :(得分:1)

您只需要通过覆盖MyWidget的{​​{1}},mousePressEvent()mouseMoveEvent()处理程序来实现必要的鼠标事件处理。

  1. 检测鼠标,获取当前鼠标位置
  2. 移动时,获取当前鼠标位置,计算差异,保存新位置,通过差异移动窗口
  3. 您可以从mouseReleaseEvent()内部通过MyWidget方法获取窗口(顶级窗口小部件)。

答案 1 :(得分:1)

这是一个关于如何实现假标题栏的示例,它具有标准按钮(最小化,最大化,关闭),并且可以拖动以移动整个窗口(这是基于@Kevin'中的方法。答案)。

screenshot

#include <QtWidgets>


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"