QGLWidget + QGraphicsScene + QGraphicsView problem - c++

I would like to create a simple thumbnail viewer using QGLWidget, QGraphicsScene and QGraphicsView. And I have a problem with placing QGLWidget on QGraphicsScene. The code is similar to this:
QGraphicsScene *testScene = new QGraphicsScene (0, 0, 400, 400, 0);
QGLWidget *testWidget1 = new QGLWidget();
testWidget1->renderText("Test text1");
QGLWidget *testWidget2 = new QGLWidget();
testWidget2->renderText("Test text2");
testScene->addWidget(testWidget1);
testScene->addWidget(testWidget2);
QGraphicsView *testView = new QGraphicsView();
testView->setScene(testScene);
testView->show()
It is possible to place few QGLWidgets on QGraphicsScene/QGraphicsView? Where I doing something wrong? Is there any other component on which I could embed QGLWidgets and show them on the screen?
Thanks for help

To make QGLWidget show in QGraphicsView, you should redirect painting for it. You can overwrite the paintGL like this:
virtual void MyGLWidget::paintGL()
{
QGLWidget::paintGL();
//support redirecting painting
QPaintDevice* device = QPainter::redirected(this);
if (device != NULL && device != this)
{
QImage image = grabFrameBuffer();
QPainter painter(this);
painter.drawImage(QPointF(0.0,0.0),image);
}
}
It works well for most platforms, but still happens to show black widget.

The QGraphicsScene::addWidget documentation states that QGLWidget is not a supported widget type.
Parenting a QGLWidget onto the viewport of the QGraphicsView doesn't seem to work either.
Edit:
Actually parenting a QGLWidget to the viewport does work provided I put the renderText call within the paintGL method of my test GL widget.

From the QGraphicsView docs:
To render using OpenGL, simply call setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport widget.
So, in order to draw text on the view, use a QGraphicsTextItem rather than trying to draw text using the QGLWidget.

Related

Qt: issue with QGraphicscene to show an imge

I am trying to develop very simple image viewer using QT. I am using the following code to show the image on QGraphicsScene widget:
QImage image(fileName);
firstPicture = new QGraphicsScene();
firstPicture->addPixmap(QPixmap::fromImage(image));
ui->graphicsView->setScene(firstPicture);
ui->graphicsView->fitInView(firstPicture->sceneRect() ,Qt::KeepAspectRatio);
I am getting the following output:
How can I fit the image into the GraphicsScene?
This approach works only when view showed your scene. In your case you did not call show(). Solution:
Use your approach when scene already shown.
You can reimplement showEvent and use your approach here.
You can scale image by yourself and set this scaled image to scene.
Also you can try to use: Qt::IgnoreAspectRatio instead of Qt::KeepAspectRatio.
You can make your custom class which inherits from QGraphicsView. You should reimplement resizeEvent( QResizeEvent *event ) in your custom QGraphicsView like:
void MyView::resizeEvent(QResizeEvent *event)
{
fitInView(firstPicture->sceneRect(), Qt::KeepAspectRatio);
QGraphicsView::resizeEvent(event);
}
This way the view will always display the whole scene. I.e. if the window size is changed and the graphicsView is resized, The scene gets scaled and you can see everything appropriately.

Scaling the QGraphicsScene to fill whole QGraphicsView

I have found a few fixes for this issue, but none of seemed to be sufficient. I have a QGraphicsView displaying a QGraphicsScene. What I want to do is to scale the scene in order to fill the whole view. Also I want it to scale dynamically when the user will be resizing the window displaying the view. Is such a thing possible? If so I'd be glad if you could give me a short example on how should it be implemented. Thanks in advance.
You can make your custom class which inherits from QGraphicsView. You should reimplement resizeEvent( QResizeEvent *event ) in your custom QGraphicsView like:
void MyView::resizeEvent(QResizeEvent *event)
{
fitInView(0, 0, 500, 500,Qt::KeepAspectRatio);
QGraphicsView::resizeEvent(event);
}
This way the view will always display the whole scene. I.e. if the window size is changed and the graphicsView is resized, The scene gets scaled and you can see everything appropriately.

Qt4.8 QGraphicsWidget usage

I can't figure out from the docs, how to use QGraphicsWidget to draw something on it.
Can you help me please? I try this code but when I add it to the graphics scene it shows nothing.
class Platform : public QGraphicsWidget
{
public:
Platform()
{
QGraphicsEllipseItem elipse(0,0,10,10,this);
setGraphicsItem(&elipse);
}
};
QGraphicsWidget is not a widget on which you draw things, it is a widget that can be draw in the Graphics View framework. To draw things, you'll need a QGraphicsScene to hold the items to draw and a QGraphicsView, which is the widget that displays the QGraphicsScene.
You should start with the documentation for the Graphics View framework.

