天天看点

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

1.最终效果展示

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

2.Qt默认的程序框架介绍

当我们用QtDesigner打开ui文件的时候,可以看到下图,下图是一个QMainWindow的框架,它包含了:菜单栏,工具栏,中心区域,状态栏

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

接下来,准备展示一下程序运行后的界面,但是为了让读者更容易看到每个区域的位置,我在MainWindow的构造函数中加了一丢丢代码:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //以下是作者添加的代码,分别向菜单栏、工具栏、状态栏添加了内容
    QMenu *menu1 = new QMenu(tr("文件"));
    menuBar()->addMenu(menu1);
    QMenu *menu2 = new QMenu(tr("编辑"));
    menuBar()->addMenu(menu2);
    QToolButton *toolBtn1 = new QToolButton(this);
    ui->mainToolBar->addWidget(toolBtn1);
    QLabel *label = new QLabel(tr("2021-10-12 11:50"));
    ui->statusBar->addWidget(label);
}
           

上面的代码运行之后,是这样的:

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

从上图可以清晰地找出菜单栏、工具栏、状态栏,而且我们能看到左上角有个程序的名称叫“MainWindow”,然后右上角有3个按钮,程序自带了黑色边框,边框外围有阴影。上述这些小部件都是Qt自动帮我们加上去的,只要你用的是QMainWindow,显示出来就会是这个样子。

上面这个界面可以看出,Qt默认的框架做出来的界面和商业化的桌面应用软件相比,可以说是很丑了。虽然Qt提供了样式表,也可以自绘,但是如果使用默认的框架,那依然有很多效果是无法实现的。以360安全卫士和HBuilder X为例,如果你想要用Qt默认的框架来实现下面这两个界面,可以说是很不好做了。

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能
Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

3.去掉默认的按钮和边框

从上一节的内容,可以看出Qt的默认框架有很大局限性,不利于我们实现很多炫酷漂亮的功能,那么应该怎么办呢?

  • (1).去掉右上角三个按钮
  • (2).去掉左上角标题
  • (3).去掉边框和阴影
  • (4).去掉菜单栏、工具栏、状态栏
  • (5).自己实现上述去掉的所有部件

那么代码怎么写呢?

上面列出的(1)、(2)、(3)可以通过下面的代码实现

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowFlags(Qt::FramelessWindowHint);
}
           

第(4)点,需要去QtDesigner上删除,右键点击对应区域,选择删除即可。

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能
Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能
Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

上面的步骤执行完后,我们再来运行程序,将会是下面这个样子的:

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

4.实现可拖拽/可最大化/可最小化/可关闭功能

经过第3节中的步骤之后,我们现在看到的程序是没有关闭按钮的,也无法移动位置,这肯定不是我们想要的结果。接下来,我将说明如何逐一实现“可拖拽/可最大化/可最小化/可关闭功能”。

4.1 第1步:新建资源文件

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能
Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能
Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

4.2 第2步:添加图标到资源文件中

在工程目录下,新建一个Resources目录,然后在网上找4个图标,分别用于最小化,最大化,关闭按钮的背景图片,以及应用程序的右上角图标。

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

打开qrc文件

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

添加前缀

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

修改前缀

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

添加图片文件

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

选择图片

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

添加图片后的样子 

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

 至此,图标已添加完成,记得按下CTRL+S保存一下。

4.3 第3步:添加控件

双击ui文件,用Qt设计师打开后,拖动5个Widget控件到界面上,并调整好位置和大小,然后修改控件名称,下图中右侧列表是我建议的名称:

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

添加两个Label控件,分别用于显示应用程序图标和名称

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

 添加3个按钮控件到右上角,分别用于最小化,最大化,关闭。 

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

4.4 第4步:设置控件文字和背景

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能
Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

使用上面的方法为每个按钮都设置一下背景图片,变成下面这样:

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

 这里由于图片的尺寸和按钮尺寸不吻合,导致被拉伸了,不好看,没关系,后面想办法处理。

4.5 第5步:实现用鼠标移动程序窗口的功能

头文件中增加如下代码:

protected:
    void mouseMoveEvent(QMouseEvent *e);
    void mousePressEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *);

private:
    bool m_bMousePressed;
    QPoint m_mousePoint;
    QRect m_areaMovable;//可移动窗口的区域,鼠标只有在该区域按下才能移动窗口
           

cpp中增加如下代码:

void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
    if (m_bMousePressed && (e->buttons() && Qt::LeftButton)) {
        this->move(e->globalPos() - m_mousePoint);
        e->accept();
    }
}

void MainWindow::mousePressEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton) {
        if (m_areaMovable.contains(e->pos()))
        {
            m_bMousePressed = true;
            m_mousePoint = e->globalPos() - this->pos();
        }
        e->accept();
    }
}

void MainWindow::mouseReleaseEvent(QMouseEvent *)
{
    m_bMousePressed = false;
}
           

并在构造函数中初始化m_areaMovable的值,

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowFlags(Qt::FramelessWindowHint);
    m_areaMovable = QRect(0,0,500,30);
}
           

然后运行一下程序,看看效果:

先切换到Release版本,不然图片显示不出来,

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

然后点击运行按钮

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

4.6 第6步:响应右上角按钮点击事件

 在头文件中添加如下代码:

public slots:
    void OnClickMinimizeBtn();
    void OnClickMaximizeBtn();
    void OnClickCloseBtn();
           

在cpp文件中添加如下代码:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    /*
    ....
    ....
    */

    connect(ui->minimizeBtn,SIGNAL(clicked()),this,SLOT(OnClickMinimizeBtn()));
    connect(ui->maximizeBtn,SIGNAL(clicked()),this,SLOT(OnClickMaximizeBtn()));
    connect(ui->closeBtn,SIGNAL(clicked()),this,SLOT(OnClickCloseBtn()));
}

void MainWindow::OnClickMinimizeBtn()
{
    showMinimized();
}

void MainWindow::OnClickMaximizeBtn()
{
    showMaximized();
}

void MainWindow::OnClickCloseBtn()
{
    close();
}
           

4.7 第7步:优化按钮图片显示效果

假如之前你添加的背景图片显示出来是正常的,那么这一节的内容可以不用看,我这里因为按钮尺寸是30*30,图片是16*16的,所以图片被拉伸了,显示出来后图片有点模糊。

下面说如何优化,我这里调整了一下margin的值:

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

 加了这句:

margin:6px;
           

加了之后图片的显示空间被压缩了,就不会被拉伸得很明显。对3个图片按钮对作同样的处理,然后下面看效果:

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

下面看一下动画效果 

Roson的Qt之旅#54 Qt去掉程序默认按钮和边框(但依然可拖动和最大最小化)1.最终效果展示2.Qt默认的程序框架介绍3.去掉默认的按钮和边框4.实现可拖拽/可最大化/可最小化/可关闭功能

到现在为止,我们实现了用鼠标移动窗口的功能,也实现了最小化、最大化、关闭按钮对应的功能,并且修改了应用程序图标,修改了按钮的样式。但是这还远远不够,比如说最大化按钮点击后,右上角的三个按钮跑到中间了,这肯定是不行的,还有标题栏、菜单栏、工具栏等全都是一个颜色,很丑。

想要了解如何解决上述问题,实现更加炫酷的效果,可以点一下左上角“关注”,右上角“订阅”,以免找不到我了,我将在后续的博客中一一讲述。

继续阅读