2011-04-22 91 views
4

我的问题是基本相同this one,但施加到Qt的C++框架。Qt的:调整无边界插件

我用标志的Qt继承了QWidget实现一个弹出窗口:: QPopup | Qt的:: QWindow。我想这个窗口是移动和调整大小,我目前使用的鼠标事件在下面的代码实现这一点:

void TextPopup::mousePressEvent(QMouseEvent* event) 
{ 
    offset = event->pos(); 
    QWidget::mousePressEvent(event); 
} 

void TextPopup::mouseMoveEvent(QMouseEvent* event) 
{ 
    if(event->buttons() & Qt::LeftButton) 
     if(resizeMode) { 
      QPoint p = mapToGlobal(event->pos()) - geometry().topLeft(); 
      resize(p.x(), p.y()); 
     } else 
      move(mapToParent(event->pos() - offset)); 
    else { 
     QPoint diff = geometry().bottomRight() - mapToGlobal(event->pos()); 
     if(diff.x() <= 6 && diff.y() <= 6) { 
      if(!resizeMode) { 
       setCursor(Qt::SizeFDiagCursor); 
       resizeMode = true; 
      } 
     } else { 
      if(resizeMode) { 
       setCursor(Qt::SizeAllCursor); 
       resizeMode = false; 
      } 
     } 
    } 
} 

void TextPopup::mouseReleaseEvent(QMouseEvent* event) 
{ 
    offset = QPoint(); 
    QWidget::mouseReleaseEvent(event); 
} 

我有这几个问题。首先,我猜想有一个更好的方法来做到这一点。更重要的是,我想在右下角调整大小符号,如this image(取自上面提到的帖子)。任何建议为达到这个目的?

enter image description here

+0

我敢肯定你意识到这一点,但其他人读这可能不是。关于Qt无边界窗口的文档指出:“用户不能通过窗口系统移动或调整无边界窗口的大小。” – cgmb 2011-04-22 05:24:06

回答

6

您可以通过(或直接在QtCreator窗体设计器)调用了QDialog的或QStatusBar的功能setSizeGripEnabled添加调整大小的抓地力。

对于自定义部件最简单的方法可能是使用QSizeGrip。我没有自己使用它,但你可以检查git上的Qt源代码QStatusBarQDialog

+0

嘿谢谢,这似乎工作。我在QSizeGrip类中遇到了一些问题,但至少它提供了这些功能。 – buck 2011-04-24 17:34:22

1

您可以在布局中使用QSizeGrip窗口小部件中:

myWidget->setWindowFlags(Qt::SubWindow); 

QSizeGrip * sizeGrip = new QSizeGrip(myWidget); 

QGridLayout * layout = new QGridLayout(myWidget); 
layout->addWidget(sizeGrip, 0,0,1,1,Qt::AlignBottom | Qt::AlignRight); 

QSizeGrip类提供了调整顶级窗口大小调整手柄。当您设置小部件标志Qt::SubWindow时,用户可以使用大小控制来调整它的大小。

4

如果你不希望QSizeGrip你可以看看这个解决方案:

frameless.h

#pragma once 
#include <QtWidgets/QWidget> 
#include <QtWidgets/QRubberBand> 
#include <QtCore/QObject> 
#include <QtCore/QEvent> 
#include <QtCore/QRect> 
#include <QtCore/QPoint> 
#include <QtCore/Qt> 
#include <QtGui/QHoverEvent> 
#include <QtGui/QMouseEvent> 

class FrameLess : public QObject { 
    Q_OBJECT 

public: 
    enum Edge { 
     None = 0x0, 
     Left = 0x1, 
     Top = 0x2, 
     Right = 0x4, 
     Bottom = 0x8, 
     TopLeft = 0x10, 
     TopRight = 0x20, 
     BottomLeft = 0x40, 
     BottomRight = 0x80, 
    }; 
    Q_ENUM(Edge); 
    Q_DECLARE_FLAGS(Edges, Edge); 

    FrameLess(QWidget *target); 

    void setBorderWidth(int w) { 
     _borderWidth = w; 
    } 
    int borderWidth() const { 
     return _borderWidth; 
    } 

protected: 
    bool eventFilter(QObject *o, QEvent *e) override; 
    void mouseHover(QHoverEvent*); 
    void mouseLeave(QEvent*); 
    void mousePress(QMouseEvent*); 
    void mouseRealese(QMouseEvent*); 
    void mouseMove(QMouseEvent*); 
    void updateCursorShape(const QPoint &); 
    void calculateCursorPosition(const QPoint &, const QRect &, Edges &); 

private: 
    QWidget *_target = nullptr; 
    QRubberBand *_rubberband = nullptr; 
    bool _cursorchanged; 
    bool _leftButtonPressed; 
    Edges _mousePress = Edge::None; 
    Edges _mouseMove = Edge::None; 
    int _borderWidth; 

