qt获取控件位置大小异常

366 阅读3分钟

在这里插入图片描述
在qt界面上放了一个QGraphicsView控件,功能上需要获取这个控件的大小。
在构造函数内,通过下面代码获取QGraphicsView的位置大小:

ui->graphicsView->rect();

一开始没有设置界面的布局的时候,完全没问题,但将布局改为垂直布局或者水平布局的时候就发现获取到的控件大小不对。
在这里插入图片描述
界面初始化之后的大小是778x553,但构造函数里拿到的大小是100x30,显然不对!

后来想到重写界面的resizeEvent事件来获取,结果还是不行。
后来想着哪个事件是界面初始化完成之后触发的,想来想去还是通过写一个计时器来实现吧,在构造函数里加上下面的代码:

m_Timer = new QTimer(this);
connect(m_Timer,&QTimer::timeout,this,&MainWindow::timerOut);
m_Timer->start(50);

写一个timerOut()函数来接收m_Timer的timeout事件

void MainWindow::timerOut()
{
    m_Timer->stop();
    qDebug()<<"graphicsView size after timerOut:"<<ui->graphicsView->rect();
}

测试结果如下,可以看到在构造函数执行完成50ms之后,再获取QGraphicsView控件位置大小就准确了:
在这里插入图片描述

比如我的例程类如下:

#include "Include/BaseDesign/maskdlg.h"
#include "ui_maskdlg.h"
#pragma execution_character_set("utf-8")
MaskDlg::MaskDlg(QWidget *parent,BaseDialog* MasterQW, QImage img,QBitmap bitmap, QColor color) :
    QDialog(parent),
    m_Image(nullptr),
    m_graphicCaliperItem(nullptr),
    m_nBrushType(1),
    m_bErase(false),
    m_pColorDialog(nullptr),
    labelColor(nullptr),
    ui(new Ui::MaskDlg)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::Widget|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);
    QString strLoginName = tr("自定义掩膜");
    m_pTitleBar = new CusTitleBar(this,strLoginName,false);
    ui->horizontalLayout_3->addWidget(m_pTitleBar);
    this->setAttribute(Qt::WA_StyledBackground,true);
    QFile iFile(":/ParaDlg.css");
    if (iFile.open(QFile::ReadOnly)) {
        this->setStyleSheet(iFile.readAll());
        iFile.close();
    }
//    ui->actionOpenPic->setData(1);//打开文件
//    ui->actionAddMask->setData(2);//添加遮罩
//    connect(ui->actionOpenPic,SIGNAL(triggered()), this, SLOT(onMenuEvent()));
//    connect(ui->actionAddMask,SIGNAL(triggered()), this, SLOT(onMenuEvent()));
    m_qgraphicsScene = new CusGraphicsScene;//要用QGraphicsView就必须要有QGraphicsScene搭配着用
    m_qgraphicsScene->setItemIndexMethod(QGraphicsScene::ItemIndexMethod::NoIndex);//防止在removeitem之后,引起QGraphicsScene内部索引异常导致程序崩溃
    //mygraphicview = new CusGraphicView(this);
    ui->mygraphicview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->mygraphicview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->mygraphicview->setBackgroundBrush(QBrush(QColor(240,240,240,255)));
    //QColor color = QColor(255,0,0);
    labelColor = new cusLabel(this);
    labelColor->setMinimumWidth(25);
    labelColor->setMinimumHeight(25);
    labelColor->setMaximumHeight(35);
    labelColor->setMaximumWidth(35);
    connect(labelColor,&cusLabel::mouseReleasedSig,this,&MaskDlg::on_labelColor_clicked);
    m_ImgBase = MasterQW;
    ui->horizontalLayout_Color->addWidget(labelColor);
    QString strSheet ="background-color: rgb(%1, %2, %3);";
    strSheet = strSheet.arg(color.red(),0,10).arg(color.green(),0,10).arg(color.blue(),0,10);
    labelColor->setStyleSheet(strSheet);
    m_imgBackIn = img;
    m_Timer = new QTimer(this);
    connect(m_Timer,&QTimer::timeout,this,&MaskDlg::timerOut);
    m_Timer->start(50);
    if(!bitmap.isNull())
    {
        m_imgMaskIn = bitmap;
    }
}
MaskDlg::~MaskDlg()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        m_qgraphicsScene->removeItem(m_graphicCaliperItem);
        delete m_graphicCaliperItem;
        m_graphicCaliperItem =nullptr;
    }
    if(m_Image!=nullptr)
    {
        m_qgraphicsScene->removeItem(m_Image);
        delete m_Image;//m_graphicCaliperItem的parentItem是m_Image,所以delete m_Image的时候也会delete m_graphicCaliperItem
        m_Image = nullptr;
    }
    if(m_qgraphicsScene!=nullptr)
    {
        m_qgraphicsScene->clear();
        delete m_qgraphicsScene;
        m_qgraphicsScene = nullptr;
    }
    if(m_pTitleBar!=nullptr)
    {
        delete m_pTitleBar;
        m_pTitleBar = nullptr;
    }
    if(m_Timer!=nullptr)
    {
        delete m_Timer;
        m_Timer = nullptr;
    }
