Qt: изменяемое и подвижное главное окно без строки заголовка
Мне нужно нарисовать Qt-окно без строки заголовка. Как правило, это может быть легко, просто установив CustomizeWindowHint
атрибут окна. Но тогда окно имеет фиксированный размер и положение.
Мне нужно подвижное окно с изменяемым размером. В этом посте показано, как перемещать окно вручную, поэтому мне интересно, есть ли способ, по крайней мере, сохранить размеры границ изменяемого размера.
Конечно, я также могу изменить размер окна вручную, но я ожидаю, что окна будут перепрыгивать и много странного поведения, поэтому я надеюсь, что есть способ использовать существующую функциональность
2 ответа
Из документов на Qt::CustomizeWindowHint
:
Этот флаг должен быть установлен, чтобы разрешить изменение флагов WindowTitleHint, WindowSystemMenuHint, WindowMinimizeButtonHint, WindowMaximizeButtonHint и WindowCloseButtonHint.
В принципе, Qt::CustomizeWindowHint
не предназначен для использования без других подсказок в строке заголовка.
использование Qt::FramelessWindowHint
в сочетании с повторной реализацией какого-либо события для перетаскивания (см. решение вашего другого вопроса). Вы можете получить контроль размера, чтобы показать примерно так:
auto statusBarWidget = statusBar();
statusBarWidget->setSizeGripEnabled(true);
Возможно, вам придется поработать с ручкой размера и строкой состояния, чтобы работать с установленным флагом безрамного окна.
Редактировать: поскольку вы не используете строку состояния, добавьте "горячую точку" в ваш центральный виджет, чтобы начать изменение размера вместо перемещения, т.е. проверьте, находится ли мышь в правом нижнем углу окна, и установите курсор соответствующим образом. Если они нажмут, начните изменять размер, а не двигать Все это может быть сделано путем переопределения событий мыши.
Редактировать: я понял
Есть некоторые прыжки, но это рабочее руководство по изменению размера / перемещению окна без строки заголовка, которое я реализовал для своего личного проекта:
//Below two methods partially from Qt Shaped Clock example
void MainWindow::mousePressEvent(QMouseEvent *event){
//From Qt Documentation:
//Reason why pos() wasn't working is because the global
//position at time of event may be very different
//This is why the mpos = event->pos(); line before was
//possibly causing jumping behavior
if (event->button() == Qt::LeftButton){
//Coordinates have been mapped such that the mouse position is relative to the
//upper left of the main window
mpos = event->globalPos() - frameGeometry().topLeft();
//At the moment of mouse click, capture global position and
//lock the size of window for resizing
global_mpos = event->globalPos();
storeWidth = this->width();
storeHeight= this->height();
event->accept();
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event){
//mapped mouse relative to upper left of window
rs_mpos=event->globalPos()-frameGeometry().topLeft();//general position tracker for resizing
QTextStream out(stdout);
//How much of the corner is considered a "resizing zone"
//I was experiencing jumping behavior with rs_size is 10 so
//I recommend rs_size=50
int rs_size=50;
//Big if statement checks if your mouse is in the upper left,
//upper right, lower left, and lower right
if ( (abs(rs_mpos.x()) < rs_size && abs(rs_mpos.y()) < rs_size) ||
(abs(rs_mpos.x()) > this->width()-rs_size && abs(rs_mpos.y()) <rs_size) ||
(abs(rs_mpos.x()) < rs_size && abs(rs_mpos.y())> this->height()-rs_size) ||
(abs(rs_mpos.x()) > this->width()-rs_size && abs(rs_mpos.y())> this->height()-rs_size)
){
//Below for debugging
/*
out << rs_mpos.x() << " , " << rs_mpos.y() << "\n";
out << "window: " << this->width() << " , " << this->height() << "\n";
out << "globalpos: " << event->globalPos().x() << " , "
<< event->globalPos().y() << "\n";
*/
//Use 2x2 matrix to adjust how much you are resizing and how much you
//are moving. Since the default coordinates are relative to upper left
//You cannot just have one way of resizing and moving the window.
//It will depend on which corner you are referring to
//adjXfac and adjYfac are for calculating the difference between your
//current mouse position and where your mouse was when you clicked.
//With respect to the upper left corner, moving your mouse to the right
//is an increase in coordinates, moving mouse to the bottom is increase
//etc.
//However, with other corners this is not so and since I chose to subtract
//This difference at the end for resizing, adjXfac and adjYfac should be
//1 or -1 depending on whether moving the mouse in the x or y directions
//increases or decreases the coordinates respectively.
//transXfac transYfac is to move the window over. Resizing the window does not
//automatically pull the window back toward your mouse. This is what
//transfac is for (translate window in some direction). It will be either
//0 or 1 depending on whether you need to translate in that direction.
//Initiate matrix
int adjXfac=0;
int adjYfac=0;
int transXfac=0;
int transYfac=0;
//Upper left corner section
if ( (abs(rs_mpos.x()) < rs_size && abs(rs_mpos.y()) < rs_size)){
this->setCursor(Qt::SizeFDiagCursor);
//Upper left. No flipping of axis, no translating window
adjXfac=1;
adjYfac=1;
transXfac=0;
transYfac=0;
}
//Upper right corner section
else if(abs(rs_mpos.x()) > this->width()-rs_size &&
abs(rs_mpos.y()) <rs_size){
this->setCursor(Qt::SizeBDiagCursor);
//upper right. Flip displacements in mouse movement across x axis
//and translate window left toward the mouse
adjXfac=-1;
adjYfac=1;
transXfac = 1;
transYfac =0;
}
//Lower left corner section
else if(abs(rs_mpos.x()) < rs_size &&
abs(rs_mpos.y())> this->height()-rs_size){
this->setCursor(Qt::SizeBDiagCursor);
//lower left. Flip displacements in mouse movement across y axis
//and translate window up toward mouse
adjXfac=1;
adjYfac=-1;
transXfac=0;
transYfac=1;
}
//Lower right corner section
else if(abs(rs_mpos.x()) > this->width()-rs_size &&
abs(rs_mpos.y())> this->height()-rs_size){
this->setCursor(Qt::SizeFDiagCursor);
//lower right. Flip mouse displacements on both axis and
//translate in both x and y direction left and up toward mouse.
adjXfac=-1;
adjYfac=-1;
transXfac=1;
transYfac=1;
}
if (event->buttons()==Qt::LeftButton ){
//Calculation of displacement. adjXfac=1 means normal displacement
//adjXfac=-1 means flip over axis
int adjXdiff = adjXfac*(event->globalPos().x() - global_mpos.x());
int adjYdiff = adjYfac*(event->globalPos().y() - global_mpos.y());
//if transfac is 1 then movepoint of mouse is translated
QPoint movePoint(mpos.x() - transXfac*adjXdiff, mpos.y()-transYfac*adjYdiff);
move(event->globalPos()-movePoint);
resize(storeWidth-adjXdiff, storeHeight-adjYdiff);
event->accept();
}
}
//in any move event if it is not in a resize region use the default cursor
else{
this->setCursor(Qt::ArrowCursor);
//simple move section
if (event->buttons()==Qt::LeftButton &&
resizeZone==false){
move(event->globalPos() - mpos);
event->accept();
}
}
}
Установите это в своем заголовочном файле
private:
QPoint mpos; //For dragging, relative mouse position to upper left
QPoint global_mpos; //For resizing, global mouse position at mouse click
QPoint rs_mpos; //for resizing
int storeWidth; //fix window size at mouseclick for resizing
int storeHeight;