DirectX with Qt

Started by
34 comments, last by the_edd 13 years, 4 months ago
I made a class that uses DirectX and Qt

/** @file Defines the widget to display a Direct3D context */ #ifndef _QD3DWIDGET_H_ #define _QD3DWIDGET_H_ #include <QtGui/QWidget> #include "ui_Main.h"struct IDirect3D9; struct IDirect3DDevice9; class QD3DWidget : public QWidget {   Q_OBJECT public:   /** Constructor */   QD3DWidget( QWidget* pParent = NULL);   /** Destructor */   ~QD3DWidget();   /** a hint to Qt to give the widget as much space as possible */   QSizePolicy sizePolicy() const { return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); }   /** a hint to Qt that we take care of the drawing for ourselves, thankyouverymuch */   QPaintEngine *paintEngine() const { return NULL; } protected:   /** Initialized the D3D environment */   void Setup();   /** Destroys the D3D environment */   void Close();   /** paints the scene */   void paintEvent( QPaintEvent* pEvent); private:   /** D3D stuff */   IDirect3D9*       mD3D;   IDirect3DDevice9* mDevice;   Ui::Form ui;}; #endif // _QD3DWIDGET_H_ 


#include "QD3DWidget.h" #include <QMessageBox>#define WIN32_LEAN_AND_MEAN #include <d3d9.h> #include <d3dx9.h> // Constructor QD3DWidget::QD3DWidget( QWidget* pParent)   : QWidget( pParent) { 	ui.setupUi(this);	mD3D = NULL; 	mDevice = NULL; 	setMinimumSize( 400, 400); 	setAttribute( Qt::WA_OpaquePaintEvent, true);  	setAttribute( Qt::WA_PaintOnScreen, true); 	Setup(); } // Destructor QD3DWidget::~QD3DWidget() { 	Close(); } // Initialized the D3D environment void QD3DWidget::Setup() { 	HWND windowHandle = winId(); 	// create Direct3D9 object 	mD3D = Direct3DCreate9( D3D_SDK_VERSION); 	if( NULL == mD3D) 	        QMessageBox::critical(this,                              "ERROR",                              "Failed to create D3D object",                              QMessageBox::Ok);	// create D3D device 	// pack hier deine eigenen PresentationParams rein     D3DPRESENT_PARAMETERS d3dpp;    // create a struct to hold various device information    ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use    d3dpp.Windowed = TRUE;    // program windowed, not fullscreen    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames    d3dpp.hDeviceWindow = windowHandle;    // set the window to be used by Direct3D	HRESULT hr = mD3D->CreateDevice(D3DADAPTER_DEFAULT,                      D3DDEVTYPE_HAL,                      windowHandle,                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,                      &d3dpp,                      &mDevice);	if( FAILED( hr)) 	        QMessageBox::critical(this,                              "ERROR",                              "Failed to create D3D device",                              QMessageBox::Ok);} // Destroys the D3D environment void QD3DWidget::Close() { 	if( mDevice) 		mDevice->Release(); 	if( mD3D) 		mD3D->Release(); } // paints the scene void QD3DWidget::paintEvent( QPaintEvent* pEvent) {   // clear render buffer   HRESULT hr = mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);  if( FAILED( hr)) 	        QMessageBox::critical(this,                              "ERROR",                              "Failed to clear backbuffer.",                              QMessageBox::Ok);  mDevice->BeginScene();    // begins the 3D scene  mDevice->EndScene();    // ends the 3D scene  // and show the result   hr = mDevice->Present(NULL, NULL, NULL, NULL);   // displays the created frame on the screen  if( FAILED( hr)) 	        QMessageBox::critical(this,                              "ERROR",                              "Failed to Present().",                              QMessageBox::Ok);  // trigger another update as soon as possible   update(); } 


and got this window:


But I would leave the Direct3D rendering in just a portion of the window, something like a Viewport of 3D studio Max, how do this?

Thanks
Advertisement
Put your QD3DWidget in a parent widget's layout. Off the top of my head, something like:

