【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属性,加上图片即可。下面给出使用上面的无边框窗口所做的词典软件的主界面:

时间: 2024-07-30 13:49:47

【Qt编程】无边框窗口的缩放与拖动的相关文章

PyQt4中无边框窗口的移动(拖动)

import sys from PyQt4.QtGui import * from PyQt4.Qt import * from PyQt4.QtCore import * class AboutUsDialog(QDialog): def __init__(self): super(AboutUsDialog,self).__init__() self.setWindowFlags(Qt.FramelessWindowHint|Qt.Dialog) def mousePressEvent(se

【Qt编程】无边框窗口的拖动

在上一篇文章中,我们讲述了如何进行无边框窗口的缩放与拖动,而在一些情况下,我们的窗口只需要进行拖动也不需要改变其大小,比如:QQ的登录窗口.本来在上一篇文章中已经讲述了如何进行窗口的拖动,但是却与窗口的缩放相关的程序放在一起,下面专门单独分离出来. 窗口的拖放只涉及到鼠标事件:按下操作.释放操作和移动操作,因此只需要重写这三个函数.由于程序比较简单,并且注释也比较详细,就不作过多介绍.新建一个基类为QWidget的Qt Gui应用程序,只需修改widget.h和widget.cpp文件如下: 1

141107●Winform拖动无边框窗口、播放音频、启动外部exe程序

鼠标拖动无边框窗口 1. //鼠标拖动 Point downpoint = new Point(); //事件,鼠标按下,获取当前坐标 private void panel1_MouseDown(object sender, MouseEventArgs e) { downpoint.X = -e.X; downpoint.Y = -e.Y; } //事件,鼠标移动,赋值新坐标 private void panel1_MouseMove(object sender, MouseEventArgs

pyQt5设计无边框窗口

from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QVBoxLayoutfrom PyQt5.QtCore import Qt, QPointfrom PyQt5.QtGui import QFont, QCursor class QTitleLabel(QLabel): """ 新建标题栏标签类 """ def __init__(self, *args): super(QTitl

QT界面开发-(特效)无边框窗口+背景图片

转发自邵发<C/C++系列教程>Qt界面开发 https://chuanke.baidu.com/4509752-209060.html 1.自己用代码画界面 2.用Laber控件放一张背景大图 hpp 1 #include <QtWidgets> 2 3 4 private: 5 virtual void paintEvent(QPaintEvent *event); 6 7 virtual void mouseMoveEvent(QMouseEvent * event); 8

无边框对话框的缩放

1.        添加WM_NCHITTEST消息 2.        设置对话框属性System Menu 为False. 如果不设置添加完代码以后对话框边框出现了箭头,但是窗口大小是固定的. 3.        添加代码 LRESULT CDialogZoomDlg::OnNcHitTest(CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //无边框缩放 //这里是防止在最大化的时候能缩放窗口(在没有WS_THICKFRAME风格的情况下需要这样

winform无边框窗口拖动

无边框的窗口想拖动,只需要在置顶的容器上添加对应的mousedown 和 mousemove 事件就可以实现了.代码如下: 1 //拖动窗口 2 private Point mPoint = new Point(); 3 4 private void panel1_MouseDown(object sender, MouseEventArgs e) 5 { 6 mPoint.X = e.X; 7 mPoint.Y = e.Y; 8 } 9 10 private void panel1_Mouse

Winform 无边框窗口移动自定义边框粗细颜色

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace Wi

QT_无边框窗口拖动缩放

public: 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 mous