【Qt编程】基于Qt的词典开发系列<四>--无边框窗口的缩放与拖动

简介:         在现在,绝大多数软件都向着简洁,时尚发展。就拿有道的单词本和我做的单词本来说,绝大多数用户肯定喜欢我所做的单词本(就单单界面,关于颜色搭配和布局问题,大家就不要在意了)。
+关注继续查看
        在现在,绝大多数软件都向着简洁,时尚发展。就拿有道的单词本和我做的单词本来说,绝大多数用户肯定喜欢我所做的单词本(就单单界面,关于颜色搭配和布局问题,大家就不要在意了)。

有道的单词本:


我所做的单词本:


        很明显,两者的主要区别就是周围的边框问题。你可以对比QQ以前的版本和这几年的版本,就会发现都倾向于下面这种窗口模式。下面我们就说说如何用Qt实现无边框窗口的缩放与拖动。

        对于无边框窗口的拖动其实很简单,其基本思想是,在鼠标移动前后记录鼠标的坐标,然后将窗口移动这两个坐标之差的距离即可,具体实现可以看代码,就非常清楚了。下面主要讲讲如何实现鼠标改变窗口的大小,首先,我们将一个窗口分为以下9个区域,其中只有鼠标在22区域时无法改变其形状,不能改变窗口大小。当鼠标在其它区域时,鼠标改变形状并可以改变窗口大小。窗口区域分类如下图:


具体实现如下代码(widget.ui未做任何改变):
1、widget.h文件
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#define MARGIN 20//四个角的长度
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT
    
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    int countFlag(QPoint p, int row);
    void setCursorType(int flag);
    int countRow(QPoint p);

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void mouseDoubleClickEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
private:
    Ui::Widget *ui;
    bool isLeftPressed;
    int curPos;
    QPoint pLast;
};

#endif // WIDGET_H

2、widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include<QMouseEvent>
#include<QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setMouseTracking(true);
    //设置在不按鼠标的情况下也触发鼠标移动事件,注意QMainWindow的情况:centralWidget()->setMouseTracking(true);
    isLeftPressed=false;
    curPos=0;//标记鼠标左击时的位置
    this->setMinimumSize(400,300);//设置最小尺寸
    QCursor cursor;
    cursor.setShape(Qt::ArrowCursor);//设置鼠标为箭头形状
   // ui->pushButton->setCursor(cursor);//当放在按钮上时,为箭头
   // cursor.setShape(Qt::OpenHandCursor);
    QWidget::setCursor(cursor);//当放在主窗口上时,为手形
    qDebug()<<"h="<<this->height();
    setWindowFlags(Qt::FramelessWindowHint);//设置主窗口无边框
    qDebug()<<this->minimumHeight();
}

