QT QGraphicsView QGraphicsWidget中改变窗口大小会导致部分控件丢失

xyconly 2015-03-11 11:08:33
之前搜寻各方帖子,看到说QGraphicsWidget与QWidget在部分功能上存在一些不同,例如窗口旋转缩放等情况下,于是我采用QGraphicsWidget作为基础窗口,并再次基础上进行绘图操作.但在实际操作中发现,当我用鼠标改变整体窗口时,继承自QGraphicsWidget部件会有一定几率不显示,并且没有调用该部件的paint事件?各处查找,没有找到相关原因,在此向各位求教.
以下为码源:
//main.cpp
#include <QtWidgets/QApplication>
#include "lineWidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
lineWidget* w = new lineWidget();
w->resize(800,450);
w->show();
return app.exec();
}
//lineWidget.h
#ifndef lineWidget_h
#define lineWidget_h
#include <QWidget>
#include "GraphicsView.h"
class lineWidget: public QWidget
{
Q_OBJECT
Q_DISABLE_COPY(timeLine)
public:
explicit lineWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
virtual ~lineWidget(){}
//>获取单例
static lineWidget* GetInstance() { return m_pInstance; }
//>获取指针
GraphicsView* GetlineWidgetView() { return m_plineWidgetView; }
private:
static lineWidget* m_pInstance;
GraphicsView* m_plineWidgetView;
};

#endif // lineWidget_h
//lineWidget.cpp
#include "lineWidget.h"
#include <QHBoxLayout>
lineWidget* lineWidget::m_pInstance = nullptr;

lineWidget::lineWidget(QWidget* parent, Qt::WindowFlags f)
: QWidget(parent,f)
{
Q_ASSERT(m_pInstance == nullptr);
m_pInstance = this;
m_plineWidgetView= new GraphicsView(this);
QHBoxLayout* hLay = new QHBoxLayout(this);
hLay->addWidget(m_plineWidgetView);
setLayout(hLay);
}
//GraphicsView.h
#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H

#include <QGraphicsView>
#include "GraphicsScene.h"
class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
explicit GraphicsView(QWidget *parent = 0);
void setscene(GraphicsScene* pCurScene);
GraphicsScene* getscene();
virtual ~GraphicsView(){}
protected:
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *pEvent) override;
private:
//>加载场景
GraphicsScene *m_pCurScene;
};
#endif // GRAPHICSVIEW_H
//GraphicsView.cpp
#include "GraphicsView.h"

GraphicsView::GraphicsView(QWidget *parent)
: QGraphicsView(parent)
{
setWindowFlags(Qt::FramelessWindowHint);
setBackgroundBrush(QColor(62, 62, 66));
QRect r(-width()/2, -height()/2, width(), height());
m_pCurScene = new GraphicsScene(r,this);
setscene(m_pCurScene);
}
void GraphicsView::setscene(GraphicsScene* pCurScene)
{
m_pCurScene = pCurScene;
setScene(pCurScene);
}
GraphicsScene* GraphicsView::getscene()
{
return m_pCurScene;
}
void GraphicsView::mousePressEvent(QMouseEvent *event)
{
return QGraphicsView::mousePressEvent(event);
}
void GraphicsView::mouseMoveEvent(QMouseEvent *pEvent)
{
return QGraphicsView::mouseMoveEvent(pEvent);
}
//GraphicsScene.h
#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H
#include <QGraphicsScene>

class timeWidget;
class GraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
explicit GraphicsScene(const QRectF &sceneRect, QObject *parent = 0);
virtual ~GraphicsScene(){}
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent *pEvent) override;
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *pEvent) override;
private:
timeWidget *m_timeWidget;
};
#endif // GRAPHICSVIEW_H
GraphicsScene.cpp
#include "GraphicsScene.h"
#include "timeWidget.h"
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>

GraphicsScene::GraphicsScene(const QRectF &sceneRect, QObject *parent)
: QGraphicsScene(sceneRect,parent)
{
m_timeWidget = new timeWidget();
addItem(m_timeWidget);
}
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *pEvent)
{
return QGraphicsScene::mousePressEvent(pEvent);
}
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *pEvent)
{
return QGraphicsScene::mouseMoveEvent(pEvent);
}
//timeWidget.h
#ifndef TIMEWIDGET_H
#define TIMEWIDGET_H

#include <QGraphicsWidget>
class Stripe;
class QGraphicsLinearLayout;