class Window : public QWidget{    public:        Window() :             QWidget(0) // top-level, no parent        {            QHBoxLayout *layout = new QHBoxLayout;            setLayout(layout);            layout->addWidget(new QD3DWidget(this));            layout->addWidget(new QPushButton("hello", this));        }};


This will create a window with your D3D widget on the left and a button on the right (if I've done everything correctly).

There are a bunch of other layouts you might wnt to use rather than a QHBoxLayout, but that's the general idea.

EDIT: or, presumably D3D has an equivalent to glViewport. You could use that if you want to split the D3D widget itself.
the_edd, thank you very much!
now working :)

Taking this thread, I have another doubt (idiot):

I have an abstract class:
class IObserver{public:   virtual void handle_Event(const std::string &msg) = 0;};


And I have my class that inherits QWidget
class server_control : public QWidget{   Q_OBJECTpublic:   server_control(Server* s, QWidget *parent = 0);   ~server_control();private:   Ui::server_control ui;   Server* server;   std::string text_map;   std::string text_server;   std::string text_type_net;   std::string text_password;   int max_players;   int port;   QTextTableFormat tableFormat;public slots:   void Submit();};


But when I try to make my class inherit the abstract class IObserver, it shows the following error:
1>dedicatedserver.cpp(142): error C2259: 'server_control' : cannot instantiate abstract class
1> due to following members:
1> 'void IObserver::handle_Event(const std::string &)' : is abstract
1> d:\projetos\dedicatedserver\dedicatedserver\Observer.h(15) : see declaration of 'IObserver::handle_Event'


And it points to that line when instantiate the object (the class that I'm trying to inherit)
s_control = new server_control(server);


Why? :(

[Edited by - alliedwarrior on December 4, 2010 7:25:03 AM]
Because you haven't implemented the pure-virtual handle_Event method in your derived class. The error message is quite helpful in this case, actually.
class server_control : public QWidget, public IObserver{	Q_OBJECTpublic:	server_control(Server* s, QWidget *parent = 0);	~server_control();	virtual void handle_Event(const std::string &msg);private://....}


Now that I have implemented the following error appears:
Quote:server_control.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall server_control::handle_Event(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?handle_Event@server_control@@UAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)


[crying]
The object file or library that contains your definition of server_control::handle_Event has not been linked in to the binary.
Excuse my ignorance, but what does that mean? how can I fix it?
The compiler turns C++ source files in to object files (typically .obj extension for Visual C++). For convenience, object files can optionally be bundled in to what's called a static library (typically a .lib extension for Visual C++). The linker then takes these object files and/or static libraries and glues them together in to an executable or dynamic library.

You are getting an error at the linking stage. Your code mentions a server_control::handle_Event function but the linker cannot find the object file/static library that contains the compiled definition of this method ("unresolved external symbol").

So, check that the source file that contains the definition of server_control::handle_Event is mentioned in your Visual C++ solution/project or your Qt .pro file.

I empathise with your desire to jump in to creating GUIs and visuals at an early stage, but I'd recommend learning a little more about the basics of C++ before continuing too much further. The last two questions are C++ 101 (and actually the first question can be answered by following any Qt tutorial, including the ones found inside Qt Assistant).
The strange thing is that this happens even I trying something very simple and in the same header:

server_control.h
class AbstractClass {public:  virtual void AbstractMemberFunction() = 0; //pure virtual function makes this class Abstract class};class server_control : public QWidget, public AbstractClass{	Q_OBJECTpublic:	server_control(Server* s, QWidget *parent = 0);	~server_control();	void AbstractMemberFunction();private:	Ui::server_control ui;	Server* server;	std::string text_map;	std::string text_server;	std::string text_type_net;	std::string text_password;	int max_players;	int port;	QTextTableFormat tableFormat;public slots:	void Submit();};


Quote:error LNK2001: unresolved external symbol "public: virtual void __thiscall server_control::AbstractMemberFunction(void)" (?AbstractMemberFunction@server_control@@UAEXXZ)


I tested in another class that does not inherit QWidget, and it worked perfectly:
class AbstractClass {public:  virtual void AbstractMemberFunction() = 0; //pure virtual function makes this class Abstract class};class Test : public AbstractClass{public:	Test() { }	~Test() { } 	void AbstractMemberFunction();}
But do you actually try to *create* a Test object?

This topic is closed to new replies.

Advertisement