Создал окно без рамки. Сейчас написал код который работает только при увеличении размеров окна, если пытаться уменьшить то получается белиберда или окно вовсе крашится. Возможно неправильно просчитываю...
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
//События для resize окна
if(acceptDrag)
{
if(event->type() == QEvent::MouseButtonPress && Border != null)
{
QMouseEvent* mouse_event = dynamic_cast<QMouseEvent*>(event);
if (mouse_event->button() & Qt::LeftButton)
{
dragStartPosition = mouse_event->pos();
dragStartGeometry = geometry();
StartResize = true;
return false;
}
}
else if(event->type() == QEvent::MouseMove)
{
QMouseEvent* mouse_event = dynamic_cast<QMouseEvent*>(event);
if(!(mouse_event->button() & Qt::LeftButton))
{
if(mouse_event->x() <= 3 && mouse_event->y() <= 3)
{
setCursor(Qt::SizeFDiagCursor);
Border = topleft;
}
else if(mouse_event->x() >= width() - 3 && mouse_event->y() <= 3)
{
setCursor(Qt::SizeBDiagCursor);
Border = topright;
}
else if(mouse_event->x() <= 3 && mouse_event->y() >= height() - 3)
{
setCursor(Qt::SizeBDiagCursor);
Border = bottomleft;
}
else if(mouse_event->x() >= width() - 3 && mouse_event->y() >= height() - 3)
{
setCursor(Qt::SizeFDiagCursor);
Border = bottomright;
}
else if(mouse_event->x() <= 3)
{
setCursor(Qt::SizeHorCursor);
Border = left;
}
else if(mouse_event->x() >= width() - 3)
{
setCursor(Qt::SizeHorCursor);
Border = right;
}
else if(mouse_event->y() <= 3)
{
setCursor(Qt::SizeVerCursor);
Border = top;
}
else if(mouse_event->y() >= height() - 3 && mouse_event->x() <= width())
{
setCursor(Qt::SizeVerCursor);
Border = bottom;
}
else {
unsetCursor();
Border = null;
}
}
if(StartResize)
{
switch(Border)
{
case topleft:
setGeometry(dragStartGeometry.left() - (dragStartPosition.x() - mouse_event->x()),
dragStartGeometry.top() - (dragStartPosition.y() - mouse_event->y()),
dragStartGeometry.width() + (dragStartPosition.x() - mouse_event->x()),
height() + (dragStartPosition.y() - mouse_event->y()));
dragStartGeometry = geometry();
break;
case bottomleft:
setGeometry(dragStartGeometry.left() - (dragStartPosition.x() - mouse_event->x()),
dragStartGeometry.top(),
dragStartGeometry.width() + (dragStartPosition.x() - mouse_event->x()),
mouse_event->y());
dragStartGeometry = geometry();
break;
case topright:
setGeometry(dragStartGeometry.left(),
dragStartGeometry.top() - (dragStartPosition.y() - mouse_event->y()),
mouse_event->x(),
height() + (dragStartPosition.y() - mouse_event->y()));
dragStartGeometry = geometry();
break;
case bottomright:
setGeometry(dragStartGeometry.left(),
dragStartGeometry.top(),
mouse_event->x(),
mouse_event->y());
break;
case left:
setGeometry(dragStartGeometry.left() - (dragStartPosition.x() - mouse_event->x()),
dragStartGeometry.top(),
dragStartGeometry.width() + (dragStartPosition.x() - mouse_event->x()),
height());
dragStartGeometry = geometry();
break;
case right:
setGeometry(dragStartGeometry.left(),
dragStartGeometry.top(),
mouse_event->x(),
height());
break;
case top:
setGeometry(dragStartGeometry.left(),
dragStartGeometry.top() - (dragStartPosition.y() - mouse_event->y()),
dragStartGeometry.width(),
height() + (dragStartPosition.y() - mouse_event->y()));
dragStartGeometry = geometry();
break;
case bottom:
setGeometry(dragStartGeometry.left(),
dragStartGeometry.top(),
width(),
mouse_event->y());
break;
case null:
break;
}
}
return false;
}
}
if(event->type() == QEvent::MouseButtonRelease)
StartResize = false;
return false;
}
В заголовке MainWindow описаны:
bool eventFilter(QObject *object, QEvent *event);
enum sBorder{topleft, left, bottomleft, bottom,
bottomright, right, topright, top, null} Border = null;
bool StartResize = false;
QPoint dragStartPosition;
QRect dragStartGeometry;
В конструкторе MainWindow:
setMouseTracking(true);
installEventFilter(this);
Заранее спасибо! Готов выслушать любые идеи)
Создадим пустой ui
диалога. В качестве границ диалога будем использовать QLabel
'лы. Для каждой стороны и угла соотвественно Top, Left, Bottom, Rigth, TopLeft, TopRight, BottomLeft, BottomRight
. Минимальный размер угловых лэйблов установим 4х4
, остальных 2x2
. По центру создать QWidget
с именем central
. Скомпоновать их следующим образом.
Всем компоновкам выставить margin
и spacing
в 0
. В основной компоновке свойству соотношения размеров виджетов внутри компоновки layoutStretch
выставить 1,1000,1
Далее объявим класс, реализующий нашу ui
.
#include "ui_DialogResizeBase.h"
class ResizeDialogBase : public QDialog, public Ui::DialogResizeBase
{
Q_OBJECT
//отображает курсор в соответствии с QLabel
void setSideCursor(int);
//Вычисляет новый размер
void changeSize(int, QMouseEvent*);
public:
ResizeDialogBase(QWidget* parent = Q_NULLPTR);
bool eventFilter(QObject *watched, QEvent *event);
};
Конструктор
enum {
TOP,
BOTTOM,
RIGHT,
LEFT,
TOP_LEFT,
BOTTOM_RIGHT,
TOP_RIGHT,
BOTTOM_LEFT
};
ResizeDialogBase::
ResizeDialogBase(QWidget *parent):
QDialog (parent)
{
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setWindowFlag(Qt::FramelessWindowHint);
//устанавливаем фильтр событий для каждого QLabel
Top->installEventFilter(this);
Bottom->installEventFilter(this);
Right->installEventFilter(this);
Left->installEventFilter(this);
LefTop->installEventFilter(this);
RightBottom->installEventFilter(this);
RightTop->installEventFilter(this);
LeftBottom->installEventFilter(this);
//Определяем свойство side для идентификации стороны
//можно сделать в дизайнере
Top->setProperty("side", TOP);
Bottom->setProperty("side", BOTTOM);
Right->setProperty("side", RIGHT);
Left->setProperty("side", LEFT);
LefTop->setProperty("side", TOP_LEFT);
RightBottom->setProperty("side", BOTTOM_RIGHT);
RightTop->setProperty("side", TOP_RIGHT);
LeftBottom->setProperty("side", BOTTOM_LEFT);
//Нажата ли левая кнопка мыши
setProperty("pressed", false);
//Обрамление диалога
setStyleSheet("QDialog {\n border: 1px solid red;\n}");
}
Фильтр событий
bool
ResizeDialogBase::
eventFilter(QObject *watched, QEvent *event)
{
switch (event->type()) {
case QEvent::Enter: setSideCursor(watched->property("side").toInt()); break;
case QEvent::Leave: setCursor(Qt::ArrowCursor); break;
case QEvent::MouseButtonPress:
if( static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton)
setProperty("pressed", true); break;
case QEvent::MouseButtonRelease:
if( static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton)
setProperty("pressed", false); break;
case QEvent::MouseMove: changeSize(watched->property("side").toInt(), static_cast<QMouseEvent*>(event)); break;
default: break;
}
return false;
}
Установка курсора
void
ResizeDialogBase::
setSideCursor(int side)
{
switch (side) {
case TOP: case BOTTOM: setCursor(Qt::SizeVerCursor); break;
case RIGHT: case LEFT: setCursor(Qt::SizeHorCursor); break;
case TOP_LEFT: case BOTTOM_RIGHT: setCursor(Qt::SizeFDiagCursor); break;
case TOP_RIGHT:case BOTTOM_LEFT: setCursor(Qt::SizeBDiagCursor); break;
}
}
Изменение размеров диалога
void
ResizeDialogBase::
changeSize(int side, QMouseEvent* event)
{
if(property("pressed").toBool()) {
auto geom = geometry();
auto x = event->globalX();
auto y = event->globalY();
static auto minW = minimumWidth();
static auto minH = minimumHeight();
switch (side) {
case TOP: {
geom.setY(minH < geom.height() ? y : geom.y());
geom.setHeight(geom.height() + (geom.y()-y));
setGeometry(geom);
break;
}
case BOTTOM:
geom.setHeight(geom.height() + event->y());
setGeometry(geom);
break;
case RIGHT:
geom.setWidth(geom.width()+event->x());
setGeometry(geom);
break;
case LEFT: {
geom.setX(minW < geom.width() ? x : geom.x());
geom.setWidth(geom.width()+(geom.x()-x));
setGeometry(geom);
break;
}
case TOP_LEFT: {
geom.setX(minW < geom.width() ? x : geom.x());
geom.setY(minH < geom.height() ? y : geom.y());
geom.setWidth(geom.width()+(geom.x()-x));
geom.setHeight(geom.height() + (geom.y()-y));
setGeometry(geom);
break;
}
case BOTTOM_RIGHT:
geom.setWidth(geom.width()+event->x());
geom.setHeight(geom.height() + event->y());
setGeometry(geom);
break;
case TOP_RIGHT: {
geom.setY(minH < geom.height() ? y : geom.y());
geom.setWidth(geom.width()+event->x());
geom.setHeight(geom.height() + (geom.y()-y));
setGeometry(geom);
break;
}
case BOTTOM_LEFT: {
geom.setX(minW < geom.width() ? x : geom.x());
geom.setWidth(geom.width()+(geom.x()-x));
geom.setHeight(geom.height() + event->y());
setGeometry(geom);
break;
}
}
}
}
Можно использовать как базовый класс для кастомных диалогов, требующих изменения размеров.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
имеется таблица,необходимо было сделать ввод в ячейки только double:
мне необходимо многопоточно обработать элементы std::mapc++ 17 для это есть for_each parallel, но я работаю на C++ 14
На странице нужно поместить два дива рядом в один контейнерКаждый див имеет фиксированную ширину, но правый див может скрываться и нужно,...