在Qt内部通过Windows GDI绘图
我试图在QGraphicsView paintEvent中使用
Windows GDI但是已经注意到一些绘图问题,例如当我调整窗口大小或最小化和最大化时,绘图消失或闪烁.当我使用Qt代替GDI时,它的工作完美.这是代码:
[更新代码] #include "CustomView.h" #include <QPainter> #include <QPaintEngine> #include <windows.h> #include <objidl.h> #include <gdiplus.h> using namespace Gdiplus; #pragma comment (lib,"Gdiplus.lib") CustomView::CustomView(QWidget *parent) : QGraphicsView(parent) { setAutoFillBackground(true); setViewportUpdateMode(QGraphicsView::FullViewportUpdate); setAttribute(Qt::WA_NativeWindow,true); } CustomView::~CustomView() { } void CustomView::paintEvent(QPaintEvent * event) { QPainter painter(viewport()); painter.beginNativePainting(); // Drawing by Windows GDI HWND hwnd = (HWND)viewport()->winId(); HDC hdc = GetDC(hwnd); QString text("Test GDI Paint"); RECT rect; GetClientRect(hwnd,&rect); HBRUSH hbrRed = CreateSolidBrush(RGB(0,255,0)); FillRect(hdc,&rect,hbrRed); Ellipse(hdc,50,rect.right - 100,rect.bottom - 100); SetTextAlign(hdc,TA_CENTER | TA_BASELINE); TextOutW(hdc,width() / 2,height() / 2,(LPCWSTR)text.utf16(),text.size()); ReleaseDC(hwnd,hdc); painter.endNativePainting(); QGraphicsView::paintEvent(event); // Drawing the same by Qt // QPainter painter(viewport()); // painter.save() ; // QBrush GreenBrush(Qt::green); // QBrush WhiteBrush(Qt::white); // QRect ViewportRect = viewport()->rect(); // painter.fillRect(ViewportRect,GreenBrush); // painter.drawEllipse(50,ViewportRect.right() - 100,ViewportRect.bottom() - 100); // QPainterPath EllipsePath; // EllipsePath.addEllipse(50,ViewportRect.bottom() - 100); // painter.fillPath(EllipsePath,WhiteBrush); // painter.drawText(ViewportRect.width() / 2,ViewportRect.height() / 2,"Test Qt Paint"); // painter.restore(); } 这是整个项目(Visual Studio 2010 Qt 5.4.1)[UPDATED ARCHIVE] 有任何想法吗? 解决方案(在Kuba Ober回答后编辑代码) #include "CustomView.h" #include <QPainter> #include <QPaintEngine> #include <windows.h> #include <objidl.h> #include <gdiplus.h> using namespace Gdiplus; #pragma comment (lib,"Gdiplus.lib") CustomView::CustomView(QWidget *parent) : QGraphicsView(parent) { // This brings the original paint engine alive. QGraphicsView::paintEngine(); setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_PaintOnScreen); setRenderHint(QPainter::Antialiasing); } CustomView::~CustomView() { } QPaintEngine* CustomView::paintEngine() const { return NULL; } bool CustomView::event(QEvent * event) { if (event->type() == QEvent::Paint) { bool result = QGraphicsView::event(event); drawGDI(); return result; } else if (event->type() == QEvent::UpdateRequest) { bool result = QGraphicsView::event(event); drawGDI(); return result; } return QGraphicsView::event(event); } void CustomView::drawGDI() { // Drawing by Windows GDI HWND hwnd = (HWND)viewport()->winId(); HDC hdc = GetDC(hwnd); QString text("Test GDI Paint"); RECT rect; GetClientRect(hwnd,hdc); } 解决方法
打算通过GDI绘制的QWidget必须:
>重新实现paintEngine返回nullptr. 此外,在通过paintEvent / QPainter绘制的内容之上通过GDI绘制的QWidget还必须: >在构造函数中调用基类的paintEngine()方法一次.这将实例化窗口小部件的本机绘制引擎. 下面的示例显示了如何在Qt的绘图系统完成的绘图之上进行重绘.当然,由于这幅画是在Qt已经绘制的顶级内容上完成的,因此有闪烁. 在Qt的后备存储上进行GDI绘制,避免闪烁也是可能的,但需要采用稍微不同的方法. #include <QApplication> #include <QGraphicsObject> #include <QPropertyAnimation> #include <QGraphicsView> #include <QPainter> #include <QPaintEvent> #include <windows.h> class View : public QGraphicsView { public: View(QWidget *parent = 0) : QGraphicsView(parent) { // This brings the original paint engine alive. QGraphicsView::paintEngine(); //setViewportUpdateMode(QGraphicsView::FullViewportUpdate); setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_PaintOnScreen); setRenderHint(QPainter::Antialiasing); } QPaintEngine * paintEngine() const Q_DECL_OVERRIDE { return 0; } bool event(QEvent * event) Q_DECL_OVERRIDE { if (event->type() == QEvent::Paint) { bool result = QGraphicsView::event(event); paintOverlay(); return result; } if (event->type() == QEvent::UpdateRequest) { bool result = QGraphicsView::event(event); paintOverlay(); return result; } return QGraphicsView::event(event); } void resizeEvent(QResizeEvent *) { fitInView(-2,-2,4,Qt::KeepAspectRatio); } virtual void paintOverlay(); }; void View::paintOverlay() { // We're called after the native painter has done its thing HWND hwnd = (HWND)viewport()->winId(); HDC hdc = GetDC(hwnd); HBRUSH hbrGreen = CreateHatchBrush(HS_BDIAGONAL,RGB(0,0)); RECT rect; GetClientRect(hwnd,&rect); SetBkMode(hdc,TRANSPARENT); SelectObject(hdc,hbrGreen); Rectangle(hdc,rect.right,rect.bottom); SelectObject(hdc,GetStockObject(NULL_BRUSH)); Ellipse(hdc,rect.bottom - 100); QString text("Test GDI Paint"); SetTextAlign(hdc,TA_CENTER | TA_BASELINE); TextOutW(hdc,text.size()); DeleteObject(hbrGreen); ReleaseDC(hwnd,hdc); } class EmptyGraphicsObject : public QGraphicsObject { public: EmptyGraphicsObject() {} QRectF boundingRect() const { return QRectF(0,0); } void paint(QPainter *,const QStyleOptionGraphicsItem *,QWidget *) {} }; void setupScene(QGraphicsScene &s) { QGraphicsObject * obj = new EmptyGraphicsObject; QGraphicsRectItem * rect = new QGraphicsRectItem(-1,0.3,2,obj); QPropertyAnimation * anim = new QPropertyAnimation(obj,"rotation",&s); s.addItem(obj); rect->setPen(QPen(Qt::darkBlue,0.1)); anim->setDuration(2000); anim->setStartValue(0); anim->setEndValue(360); anim->setEasingCurve(QEasingCurve::InBounce); anim->setLoopCount(-1); anim->start(); } int main(int argc,char *argv[]) { QApplication a(argc,argv); QGraphicsScene s; setupScene(s); View view; view.setScene(&s); view.show(); return a.exec(); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows-7 – Windows 7紧凑型动态VHD
- windows-server-2008 – 连接到VPN时丢失Internet连接
- 你可以在Windows应用程序中使用asp.net会员提供程序吗?
- active-directory – 从旧服务器上的目录中删除打印机
- .net – 是否有Robocopy的API包装器?
- 唤醒用于Windows的Lan工具?
- 怎么把电脑桌面上的CAD图纸转换成BMP格式图纸?
- windows-server-2008-r2 – Windows Server 2008 R2上的IIS
- vs调试程序缺少 msvcp140d.dll 解决方法
- 如何在Windows PE 32位可执行文件中为我的代码洞穴腾出空间