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

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

时间 2014-08-22 16:06:05 CSDN博客

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

主题 Qt

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

有道的单词本:

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

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

具体实现如下代码(widget.ui未做任何改变):

1、widget.h文件

#ifndef WIDGET_H

#define WIDGET_H

 

#include

#define MARGIN 20//四个角的长度

namespace Ui {

class Widget;

}

 

class Widget : public QWidget

{

  Q_OBJECT

 

public:

  explicitWidget(QWidget *parent = 0);

  ~Widget();

  intcountFlag(QPoint p, int row);

  voidsetCursorType(int flag);

  intcountRow(QPoint p);

 

protected:

  voidmousePressEvent(QMouseEvent *event);

  voidmouseReleaseEvent(QMouseEvent *event);

  voidmouseDoubleClickEvent(QMouseEvent *event);

  voidmouseMoveEvent(QMouseEvent *event);

private:

  Ui::Widget *ui;

  boolisLeftPressed;

  int curPos;

  QPoint pLast;

};

 

#endif // WIDGET_H

2、widget.cpp文件

#include "widget.h"

#include "ui_widget.h"

#include

#include

 

Widget::Widget(QWidget *parent) :

  QWidget(parent),

  ui(newUi::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="<height();

  setWindowFlags(Qt::FramelessWindowHint);//设置主窗口无边框

  qDebug()<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);

    elsesetWindowState(Qt::WindowNoState);//恢复正常模式

  }

  event->ignore();

}

 

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

{

 

  intposs=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

    {

      QRectwid=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()

    return 10+row;

  else if(p.y()>this->height()-MARGIN)

    return 30+row;

  else

    return 20+row;

}

 

void Widget::setCursorType(int flag)//根据鼠标所在位置改变鼠标指针形状

{

  Qt::CursorShapecursor;

  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()(this->width()-MARGIN)?3:2);

}

3、main.cpp文件

#include

#include "widget.h"

int main(int argc, char *argv[])

{

    QApplicationa(argc, argv);

    Widget w;

    w.show();

   

    return a.exec();

}

程序运行截图如下:

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

 

你可能感兴趣的:(QT)