通过单击内部小部件而不是标题栏来移动窗口 [英] Move a window by clicking an internal widget instead of title bar

查看:27
本文介绍了通过单击内部小部件而不是标题栏来移动窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

在我的应用程序中,我使用 setWindowFlags(Qt::CustomizeWindowHint) 隐藏了标题栏,我正在尝试使用小部件构建自定义标题栏并将其设置在菜单空间中使用 setMenuWidget(myWidget).

In my application I've hidden the title bar by using setWindowFlags(Qt::CustomizeWindowHint) and I'm trying to build a custom title bar using a widget and setting it in the menu space with setMenuWidget(myWidget).

现在我想重现原来的行为:我想点击 QMainWindow 内的 MyWidget 小部件,然后在按下鼠标的同时拖动鼠标移动窗口.

Now I want to reproduce the original behaviour: I want to click on my MyWidget widget inside the QMainWindow and, while mouse is pressed, dragging the mouse moves the window.

有办法吗?

推荐答案

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

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 <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"

这篇关于通过单击内部小部件而不是标题栏来移动窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