class timeWidget : public QGraphicsWidget
{
Q_OBJECT
public:
explicit timeWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
virtual ~timeWidget(){}
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
public slots:
void addStripe(Stripe* stripe = 0);
private:
void CreateLayout();
private:
QGraphicsLinearLayout *m_pLayout;
//> 窗口集合
QList<Stripe*> m_stripies;
};
#endif // TIMEWIDGET_H
//timeWidget.cpp
#include "timeWidget.h"
#include "rulerwidget.h"
#include "CursorItem.h"
#include "Stripe.h"
#include <QGraphicsLinearLayout>
#include <QWidget>
//#include <QGraphicsScene>

timeWidget::timeWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
: QGraphicsWidget(parent,wFlags)
{
CreateLayout();

for( int i = 0 ; i < 5 ; i++)
addStripe();
}

void timeWidget::CreateLayout()
{
m_pLayout = new QGraphicsLinearLayout(Qt::Vertical,this);
m_pLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_pLayout->setContentsMargins(0, 0, 0, 0);
m_pLayout->setSpacing(0);
m_pLayout->setPreferredWidth(0);
setLayout(m_pLayout);
}

void timeWidget::addStripe(Stripe* parent)
{
Stripe *new_stripe;
if( parent )
new_stripe = new Stripe(parent);
else
new_stripe = new Stripe(this);

new_stripe->setZValue(-10);
new_stripe->setBackColor(QColor(37,37,38));
m_pLayout->addItem(new_stripe);
m_stripies << new_stripe;
}

void timeWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QRect rc( widget->rect() );
int stripieHeight(0);
int i(0);
for ( auto stripie : m_stripies )
{
stripie->setOriginHeight( stripieHeight );
stripieHeight += stripie->getHeightPercentage() * rc.height()/2;
i++;
}
}
//Stripe.h
#ifndef TRACK_H
#define TRACK_H

#include "rectWidgetBase.h"
class Stripe : public rectWidgetBase
{
Q_OBJECT
public:
explicit Stripe(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
explicit Stripe(Stripe *parent, Qt::WindowFlags wFlags = 0);
virtual ~Stripe(){}

protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
private:
//>是否为子项
bool m_isChildren;
};

#endif // CURSORITEM_H
//Stripe.cpp
#include "Stripe.h"
#include <QPainter>

Stripe::Stripe(QGraphicsItem *parent,Qt::WindowFlags wFlags)
: rectWidgetBase(parent,wFlags)
, m_isChildren(false)
{
}
Stripe::Stripe(Stripe *parent, Qt::WindowFlags wFlags)
: rectWidgetBase(parent,wFlags)
, m_isChildren(true)
{
}
void Stripe::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
rectWidgetBase::paint(painter,option,widget);
// 绘制顶部边框线
painter->setPen(QColor(0,0,0));
painter->drawLine( rect().topLeft(), rect().topRight() );
}
//rectWidgetBase.h
#ifndef RECTWIDGETBASE_H
#define RECTWIDGETBASE_H

#include <QGraphicsWidget>

class rectWidgetBase : public QGraphicsWidget
{
Q_OBJECT
public:
explicit rectWidgetBase(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
virtual ~rectWidgetBase(){}

//>设置起始高度
inline void setOriginHeight(int originheight){m_originheight = originheight;}
//>设置高度占窗口百分比
inline void setHeightPercentage(double heightPercentage){m_heightPercentage = heightPercentage;}
//>设置宽度占窗口百分比
inline void setWidthPercentage(double widthPercentage){m_widthPercentage = widthPercentage;}
//>设置背景色
inline void setBackColor(QColor color){m_backcolor = color;}

//>获取左上角X坐标
inline int getWidgetLeftTopX(){ return m_leftTopX; }
//>获取左上角Y坐标
inline int getWidgetLeftTopY(){ return m_leftTopY; }
//>获取宽度
inline int getWidgetWidth(){ return m_width; }
//>获取宽度百分比
inline double getWidthPercentage(){ return m_widthPercentage; }
//>获取高度
inline int getWidgetHeight(){ return m_height; }
//>获取条形框高度百分比
inline double getHeightPercentage(){ return m_heightPercentage; }
protected:
//>重绘
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
private:
//>高度占窗口百分比
double m_heightPercentage;
//>初始高度
int m_originheight;
//>高度
int m_height;
//>宽度占窗口百分比
double m_widthPercentage;
//>宽度
int m_width;
//>背景色
QColor m_backcolor;
//>左上角顶点X坐标
int m_leftTopX;
//>左上角顶点Y坐标
int m_leftTopY;
};
#endif // RECTWIDGETBASE_H
//rectWidgetBase.cpp
#include "rectWidgetBase.h"
#include <QWidget>
#include <QPainter>
#include <QGraphicsScene>

rectWidgetBase::rectWidgetBase(QGraphicsItem *parent,Qt::WindowFlags wFlags)
: QGraphicsWidget(parent,wFlags)
, m_leftTopX(0)
, m_leftTopY(0)
, m_width(0)
, m_height(0)
, m_originheight(0)
, m_widthPercentage(0.4)
, m_heightPercentage(0.2)
, m_backcolor(QColor(45,45,48))
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setContentsMargins(0, 0, 0, 0);
setFlags(QGraphicsItem::ItemSendsScenePositionChanges);
}
void rectWidgetBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QRect rc( widget->rect() );
double left = rc.width() / 2 * m_widthPercentage;
m_leftTopX = -rc.width() / 2 + left;
m_leftTopY = -rc.height() / 2 + m_originheight;
m_width = rc.width() - left - 1;
m_height = rc.height() / 2 * m_heightPercentage;
//> 绘制条形框背景
painter->setBrush(m_backcolor);
painter->setPen(Qt::NoPen/*QColor(0, 255, 0)*/);
QRect r(m_leftTopX, m_leftTopY, m_width, m_height);
resize(m_width, m_height);
painter->drawRect( rect() );
setPos(m_leftTopX, m_leftTopY);
if ( scene() )
scene()->update();
}
...全文
1396 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
xyconly 2015-03-11
  • 打赏
  • 举报
