QT实现鼠标拖动调整窗口大小

要想实现该功能,我们需要考虑一下几个问题。

1、如何获取鼠标的移动,点击,释放

    通过实现一下几个事件来获取窗体的事件

    void mouseMoveEvent(QMouseEvent *event);

    void mousePressEvent(QMouseEvent *event);

    void mouseReleaseEvent(QMouseEvent *event);

2、如何判断鼠标是否移动到窗体的边界

    一个窗体的结构大概如下图所示

    上左   上   上右

    左       中     右   

    下左   下    下右

    那么我们用数字来表示如下

    11    12    13

    21    22    23

    31    32    33

    那么我们就得到鼠标在除了22的位置就到达了窗体的边界

上代码:

enum {
    TOPLEFT = 11,
    TOP = 12,
    TOPRIGHT = 13,
    LEFT = 21,
    CENTER = 22,
    RIGHT = 23,
    BUTTOMLEFT = 31,
    BUTTOM = 32,
    BUTTOMRIGHT = 33
};

#define FRAMESHAPE 10    

public:
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    int CalCursorCol(QPoint pt);    //计算鼠标X的位置 
    int CalCursorPos(QPoint pt, int colPos);    //计算鼠标的位置
    void setCursorShape(int CalPos);    //设置鼠标对应位置的形状

private:
    int     m_iCalCursorPos;
    bool    m_bLeftPress;
    QRect   m_rtPreGeometry;
    QPoint  m_ptViewMousePos;
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    m_bLeftPress(false)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::FramelessWindowHint);    //取消窗体的标题栏
    setMouseTracking(true);   //MouseMoveEvent为了不太耗资源在默认状态下是要鼠标按下才能捕捉到,要想鼠标不按下时的移动也能捕捉到设置为true
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    //窗体不是最大的话就改变鼠标的形状
    if(Qt::WindowMaximized != windowState())
    {
        setCursorShape(CalCursorPos(event->pos(),CalCursorCol(event->pos())));
    }
    //获取当前的点,这个点是全局的
    QPoint ptCurrentPos = QCursor::pos();
    //计算出移动的位置,当前点 - 鼠标左键按下的点
    QPoint ptMoveSize = ptCurrentPos - m_ptViewMousePos;
    QRect rtTempGeometry = m_rtPreGeometry;
    if(m_bLeftPress)
    {
        switch(m_iCalCursorPos)
        {
        case TOPLEFT:
            rtTempGeometry.setTopLeft(m_rtPreGeometry.topLeft()+ptMoveSize);
            break;
        case TOP:
            rtTempGeometry.setTop(m_rtPreGeometry.top()+ptMoveSize.y());
            break;
        case TOPRIGHT:
            rtTempGeometry.setTopRight(m_rtPreGeometry.topRight()+ptMoveSize);
            break;
        case LEFT:
            rtTempGeometry.setLeft(m_rtPreGeometry.left()+ptMoveSize.x());
            break;
        case RIGHT:
            rtTempGeometry.setRight(m_rtPreGeometry.right()+ptMoveSize.x());
            break;
        case BUTTOMLEFT:
            rtTempGeometry.setBottomLeft(m_rtPreGeometry.bottomLeft()+ptMoveSize);
            break;
        case BUTTOM:
            rtTempGeometry.setBottom(m_rtPreGeometry.bottom()+ptMoveSize.y());
            break;
        case BUTTOMRIGHT:
            rtTempGeometry.setBottomRight(m_rtPreGeometry.bottomRight()+ptMoveSize);
            break;
        default:
            break;
        }
        //移动窗体,如果比最小窗体大,就移动
        if(rtTempGeometry.width() >= 200 && rtTempGeometry.height() >= 300)
            setGeometry(rtTempGeometry);

    }
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    m_iCalCursorPos = CalCursorPos(event->pos(),CalCursorCol(event->pos()));
    if (event->button() == Qt::LeftButton /*&& Qt::WindowMaximized != windowState()*/)
    {
        if(m_iCalCursorPos != CENTER)
        {
            m_bLeftPress = true;
        }
    }
    m_rtPreGeometry = geometry();
    m_ptViewMousePos = event->globalPos();
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    m_bLeftPress = false;
    QApplication::restoreOverrideCursor();
}

int Widget::CalCursorCol(QPoint pt)
{
    return (pt.x() < FRAMESHAPE ? 1 : ((pt.x() > this->width() - FRAMESHAPE) ? 3 : 2));
}

int Widget::CalCursorPos(QPoint pt, int colPos)
{
    return ((pt.y() < FRAMESHAPE ? 10 : ((pt.y() > this->height() - FRAMESHAPE) ? 30 : 20)) + colPos);
}

