Qt:无标题栏可调整大小和移动的主窗口

4

我需要绘制一个没有标题栏的Qt窗口。通常,只需设置CustomizeWindowHint窗口属性即可轻松实现。但是这样窗口就有了固定的大小和位置。

我需要一个可移动可调整大小的窗口。这篇帖子展示了如何手动移动窗口,所以我想知道是否有一种方法至少可以保持边框可调整大小。

当然,我也可以手动调整窗口的大小,但我预期会出现跳动窗口和各种奇怪行为,因此我希望有一种方式可以使用现有功能。


你的窗口类型是基于什么的?QMainWindowQDialog - jonspaceharper
QMainWindow - 但我不确定是否可以切换,你有什么建议? - frans
如果您可以不使用工具栏和停靠窗口在主窗口上,您可以使用一个 QDockWidget,然后创建一个自定义的 TitleBarWidget。您可以把它做得很小,并与背景匹配,使其看起来就像没有标题栏。只是一个想法。 - justengel
2个回答

3

Qt::CustomizeWindowHint文档中得知:

必须设置此标志才能更改WindowTitleHint、WindowSystemMenuHint、WindowMinimizeButtonHint、WindowMaximizeButtonHint和WindowCloseButtonHint标志。

基本上,Qt::CustomizeWindowHint不应单独使用。

与某些拖动事件重新实现配合使用,在其中使用Qt::FramelessWindowHint(请参见此解决方案)即可显示大小调整手柄。

auto statusBarWidget = statusBar();
statusBarWidget->setSizeGripEnabled(true);

如果设置了无边框窗口标志,您可能需要使用大小调整手柄和状态栏来处理它。

编辑:由于您没有使用状态栏,请在中央小部件中添加一个“热点”来开始调整大小而不是移动,即检查鼠标是否在窗口的右下角并相应地设置光标。 如果他们单击,则开始调整大小而不是移动。这可以通过重新实现鼠标事件来完成。


+1 因为我可以调整窗口大小而没有标题栏。不幸的是,这样我需要一个状态栏。我的目标是只拥有可调整大小和可移动的中央部件区域。 - frans

1

编辑:我明白了


有一些跳跃的行为,但是这是我为我的个人项目实现的一个没有标题栏的工作手动调整/移动窗口:

//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;

这在我翻译的pyqt5版本中大部分都能正常工作。但是当你把窗口缩小到极小时,算法似乎会失效,导致出现奇怪的调整大小问题...有什么想法吗? - Brad
另外,在最后一个if语句中,resizeZone的目的不太清楚?这里是否缺少一些代码? - Brad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接