回复
已解决,参考socrates中提到的"通过paint重绘需要手动的调用QGraphicsScene的update()函数来刷新界面" http://blog.csdn.net/socrates/article/details/1999845 考虑到可能是由于update时函数响应冲突的问题,故在timeWidget::paint函数中做相应修改(根据QT响应先后顺序,首先响应GraphicsView::paint函数,之后响应timeWidget::paint函数,之后按创建顺序响应,该问题是由于未响应paint函数引起,故在此处设置会导致强制响应各子项的函数即可)
void timeWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 
{
    if( !scene() )
        return QGraphicsWidget::paint(painter,option,widget);

    QRectF rc( scene()->sceneRect() );
    int rulerHeight(0);
    int stripieHeight(0);
    int i(0);
    for ( auto stripie : m_stripies )
    {
        int originHeight = rulerHeight + stripieHeight;
        stripieHeight += stripie->getHeightPercentage() * rc.height()/2;
        stripie->setOriginHeight( originHeight );
        i++;
        stripie->setPos( rc.width()/2 * (stripie->getWidthPercentage()-1), -rc.height()/2 + originHeight );
    }
    scene()->update(rc);
}
另外,由于sceneRect()的大小应实时随窗口改变,故应在GraphicsView中添加paint函数来随时修改大小
 void GraphicsView::paintEvent(QPaintEvent *event)
 {
     QRect r(-width()/2+2, -height()/2+2, width()-4, height()-4);//2为边距,+2使得与QGraphicsItem::paint中的widget大小保持一致
     m_pCurScene->setSceneRect(r);
     QRect re = rect();
     QGraphicsView::paintEvent(event);
 }
由于时间原因,未能自动全部显示部件的原因尚未找到,如有人知道,烦请告诉我一声,不甚感激~
xyconly 2015-03-11
  • 打赏
  • 举报
回复
各位可以直接放入编译器中进行测试,也便于观看,本代码编写环境:QT5,VS2012
内容概要:本文围绕可变桨叶四旋翼无人机的规范控制与点对点运动模拟展开,重点研究优化推力分配策略在翻转动作的应用与性能比较。通过Matlab代码实现,构建了四旋翼动力学模型,并设计了多种控制算法以实现精确的姿态调整与轨迹跟踪。研究对比了不同推力分配方案在执行高机动性翻转动作时的稳定性、能耗效率与响应速度,旨在提升无人机在复杂飞行任务的动态性能与控制精度。该仿真研究为无人机飞控系统的设计与优化提供了理论依据和技术支持。; 适合人群:具备一定自动控制理论基础和Matlab编程能力,从事无人机控制、飞行器动力学或机器人系统研究的科研人员及研究生。; 使用场景及目标:① 实现四旋翼无人机在三维空间的精确点对点运动控制;② 对比分析不同推力分配策略在执行翻转等高难度动作时的控制效果与能耗表现,优化飞行性能;③ 为无人机自主飞行、特技飞行及复杂环境下的机动控制提供算法验证平台。; 阅读建议:此资源以Matlab仿真为核心,建议读者结合相关控制理论知识,深入理解代码实现细节,重点关注动力学建模、控制律设计与推力分配模块。在学习过程,应动手调试参数,复现文翻转动作的仿真结果,并尝试拓展至其他复杂飞行任务,以加深对无人机控制机理的理解。

21,495

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