QMainWindow centralWidget border

I have a QMainWindow whose central widget has been set to a QGraphicsView viewing a black scene (for test purposes). Note that in the code below, I use my class derived from QGraphicsView, called CQtGlView, which reimplements only the resizeEvent function.
Regardless of whether I add the view directly,
CQtMainWindow::CQtMainWindow() {
m_glView = new CQtGlView();
setCentralWidget(m_glView);
}
or stick it in a layout with margins of 0 in a dummy widget,
CQtMainWindow::CQtMainWindow() {
m_glView = new CQtGlView();
QWidget* dummy = new QWidget();
QHBoxLayout* l = new QHBoxLayout();
l->setContentsMargins(0,0,0,0);
l->addWidget(m_glView);
dummy->setLayout(l);
setCentralWidget(dummy);
}
I get an unwanted grey border around the widget.
The screenshot below illustrates the problem, visible between my scene and the windows aero border.
This would not be a problem if my application did not allow switching to full screen. The border is very obvious once the rest of the screen is black.
It's possible this area represents the DockWidgetAreas around the outside of the central widget.
Is there anything I can do to solve this other than not use QMainWindow? (Undesirable due to my use of menuBar, tool bars, and statusBar.)
It turns out that QGraphicsView derives from QFrame, where I assumed it was only a QWidget.
The solution to this problem was to call setFrameStyle(QFrame::NoFrame); in the constructor of my QGraphicsView subclass. Or if it was not a subclass,
m_glView->setFrameStyle(QFrame::NoFrame);
Have you tried setFrameShape(QFrame::NoFrame) on the QGraphicsView?

painting inside widget in Qt

I created a very simple GUI that has a push button and a "Graphics View" widget from Display Widgets. On pushing the button I want a line to be drawn across the "Graphics View" widget. I have changed the name of the "Graphics View" widget to gv by right-clicking the widget in design view and then selecting change objectName. I am not able to understand how should the line be drawn. I read various texts on Qt that provided information about QPainter, PaintEvent etc. But I got more confused.
Kindly help me with this. A small sample code shall be really helpful for me as I am new to Qt.
A QGraphicsView is meant for displaying instances of QGraphicsItem that are managed by a component called QGraphicsScene. In your case, you'd create a QGraphicsLineItem and add it to the scene, or directly create it as an item of the scene by calling the addLine member function of your QGraphicsScene instance.
All drawing will be done by Qt itself, assuming that you did connect your graphics view and scene properly. Be sure to read The Graphics View Framework, which gives you an overview over how these components work.
You will find code examples of how to manage and display a scene using the graphics view framework here: http://doc.trolltech.com/4.6/examples-graphicsview.html
You can paint into a QPainter
Either override the paintevent and draw there
void MyDisplayWidget::paintEvent(QPaintEvent*)
{
QPainter p(this);
p.setPen(Qt::green);
p.drawText(10,10,"hello");
}
Or draw into a QImage and display that
QImage image = QImage(size);
QPainter p(&image);
p.drawText(10,10,"hello");
// draw or save QImage
You can even use the same draw function taking a QPainter * to draw either direct to the screen or to an image.
first you must knew some information about QPainter to have benefit of it.
QPainter provides highly optimized functions to do most of the drawing GUI programs require. It can draw everything from simple graphical primitives (represented by the QPoint, QLine, QRect, QRegion and QPolygon classes) to complex shapes like vector paths .and we use it to draw on paint devices
then render it to view,and we have alot of qpaint devices like : QWidget, QImage, QPixmap, QPicture, QPrinter, and QOpenGLPaintDevice you can use any one of them depending on your requirements then create QGraphic scene and add you paint device as qgraphic scene item to be shown in qgraphic view.
here is simple code:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
scene=new QGraphicsScene(this); //allocate your scene to your main widget
view=new QGraphicsView(scene,this);//here is your view
pixmap=new QPixmap(QSize(700,700));// paint device
view->resize(700,700);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *e)
{
painter=new QPainter;// create your painter
painter->begin(pixmap);//add painter to your paint device
painter->fillRect(0,0,300,300,Qt::red);//draw rect
painter->setPen(Qt::yellow);
painter->drawLine(0,0,700,700);//draw line
painter->end();
scene->addPixmap(*pixmap);// add your paint device to your scene
view->show();//then show your view
}