Widget::~Widget()
{
    delete ui;
}
void Widget::mousePressEvent(QMouseEvent *event)//鼠标按下事件
{
    if(event->button()==Qt::LeftButton)
    {
        this->isLeftPressed=true;
        QPoint temp=event->globalPos();
        pLast=temp;
        curPos=countFlag(event->pos(),countRow(event->pos()));
        event->ignore();
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event)//鼠标释放事件
{
    if(isLeftPressed)
        isLeftPressed=false;
    QApplication::restoreOverrideCursor();//恢复鼠标指针性状
    event->ignore();
}

void Widget::mouseDoubleClickEvent(QMouseEvent *event)//鼠标双击 全屏
{
    if(event->button()==Qt::LeftButton)
    {
        if(windowState()!=Qt::WindowFullScreen)
            setWindowState(Qt::WindowFullScreen);
        else setWindowState(Qt::WindowNoState);//恢复正常模式
    }
    event->ignore();
}

void Widget::mouseMoveEvent(QMouseEvent *event)//鼠标移动事件
{

    int poss=countFlag(event->pos(),countRow(event->pos()));
    setCursorType(poss);
    if(isLeftPressed)//是否左击
    {
        QPoint ptemp=event->globalPos();
        ptemp=ptemp-pLast;
        if(curPos==22)//移动窗口
        {
            ptemp=ptemp+pos();
            move(ptemp);
        }
        else
        {
            QRect wid=geometry();

            switch(curPos)//改变窗口的大小
            {

            case 11:wid.setTopLeft(wid.topLeft()+ptemp);break;//左上角
            case 13:wid.setTopRight(wid.topRight()+ptemp);break;//右上角
            case 31:wid.setBottomLeft(wid.bottomLeft()+ptemp);break;//左下角
            case 33:wid.setBottomRight(wid.bottomRight()+ptemp);break;//右下角
            case 12:wid.setTop(wid.top()+ptemp.y());break;//中上角
            case 21:wid.setLeft(wid.left()+ptemp.x());break;//中左角
            case 23:wid.setRight(wid.right()+ptemp.x());break;//中右角
            case 32:wid.setBottom(wid.bottom()+ptemp.y());break;//中下角
            }
            setGeometry(wid);
        }


        pLast=event->globalPos();//更新位置
    }
    event->ignore();
}



int Widget::countFlag(QPoint p,int row)//计算鼠标在哪一列和哪一行
{
    if(p.y()<MARGIN)
        return 10+row;
    else if(p.y()>this->height()-MARGIN)
        return 30+row;
    else
        return 20+row;
}

void Widget::setCursorType(int flag)//根据鼠标所在位置改变鼠标指针形状
{
    Qt::CursorShape cursor;
    switch(flag)
    {
    case 11:
    case 33:
        cursor=Qt::SizeFDiagCursor;break;
    case 13:
    case 31:
        cursor=Qt::SizeBDiagCursor;break;
    case 21:
    case 23:
        cursor=Qt::SizeHorCursor;break;
    case 12:
    case 32:
        cursor=Qt::SizeVerCursor;break;
    case 22:
        cursor=Qt::OpenHandCursor;break;
    default:
       //  QApplication::restoreOverrideCursor();//恢复鼠标指针性状
         break;

    }
    setCursor(cursor);
}

int Widget::countRow(QPoint p)//计算在哪一列
{
    return (p.x()<MARGIN)?1:(p.x()>(this->width()-MARGIN)?3:2);
}
3、main.cpp文件

#include<QtWidgets>
#include "widget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}

程序运行截图如下:


        当你将鼠标放在窗口的边缘时,鼠标会变化形状,表示可以拖动窗口。由于没有关闭窗口,只能在强制关闭窗口。如果想做到和不同窗口实现最小化和关闭窗口的画,我们可以在窗口左上角放置两个ToolButton,并设置autorise属性,加上图片即可。下面给出使用上面的无边框窗口所做的词典软件的主界面:



基于Qt的词典开发系列

  1. 词典框架设计及成品展示
  2. 本地词典的设计
  3. 开始菜单的设计
  4. 无边框窗口的缩放与拖动
  5. 无边框窗口的拖动
  6. 界面美化设计
  7. 调用网络API
  8. 用户登录及API调用的实现
  9. JSON数据解析
  10. 国际音标的显示
  11. 系统托盘的显示
  12. 调用讲述人
  13. 音频播放
  14. 自动补全功能
  15. HTML特殊字符及正则表达式
  16. 后序
作品下载地址(发布版)http://download.csdn.net/detail/tengweitw/8548767
作品下载地址(绿色版)http://download.csdn.net/detail/tengweitw/8830495
源码下载地址http://download.csdn.net/detail/tengweitw/8830503

原文:http://blog.csdn.net/tengweitw/article/details/38758051

作者:nineheadedbird




目录
相关文章
|
9月前
|
C++
qt开发从入门到实战1
qt开发从入门到实战1
145 1
qt开发从入门到实战1
|
10月前
|
区块链 开发工具 C语言
教你用Qt开发一个串口上位机控制LED
教你用Qt开发一个串口上位机控制LED
498 0
教你用Qt开发一个串口上位机控制LED
|
11月前
|
JavaScript 大数据
Qt+ECharts开发笔记(五):ECharts的动态排序柱状图介绍、基础使用和Qt封装Demo
上一篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口。   本篇的demo实现了自动排序的柱状图,实现了一个自动排序柱状图的基本交互方式,即Qt调用js脚本操作html。   本篇demo使用Qt定时器方式,实现数据定时刷新自增,并预留出了定时器间隔参数。   像大数据网页常看的人口增长时间图,收入年度增长时间图等都是这一类。
Qt+ECharts开发笔记(五):ECharts的动态排序柱状图介绍、基础使用和Qt封装Demo
|
JavaScript
Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo
前一篇介绍了横向柱图图。本篇将介绍基础饼图使用,并将其封装一层Qt。本篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口。
Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo
|
存储 编解码 缓存
Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件
上一篇已经将himpp套入qt的基础上进行开发。那么qt中拿到frame则是很关键的交互,这是qt与海思可能编解码交叉开发的关键步骤。
Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件
|
缓存 JavaScript 编译器
Qt+ECharts开发笔记(三):ECharts的柱状图介绍、基础使用和Qt封装Demo
上一篇成功是EChart随着Qt窗口变化而变化,本篇将开始正式介绍柱状图介绍、基础使用,并将其封装一层Qt。   本篇的demo实现了隐藏js代码的方式,实现了一个条形图的基本交互方式,即Qt调用js脚本操作html。
Qt+ECharts开发笔记(三):ECharts的柱状图介绍、基础使用和Qt封装Demo
|
Windows
Qt+ECharts开发笔记(二):Qt窗口动态调整大小,使ECharts跟随Qt窗口大小变换而变换大小
上一篇将ECharts嵌入Qt中,在开始ECharts使用之前,还有一个很重要的功能,就是在窗口变换大小的时候,ECharts的图表尺寸也要跟随Qt窗口变换大小而变换大小。
Qt+ECharts开发笔记(二):Qt窗口动态调整大小,使ECharts跟随Qt窗口大小变换而变换大小
|
Web App开发 数据可视化 JavaScript
Qt+ECharts开发笔记(一):ECharts介绍、下载和Qt调用ECharts基础柱状图Demo
使用Qt开发大数据可视化看板,基于Qt使用QWidget或者QML是很难达到ECharts大数据看板的效果,所以使用Qt来制作。
Qt+ECharts开发笔记(一):ECharts介绍、下载和Qt调用ECharts基础柱状图Demo
|
关系型数据库 MySQL 数据库
树莓派开发笔记(十七):树莓派4B+上Qt多用户连接操作Mysql数据库同步(单条数据悲观锁)
安装了mysq数据库,最终时为了实现在一个树莓派上实现多用户多进程操作的同步问题,避免数据并发出现一些错误,本篇安装了远程服务并且讲述了使用Qt进行悲观锁for update操作,命令行进行同步查询的示例。
树莓派开发笔记(十七):树莓派4B+上Qt多用户连接操作Mysql数据库同步(单条数据悲观锁)
|
Ubuntu Linux C语言
麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12
麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12
麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12
相关产品
云迁移中心
推荐文章
更多
推荐镜像
更多