    QPoint _dragPos; 
    bool _dragStart = false; 
}; 

Q_DECLARE_OPERATORS_FOR_FLAGS(FrameLess::Edges); 

frameless.cpp

#include "frameless.h" 

FrameLess::FrameLess(QWidget *target) : 
    _target(target), 
    _cursorchanged(false), 
    _leftButtonPressed(false), 
    _borderWidth(5), 
    _dragPos(QPoint()) 
{ 
    _target->setMouseTracking(true); 
    _target->setWindowFlags(Qt::FramelessWindowHint); 
    _target->setAttribute(Qt::WA_Hover); 
    _target->installEventFilter(this); 
    _rubberband = new QRubberBand(QRubberBand::Rectangle); 
} 

bool FrameLess::eventFilter(QObject *o, QEvent*e) { 
    if (e->type() == QEvent::MouseMove || 
     e->type() == QEvent::HoverMove || 
     e->type() == QEvent::Leave || 
     e->type() == QEvent::MouseButtonPress || 
     e->type() == QEvent::MouseButtonRelease) { 

     switch (e->type()) { 
     case QEvent::MouseMove: 
      mouseMove(static_cast<QMouseEvent*>(e)); 
      return true; 
      break; 
     case QEvent::HoverMove: 
      mouseHover(static_cast<QHoverEvent*>(e)); 
      return true; 
      break; 
     case QEvent::Leave: 
      mouseLeave(e); 
      return true; 
      break; 
     case QEvent::MouseButtonPress: 
      mousePress(static_cast<QMouseEvent*>(e)); 
      return true; 
      break; 
     case QEvent::MouseButtonRelease: 
      mouseRealese(static_cast<QMouseEvent*>(e)); 
      return true; 
      break; 
     } 
    } 
    else { 
     return _target->eventFilter(o, e); 
    } 
} 

void FrameLess::mouseHover(QHoverEvent *e) { 
    updateCursorShape(_target->mapToGlobal(e->pos())); 
} 

void FrameLess::mouseLeave(QEvent *e) { 
    if (!_leftButtonPressed) { 
     _target->unsetCursor(); 
    } 
} 

void FrameLess::mousePress(QMouseEvent *e) { 
    if (e->button() & Qt::LeftButton) { 
     _leftButtonPressed = true; 
     calculateCursorPosition(e->globalPos(), _target->frameGeometry(), _mousePress); 
     if (!_mousePress.testFlag(Edge::None)) { 
      _rubberband->setGeometry(_target->frameGeometry()); 
     } 
     if (_target->rect().marginsRemoved(QMargins(borderWidth(), borderWidth(), borderWidth(), borderWidth())).contains(e->pos())) { 
      _dragStart = true; 
      _dragPos = e->pos(); 
     } 
    } 
} 

void FrameLess::mouseRealese(QMouseEvent *e) { 
    if (e->button() & Qt::LeftButton) { 
     _leftButtonPressed = false; 
     _dragStart = false; 
    } 
} 

void FrameLess::mouseMove(QMouseEvent *e) { 
    if (_leftButtonPressed) { 
     if (_dragStart) { 
      _target->move(_target->frameGeometry().topLeft() + (e->pos() - _dragPos)); 
     } 

     if (!_mousePress.testFlag(Edge::None)) { 
      int left = _rubberband->frameGeometry().left(); 
      int top = _rubberband->frameGeometry().top(); 
      int right = _rubberband->frameGeometry().right(); 
      int bottom = _rubberband->frameGeometry().bottom(); 
      switch (_mousePress) { 
      case Edge::Top: 
       top = e->globalPos().y(); 
       break; 
      case Edge::Bottom: 
       bottom = e->globalPos().y(); 
       break; 
      case Edge::Left: 
       left = e->globalPos().x(); 
       break; 
      case Edge::Right: 
       right = e->globalPos().x(); 
       break; 
      case Edge::TopLeft: 
       top = e->globalPos().y(); 
       left = e->globalPos().x(); 
       break; 
      case Edge::TopRight: 
       right = e->globalPos().x(); 
       top = e->globalPos().y(); 
       break; 
      case Edge::BottomLeft: 
       bottom = e->globalPos().y(); 
       left = e->globalPos().x(); 
       break; 
      case Edge::BottomRight: 
       bottom = e->globalPos().y(); 
       right = e->globalPos().x(); 
       break; 
      } 
      QRect newRect(QPoint(left, top), QPoint(right, bottom)); 
      if (newRect.width() < _target->minimumWidth()) { 
       left = _target->frameGeometry().x(); 
      } 
      else if (newRect.height() < _target->minimumHeight()) { 
       top = _target->frameGeometry().y(); 
      } 
      _target->setGeometry(QRect(QPoint(left, top), QPoint(right, bottom))); 
      _rubberband->setGeometry(QRect(QPoint(left, top), QPoint(right, bottom))); 
     } 
    } 
    else { 
     updateCursorShape(e->globalPos()); 
    } 
} 

