背景
在qt程序中,如果数据刷新频率过高,容易造成窗口卡顿,因为qt程序是整个窗口刷新,在此种背景下可以在qt程序的主程序上内嵌一个拥有独立句柄的窗口,两个窗口刷新就互不干扰。
案例
以下例子,在主窗口中内嵌一个窗口,窗口显示是QChart相关的图标。
#pragma once
#include <qwidget.h>
#include <QLayout>
#include <QGraphicsView>
#include <QChartView>
#include <QValueAxis>
#include <QLineSeries>
#include <QDebug>
#include <QList>
#include <QTimer>
#include <QtPlatformHeaders/QWindowsWindowFunctions>
#include <thread>
#include <mutex>
#include <vector>
#include <queue>
#include <exception>
namespace ViewDataChart
{
QT_CHARTS_USE_NAMESPACE
class DataLineView : public QWidget
{
Q_OBJECT
public:
DataLineView(int minY, int maxY, int numY, int maxX, int numX);
~DataLineView();
// 显示设置
void SetYNum(int value);
void SetYMax(int value);
void SetYMin(int value);
void SetXNum(int value);
void SetXMax(int value);
public slots:
void UpdateLine();
// 赋值
void AppendValue(unsigned short value);
void AppendValue(std::vector<unsigned short>& list);
protected:
void resizeEvent(QResizeEvent*);
private:
QVBoxLayout* verticalLayout;
QGraphicsView* pGrapView_;
QChartView* pView_;
QWidget* m_winContainer;
QChart* pWavePic_;
QValueAxis* pAxisX_;
QValueAxis* pAxisY_;
QLineSeries* pLineData_;
// QTimer* pTimer_;
int objNum_;
int maxXNum_;
std::mutex mtxData_;
std::vector<ushort> values_;
};
};
#include "DataLineView.h"
#include <QWindow>
ViewDataChart::DataLineView::DataLineView(int minY, int maxY, int numY, int maxX, int numX)
: maxXNum_(maxX)
{
if (this->objectName().isEmpty())
this->setObjectName(QStringLiteral("PlayVideoWidget"));
this->resize(1, 1);
verticalLayout = new QVBoxLayout(this);
verticalLayout->setSpacing(0);
verticalLayout->setContentsMargins(0, 0, 0, 0);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
verticalLayout->setContentsMargins(0, 0, 0, 0);
//this->setWindowTitle("");
QMetaObject::connectSlotsByName(this);
// wave
pAxisX_ = new QValueAxis();
pAxisY_ = new QValueAxis();
pAxisX_->setMin(0);
pAxisX_->setMax(maxX);
// pAxisX_->setVisible(false);
pAxisY_->setMin(minY);
pAxisY_->setMax(maxY);
pAxisY_->setTickCount(numY + 1);
pAxisX_->setTickCount(numX + 1);
pLineData_ = new QLineSeries();
pLineData_->setPointsVisible(true);
pLineData_->setUseOpenGL(true);
// //pLineData_->setName("");
pWavePic_ = new QChart();
pWavePic_->addAxis(pAxisY_, Qt::AlignLeft);
pWavePic_->addAxis(pAxisX_, Qt::AlignBottom);
pWavePic_->addSeries(pLineData_);
pWavePic_->setAnimationOptions(QChart::SeriesAnimations);
pLineData_->attachAxis(pAxisX_);
pLineData_->attachAxis(pAxisY_);
pView_ = new QChartView(pWavePic_);
pView_->setVisible(true);
pView_->resize(geometry().size());
pView_->setChart(pWavePic_);
pView_->setRenderHint(QPainter::Antialiasing);
pView_->setStyleSheet("background-color: rgb(255, 255, 255);");
// 此处开始创建独立句柄
QWindow* win = pView_->windowHandle();
if (!win)
win = pView_->topLevelWidget()->windowHandle();
win->setFlags(Qt::FramelessWindowHint);
QWindowsWindowFunctions::setHasBorderInFullScreen(win, true);
m_winContainer = QWidget::createWindowContainer(win, this);
m_winContainer->setStyleSheet(QString::fromUtf8("border:0px"));
m_winContainer->setStyleSheet("background-color: rgb(255, 255, 255);");
m_winContainer->resize(geometry().size());
verticalLayout->addWidget(m_winContainer);
/*pTimer_ = new QTimer(this);
pTimer_->setSingleShot(false);
pTimer_->setInterval(5);
connect(pTimer_, &QTimer::timeout, this, &ViewDataChart::DataLineView::UpdateLine);
pTimer_->start();*/
//setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
/*QPalette palette = this->palette();
palette.setColor(QPalette::Base, Qt::transparent);
setPalette(palette);
setAttribute(Qt::WA_TranslucentBackground);
setWindowFlags(Qt::FramelessWindowHint);*/
}
ViewDataChart::DataLineView::~DataLineView()
{
delete pLineData_;
pLineData_ = nullptr;
delete pAxisX_;
pAxisX_ = nullptr;
delete pAxisY_;
pAxisY_ = nullptr;
delete pWavePic_;
pWavePic_ = nullptr;
delete pView_;
pView_ = nullptr;
delete verticalLayout;
verticalLayout = nullptr;
}
// 设置y轴刻度数
void ViewDataChart::DataLineView::SetYNum(int value)
{
pAxisY_->setTickCount(value);
}
// 设置y轴最大值
void ViewDataChart::DataLineView::SetYMax(int value)
{
pAxisY_->setMax(value);
}
// 设置y轴最小值
void ViewDataChart::DataLineView::SetYMin(int value)
{
pAxisY_->setMin(value);
}
// 设置x轴刻度数
void ViewDataChart::DataLineView::SetXNum(int value)
{
pAxisX_->setTickCount(value);
}
// 设置x轴最大值
void ViewDataChart::DataLineView::SetXMax(int value)
{
for (int i = 0; i < value - maxXNum_; ++i)
{
if (pLineData_->count() > 0)
pLineData_->remove(0);
}
maxXNum_ = value;
pAxisX_->setMax(maxXNum_);
}
// 添加数据值
void ViewDataChart::DataLineView::AppendValue(unsigned short value)
{
std::unique_lock<std::mutex> lock(mtxData_);
while (pLineData_->count() + 1 > maxXNum_ && maxXNum_ > 1)
{
pLineData_->remove(0);
}
pLineData_->append(pLineData_->count() + 1, value);
}
// 添加数据值(数组)
void ViewDataChart::DataLineView::AppendValue(std::vector<unsigned short>& list)
{
std::unique_lock<std::mutex> lock(mtxData_);
values_ = list;
pLineData_->clear();
for (int i = 0; i < list.size(); ++i)
{
pLineData_->append(QPointF(i, list[i]));
}
}
void ViewDataChart::DataLineView::resizeEvent(QResizeEvent* event)
{
if (pView_)
{
pView_->show();
pView_->resize(geometry().size());
pView_->setVisible(true);
//pView_->resize(geometry().size());
}
QWidget::resizeEvent(event);
}
// 更新图像
void ViewDataChart::DataLineView::UpdateLine()
{
}
案例中数据显示未做完善,在构造函数注明创建独立句柄的代码处。
如下图是效果图,外表看无法看出是内嵌窗口,可以使用 QWidget::winId 函数来获取窗口句柄(HWND)。