void Widget::setCursorShape(int CalPos)
{
    Qt::CursorShape cursor;
    switch(CalPos)
    {
    case TOPLEFT:
    case BUTTOMRIGHT:
        cursor = Qt::SizeFDiagCursor;
        break;
    case TOPRIGHT:
    case BUTTOMLEFT:
        cursor = Qt::SizeBDiagCursor;
        break;
    case TOP:
    case BUTTOM:
        cursor = Qt::SizeVerCursor;
        break;
    case LEFT:
    case RIGHT:
        cursor = Qt::SizeHorCursor;
        break;
    default:
        cursor = Qt::ArrowCursor;
        break;
    }
    setCursor(cursor);
}

 

  • 9
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: 当我们在Qt桌面应用程序中进行缩放操作时,会面临一个问题,那就是在缩放后如何处理鼠标拖动。 首先,为了实现桌面缩放功能,我们可以使用Qt中的QGraphicsView类。这个类是用于在桌面上展示可视化图形的视图类。它可以帮助我们轻松地实现桌面缩放的功能。 在缩放操作中,一个常见的需求是,当我们使用鼠标在已缩放好的桌面上进行拖动时,视图能够跟随鼠标移动,并保持相对的位置。为了实现这一需求,我们可以使用QGraphicsView的鼠标事件函数来处理鼠标拖动的操作。 具体而言,我们可以在QGraphicsView的mousePressEvent、mouseMoveEvent和mouseReleaseEvent函数中编写代码来处理鼠标拖动操作。当我们按下鼠标按钮时,可以记录下鼠标的初始位置,并将鼠标移动事件与当前视图的位置变化联系起来。在移动鼠标过程中,我们可以通过计算鼠标相对于初始位置的偏移量来调整视图的位置。最后,在释放鼠标按钮时,停止记录鼠标的位置信息。 需要注意的是,在处理鼠标拖动的过程中,我们还应该考虑到缩放的逻辑。换句话说,当我们拖动缩放过的桌面时,应该相应地调整视图的位置,并将缩放因子考虑在内。这样才能保证拖动操作的平滑和正确。 综上所述,通过使用QGraphicsView类,并适当地处理鼠标事件,我们就能够实现Qt桌面应用程序中,进行缩放后的鼠标拖动操作。这样,用户就可以方便地在缩放后的桌面上进行拖动操作,从而获得更好的使用体验。 ### 回答2: 在Qt中,当我们对桌面进行缩放后,鼠标拖动的行为会受到影响。 首先,要明确桌面缩放的概念。在某些情况下,我们可能需要更改桌面上的视图大小,以便更好地适应不同的显示设备。这意味着所有的桌面元素,包括窗口、控件和图像,都会相应地缩放。 当桌面缩放后,鼠标拖动行为会发生变化。具体来说,因为桌面元素缩小了,鼠标的移动距离也会相应地减小。例如,如果我们将桌面缩放比例设置为50%,那么鼠标在屏幕上实际移动的距离将是原来的一半。 这就对我们在编写Qt程序时处理鼠标拖动的代码提出了挑战。我们需要根据屏幕的缩放比例来调整鼠标的移动距离,以使其在逻辑上与实际的桌面元素相对应。一种常见的解决方案是使用Qt的“逻辑像素”来处理鼠标移动事件,而不是依赖于实际的物理像素。 通过这种方式,我们可以确保在任何桌面缩放比例下,鼠标拖动行为都是一致的。但是需要注意的是,当我们的应用程序需要与其他非Qt的桌面应用程序进行交互时,可能会出现一些兼容性问题。因为其他应用程序可能不支持Qt的逻辑像素概念,导致鼠标拖动行为不一致。 因此,在编写Qt程序时,我们应该尽量考虑到桌面缩放的情况,并采取相应的处理方式,以确保鼠标拖动行为在不同的缩放比例下都能正常工作。这需要一些额外的逻辑和计算,但可以提高用户体验并适应不同的显示设备。 ### 回答3: 在Qt桌面应用程序中,如果想要实现桌面缩放后鼠标拖动的功能,可以按照以下步骤进行操作: 首先,需要使用Qt的窗口部件类(比如QWidget)创建一个主窗口。在主窗口中,通过重写鼠标事件函数来实现拖动操作。 其次,需要在主窗口中设置一个缩放因子,用于控制桌面的缩放比例。可以使用QTransform类来实现缩放效果。 然后,需要重写主窗口的鼠标事件函数。在鼠标按下事件中,记录鼠标的初始位置;在鼠标移动事件中,根据鼠标的当前位置计算出移动的距离,并根据缩放因子进行调整;最后,在鼠标释放事件中,重置鼠标的位置。 最后,将主窗口显示出来,并启动应用程序的事件循环。 通过以上步骤,就可以在Qt桌面应用程序中实现缩放后鼠标拖动的功能。当用户鼠标按下并移动时,主窗口会跟随鼠标的移动而进行相应的拖动操作,且拖动的位移会根据缩放因子进行调整,以保证拖动的平滑性和准确性。 需要注意的是,这只是一个基本的实现思路,具体的代码实现需要根据实际需求进行调整和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值