void FrameLess::updateCursorShape(const QPoint &pos) { 
    if (_target->isFullScreen() || _target->isMaximized()) { 
     if (_cursorchanged) { 
      _target->unsetCursor(); 
     } 
     return; 
    } 
    if (!_leftButtonPressed) { 
     calculateCursorPosition(pos, _target->frameGeometry(), _mouseMove); 
     _cursorchanged = true; 
     if (_mouseMove.testFlag(Edge::Top) || _mouseMove.testFlag(Edge::Bottom)) { 
      _target->setCursor(Qt::SizeVerCursor); 
     } 
     else if (_mouseMove.testFlag(Edge::Left) || _mouseMove.testFlag(Edge::Right)) { 
      _target->setCursor(Qt::SizeHorCursor); 
     } 
     else if (_mouseMove.testFlag(Edge::TopLeft) || _mouseMove.testFlag(Edge::BottomRight)) { 
      _target->setCursor(Qt::SizeFDiagCursor); 
     } 
     else if (_mouseMove.testFlag(Edge::TopRight) || _mouseMove.testFlag(Edge::BottomLeft)) { 
      _target->setCursor(Qt::SizeBDiagCursor); 
     } 
     else if (_cursorchanged) { 
      _target->unsetCursor(); 
      _cursorchanged = false; 
     } 
    } 
} 

void FrameLess::calculateCursorPosition(const QPoint &pos, const QRect &framerect, Edges &_edge) { 
    bool onLeft = pos.x() >= framerect.x() - _borderWidth && pos.x() <= framerect.x() + _borderWidth && 
     pos.y() <= framerect.y() + framerect.height() - _borderWidth && pos.y() >= framerect.y() + _borderWidth; 

    bool onRight = pos.x() >= framerect.x() + framerect.width() - _borderWidth && pos.x() <= framerect.x() + framerect.width() && 
     pos.y() >= framerect.y() + _borderWidth && pos.y() <= framerect.y() + framerect.height() - _borderWidth; 

    bool onBottom = pos.x() >= framerect.x() + _borderWidth && pos.x() <= framerect.x() + framerect.width() - _borderWidth && 
     pos.y() >= framerect.y() + framerect.height() - _borderWidth && pos.y() <= framerect.y() + framerect.height(); 

    bool onTop = pos.x() >= framerect.x() + _borderWidth && pos.x() <= framerect.x() + framerect.width() - _borderWidth && 
     pos.y() >= framerect.y() && pos.y() <= framerect.y() + _borderWidth; 

    bool onBottomLeft = pos.x() <= framerect.x() + _borderWidth && pos.x() >= framerect.x() && 
     pos.y() <= framerect.y() + framerect.height() && pos.y() >= framerect.y() + framerect.height() - _borderWidth; 

    bool onBottomRight = pos.x() >= framerect.x() + framerect.width() - _borderWidth && pos.x() <= framerect.x() + framerect.width() && 
     pos.y() >= framerect.y() + framerect.height() - _borderWidth && pos.y() <= framerect.y() + framerect.height(); 

    bool onTopRight = pos.x() >= framerect.x() + framerect.width() - _borderWidth && pos.x() <= framerect.x() + framerect.width() && 
     pos.y() >= framerect.y() && pos.y() <= framerect.y() + _borderWidth; 

    bool onTopLeft = pos.x() >= framerect.x() && pos.x() <= framerect.x() + _borderWidth && 
     pos.y() >= framerect.y() && pos.y() <= framerect.y() + _borderWidth; 

    if (onLeft) { 
     _edge = Left; 
    } 
    else if (onRight) { 
     _edge = Right; 
    } 
    else if (onBottom) { 
     _edge = Bottom; 
    } 
    else if (onTop) { 
     _edge = Top; 
    } 
    else if (onBottomLeft) { 
     _edge = BottomLeft; 
    } 
    else if (onBottomRight) { 
     _edge = BottomRight; 
    } 
    else if (onTopRight) { 
     _edge = TopRight; 
    } 
    else if (onTopLeft) { 
     _edge = TopLeft; 
    } 
    else { 
     _edge = None; 
    } 
} 

而只是创建一个实例,并把你的QWidget

#include "frameless.h" 
#include <QtWidgets/qapplication.h> 

int main(int argc, char *argv[]) { 
    QApplication a(argc, argv); 
    QWidget *widget = new QWidget; 
    FrameLess f(widget); 
    widget->show(); 
    return a.exec(); 
}