[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
-
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 returnif (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] -
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_OBJECTpublic:
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]