[SOLVED] Resizable (by mouse) QFrame



  • Hi,
    I'm trying to implement a QFrame that can be resized and dragged around using the mouse. Having googled around a bit and found nothing, I started to implement the thing a bit low-level. Dragging around is working, however resizing doesn't really work. Now before I put too much effort into that: Is there another way I could go? Maybe Qt does offer a widget that does just what I need but somehow I missed it?
    Here's what I have up to now (a complete demo project can be uploaded if it helps):

    EDIT: code removed, see my solution in later post



  • Who is the parent to the resizableFrame? Is it in a layout, or maybe a central widget in a QMainWindow?



  • I'm currently developing it as the central widget in a QMainWindow but the usecase later will have another (not resizable) QFrame as parent. That one will be used in some kind of layout I yet need to think about :)
    The inner (resizable) frames are not meant to be moved outside their parent QFrame.

    Does it make any difference who/what the parent-object is?



  • [quote author="kripton" date="1358957005"]Does it make any difference who/what the parent-object is?[/quote]

    No it doesn't, it just gives me an idea of how you were using the widget. Setting the resizableFrame as a central widget actually puts the widget into a layout in the main window. Calling setGeometry on a widget in a layout is counter productive because the layout system will fight with you.

    You can try calling updateGeometry(), and then in the sizeHint() function return a size bigger than it currently is to force it to grow.



  • Here's how it's solved (not actually hard, just needs a bit of thinking):
    [code]#include "resizableframe.h"

    #include <QDebug>

    ResizableFrame::ResizableFrame(QWidget *parent) :
    QFrame(parent)
    {
    setMouseTracking(true);
    }

    ResizableFrame::~ResizableFrame()
    {
    }

    void ResizableFrame::mousePressEvent(QMouseEvent *event)
    {
    if (event->button() == Qt::LeftButton) {
    dragStartPosition = event->pos();
    dragStartGeometry = geometry();
    }
    }

    void ResizableFrame::mouseMoveEvent(QMouseEvent *event)
    {
    if (!(event->buttons() & Qt::LeftButton)) {
    // No drag, just change the cursor and return

        if (event->x() <= 3 && event->y() <= 3) {
            startPos = topleft;
            setCursor(Qt::SizeFDiagCursor);
        } else if (event->x() <= 3 && event->y() >= height() - 3) {
            startPos = bottomleft;
            setCursor(Qt::SizeBDiagCursor);
        } else if (event->x() >= width() - 3 && event->y() <= 3) {
            startPos = topright;
            setCursor(Qt::SizeBDiagCursor);
        } else if (event->x() >= width() - 3 && event->y() >= height() - 3) {
            startPos = bottomright;
            setCursor(Qt::SizeFDiagCursor);
        } else if (event->x() <= 3) {
            startPos = left;
            setCursor(Qt::SizeHorCursor);
        } else if (event->x() >= width() - 3) {
            startPos = right;
            setCursor(Qt::SizeHorCursor);
        } else if (event->y() <= 3) {
            startPos = top;
            setCursor(Qt::SizeVerCursor);
        } else if (event->y() >= height() - 3) {
            startPos = bottom;
            setCursor(Qt::SizeVerCursor);
        } else {
            startPos = move;
            setCursor(Qt::SizeAllCursor);
        }
        return;
    }
    
    switch (startPos) {
    case topleft:
        setGeometry(dragStartGeometry.left() - (dragStartPosition.x() - event->x()),
                    dragStartGeometry.top() - (dragStartPosition.y() - event->y()),
                    dragStartGeometry.width() + (dragStartPosition.x() - event->x()),
                    height() + (dragStartPosition.y() - event->y()));
        dragStartGeometry = geometry();
        break;
    
    case bottomleft:
        setGeometry(dragStartGeometry.left() - (dragStartPosition.x() - event->x()),
                    dragStartGeometry.top(),
                    dragStartGeometry.width() + (dragStartPosition.x() - event->x()),
                    event->y());
        dragStartGeometry = geometry();
        break;
    
    case topright:
        setGeometry(dragStartGeometry.left(),
                    dragStartGeometry.top() - (dragStartPosition.y() - event->y()),
                    event->x(),
                    height() + (dragStartPosition.y() - event->y()));
        dragStartGeometry = geometry();
        break;
    
    case bottomright:
        setGeometry(dragStartGeometry.left(),
                    dragStartGeometry.top(),
                    event->x(),
                    event->y());
        break;
    
    case left:
        setGeometry(dragStartGeometry.left() - (dragStartPosition.x() - event->x()),
                    dragStartGeometry.top(),
                    dragStartGeometry.width() + (dragStartPosition.x() - event->x()),
                    height());
        dragStartGeometry = geometry();
        break;
    
    case right:
        setGeometry(dragStartGeometry.left(),
                    dragStartGeometry.top(),
                    event->x(),
                    height());
        break;
    
    case top:
        setGeometry(dragStartGeometry.left(),
                    dragStartGeometry.top() - (dragStartPosition.y() - event->y()),
                    dragStartGeometry.width(),
                    height() + (dragStartPosition.y() - event->y()));
        dragStartGeometry = geometry();
        break;
    
    case bottom:
        setGeometry(dragStartGeometry.left(),
                    dragStartGeometry.top(),
                    width(),
                    event->y());
        break;
    
    case move:
        setGeometry(dragStartGeometry.left() - (dragStartPosition.x() - event->x()),
                    dragStartGeometry.top() - (dragStartPosition.y() - event->y()),
                    width(),
                    height());
        dragStartGeometry = geometry();
        break;
    
    default:
        break;
    }
    

    }
    [/code]



  • Thanks for posting reply for sharing purpose.
    I tried using it, stuck at datatype of "startPos". Can you mention that?



  • True, you can't know that one. For completeness, here's the resizableframe.h file:
    [code]
    #ifndef RESIZABLEFRAME_H
    #define RESIZABLEFRAME_H

    #include <QFrame>
    #include <QMouseEvent>

    class ResizableFrame : public QFrame
    {
    Q_OBJECT

    public:
    explicit ResizableFrame(QWidget *parent = 0);
    ~ResizableFrame();

    enum startPositions {topleft, left, bottomleft, bottom, bottomright, right, topright, top, move} startPositions;
    

    protected:
    void mousePressEvent(QMouseEvent event);
    void mouseMoveEvent(QMouseEvent
    event);

    private:
    QPoint dragStartPosition;
    QRect dragStartGeometry;
    enum startPositions startPos;
    };

    #endif // RESIZABLEFRAME_H
    [/code]


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.