PDA

View Full Version : Subclassing from QGraphicsTextItem and QScrollArea issue



sreenidhi707
7th January 2019, 01:23
Hello Everyone

I want to create a main window with a scrollable QGraphicsScene which has objects subclassed from QGraphicsTextItem. Basically, I want to draw a white rectangle with text inside it (the code to draw text inside the rectangle is not shown), and when the rectangle is bigger than the viewport, I want scroll bars to automatically appear in the QGraphicsScene

In the code snippets below I have simplified the code with just one object of MyGraphicsTextItem in the QGraphicsScene object. All I see with the code below is a blank screen, the overridden MyGraphicsTextItem:: paint() does not get called.

mainwindow.h


namespace Ui {
class MainWindow;
}

class MyGraphicsTextItem : public QGraphicsTextItem
{
Q_OBJECT
public:
explicit MyGraphicsTextItem()
{

};
~MyGraphicsTextItem(){};

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};

class MyWidget : public QWidget
{
Q_OBJECT

public:
explicit MyWidget(QWidget *_parent = nullptr) :
QWidget(_parent)
{
parent = _parent;

RenderScene();


};

~MyWidget(){};

QWidget* parent = nullptr;
QGraphicsScene* graphicsScene = nullptr ;
QScrollArea* scrollArea = nullptr;
void RenderScene();

};

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;

MyWidget* myWidget = nullptr;
};

mainwindow.cpp


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

myWidget = new MyWidget(this);

this->setCentralWidget(myWidget);

}


void MyWidget::RenderScene()
{
graphicsScene = new QGraphicsScene(this);

MyGraphicsTextItem* graphicsTextItem = new MyGraphicsTextItem();
graphicsScene->addItem(graphicsTextItem);

QGraphicsView* graphicsView = new QGraphicsView(this);
graphicsView->setScene(graphicsScene);

scrollArea = new QScrollArea();

QHBoxLayout* scrollLayout = new QHBoxLayout();
scrollArea->setLayout(scrollLayout);

scrollArea->setWidget(graphicsView);
scrollArea->setWidgetResizable(true);


}

MainWindow::~MainWindow()
{
delete ui;
}

void MyGraphicsTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
cout << "Paint called\n";
QRect pixelRect(0, 0, 500, 500);

QPainterPath painterPath;
painterPath.addRect(pixelRect);

painter->setPen(Qt::black);
painter->setRenderHint(QPainter::Antialiasing);

painter->fillPath(painterPath, Qt::white);

QGraphicsTextItem::paint(painter,option,widget);
}

On the other hand, if I change this


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

myWidget = new MyWidget(this);

this->setCentralWidget(myWidget);

}

to this


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

myWidget = new MyWidget(this);

this->setCentralWidget(myWidget->scrollArea);

}

I can see the white rectangle, however I don't get scrollbars in the window.
13006

d_stranz
7th January 2019, 16:21
First, you have your logic turned around backwards. The scroll area should be the central widget for the MainWindow, you should put a layout inside that, and then you should add your "MyWidget" instance into the layout. My widget should not be managing the scroll area, it should be the other way around.

Second, the items in QGraphicsScene instances are rendered into QGraphicsView instances. There is really no need for you to have a "MyWidget" class, simply put the QGraphicsView as the widget managed by the layout in the scroll area.

Finally, there will be no scrollbars if the scene is smaller than the view. You might be drawing into a QRect that is 500 x 500, but nowhere do you tell the scene that your custom text object is that big.

There are many examples of the Graphics / View architecture in the Qt distribution, including some that do the same things you are trying to do.