//    if(labelColor!=nullptr)
//    {
//        delete labelColor;
//        labelColor = nullptr;
//    }
    delete ui;
}
void MaskDlg::recvShowPicSignal(QImage image)
{
    m_qgraphicsScene->clear();
    m_Image = new ImageWidget(image);//实例化类ImageWidget的对象m_Image,该类继承自QGraphicsItem,是自己写的类
    int nwith = ui->mygraphicview->width();//获取界面控件Graphics View的宽度
    int nheight = ui->mygraphicview->height();//获取界面控件Graphics View的高度
    m_Image->setQGraphicsViewWH(nwith,nheight);//将界面控件Graphics View的width和height传进类m_Image中
    m_Image->setAcceptHoverEvents(true);
    m_qgraphicsScene->addItem(m_Image);//将1QGraphicsItem类对象放进QGraphicsScene中
    ui->mygraphicview->setSceneRect(QRectF(-(nwith/2),-(nheight/2),nwith,nheight));//使视窗的大小固定在原始大小,不会随图片的放大而放大(默认状态下图片放大的时候视窗两边会自动出现滚动条,并且视窗内的视野会变大),防止图片放大后重新缩小的时候视窗太大而不方便观察图片
    ui->mygraphicview->setScene(m_qgraphicsScene);//Sets the current scene to scene. If scene is already being viewed, this function does nothing.
    ui->mygraphicview->setFocus();//将界面的焦点设置到当前Graphics View控件
    ui->mygraphicview->setMouseTracking(true);
    ui->mygraphicview->releaseMouse();
    //添加mask的item
    if(m_graphicCaliperItem==nullptr)
    {
        m_graphicCaliperItem = new CusGraphicCaliperitem();
        m_graphicCaliperItem->setParentImgItem(m_Image);
        m_graphicCaliperItem->m_ShapeType = C_MASK;
        m_graphicCaliperItem->InitRect(QPointF(0,0),m_Image->getPicWidth(),m_Image->getPicHeight());
        if(!m_imgMaskIn.isNull())
        {
            m_graphicCaliperItem->setMaskImg(m_imgMaskIn);
        }
        m_qgraphicsScene->addItem(m_graphicCaliperItem);
    }
}
QBitmap MaskDlg::getMaskImg()
{
    return m_imgMaskOut;
}
void MaskDlg::setMaskIn(QBitmap bitmap)
{
    m_imgMaskIn = bitmap;
}
void MaskDlg::on_spinBoxMaskWidth_valueChanged(int arg1)
{
    if(m_graphicCaliperItem!=nullptr)
    {
        m_graphicCaliperItem->setMaskpenWidth(ui->spinBoxMaskWidth->value());
    }
}
void MaskDlg::on_pushButtonMoveImg_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        //拖动、绘制
        if(ui->pushButtonMoveImg->text()==tr("绘制"))
        {
            ui->pushButtonMoveImg->setText(tr("拖动"));
            m_graphicCaliperItem->setBackImgMovable(true);
        }
        else
        {
            ui->pushButtonMoveImg->setText(tr("绘制"));
            m_graphicCaliperItem->setBackImgMovable(false);
        }
    }
    //●■
}
void MaskDlg::on_pushButtonBrushType_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        if(m_nBrushType==1)
        {
            ui->pushButtonBrushType->setText(tr("矩形"));
            m_nBrushType=2;
            m_graphicCaliperItem->setBrushType(m_nBrushType);
        }
        else
        {
            ui->pushButtonBrushType->setText(tr("圆形"));
            m_nBrushType=1;
            m_graphicCaliperItem->setBrushType(m_nBrushType);
        }
    }
}
void MaskDlg::on_pushButtonErase_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        if(!m_bErase)
        {
            m_bErase = true;
            m_graphicCaliperItem->setErase(m_bErase);
        }
        else
        {
            m_bErase = false;
            m_graphicCaliperItem->setErase(m_bErase);
        }
    }
}
void MaskDlg::on_labelColor_clicked()
{
    if(m_pColorDialog==nullptr)
    {
        m_pColorDialog = new QColorDialog(this);
        connect(m_pColorDialog,SIGNAL(colorSelected(QColor)),this,SLOT(slot_getColor(QColor)));
    }
    m_pColorDialog->exec();
}
void MaskDlg::timerOut()
{
    m_Timer->stop();
    recvShowPicSignal(m_imgBackIn);
}
void MaskDlg::slot_getColor(QColor color)
{
    if(m_graphicCaliperItem!=nullptr)
    {
        QString strSheet ="background-color: rgb(%1, %2, %3);";
        strSheet = strSheet.arg(color.red(),0,10).arg(color.green(),0,10).arg(color.blue(),0,10);
        labelColor->setStyleSheet(strSheet);
        m_graphicCaliperItem->setMaskColor(color);
    }
}
void MaskDlg::on_pushButtonSaveMask_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        QBitmap bitmap = m_graphicCaliperItem->getMaskBitmap();
        QString strFileName = QFileDialog::getSaveFileName(this,tr("Save Picture"),"","PNG(*.png);;JPG(*.jpg);;BMP(*.bmp)");
        if(!strFileName.isNull())
        {
            bitmap.save(strFileName);
        }
    }
}
void MaskDlg::on_pushButton_2_clicked()
{
    reject();
    deleteLater();
}
void MaskDlg::on_pushButton_clicked()
{
    m_imgMaskOut = m_graphicCaliperItem->getMaskBitmap();
    m_ImgBase->MaskEditFinish(m_imgMaskOut);
    accept();
    deleteLater();
}
void MaskDlg::on_pushButtonMaskAll_clicked()
{
    m_graphicCaliperItem->setMaskAllBlack();
}