QGraphicScene Pop Ups for a second then vanishes - qt

I have a all my code inside the constructor of a mainWindow. The problem is that the display only pop ups for a second and than vanishes. Any help will be much appreciated . Following is the code.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QPixmap kineticPix(":/images/kinetic.png");
QPixmap bgPix(":/images/Time-For-Lunch-2.jpg");
QGraphicsScene scene(-350, -350, 700, 700);
QGraphicsItem *buttonParent = new QGraphicsRectItem;
Button *ellipseButton = new Button(QPixmap(":/images/ellipse.png"), buttonParent);
Button *figure8Button = new Button(QPixmap(":/images/figure8.png"), buttonParent);
Button *randomButton = new Button(QPixmap(":/images/random.png"), buttonParent);
Button *tiledButton = new Button(QPixmap(":/images/tile.png"), buttonParent);
Button *centeredButton = new Button(QPixmap(":/images/centered.png"), buttonParent);
ellipseButton->setPos(-100, -100);
figure8Button->setPos(100, -100);
randomButton->setPos(0, 0);
tiledButton->setPos(-100, 100);
centeredButton->setPos(100, 100);
scene.addItem(buttonParent);
buttonParent->scale(0.75, 0.75);
buttonParent->setPos(200, 200);
buttonParent->setZValue(65);
}

You have created the scene on the stack and not assigned it to a member variable, so as soon as control leaves the constructor it is deleted.

Related

QGraphicsPixmapItem doesn't show in QGraphicsScene

In the inherited class GraphicWidgetItem from QGraphicsItem, I create rectangles, a circle, and a picture. Everything is displayed except the picture. What am I doing wrong?
CustomItem::CustomItem( QObject *parent):
GraphicWidgetItem(parent)
{
QGraphicsRectItem *topLevel = new QGraphicsRectItem(this);
topLevel->setRect(0, 0, 20, 20);
topLevel->setBrush(Qt::gray);
topLevel->setPos(-30 , -30);
QGraphicsRectItem *lowLevel = new QGraphicsRectItem(this);
lowLevel->setRect(0, 0, 20, 20);
lowLevel->setBrush(Qt::red);
lowLevel->setPos(-30 , 60);
QGraphicsEllipseItem *circle = new QGraphicsEllipseItem(this);
circle->setBrush(Qt::green);
circle->setRect(0, 0, 20, 20);
QGraphicsPixmapItem* pi = new QGraphicsPixmapItem(QPixmap(":/icons/image"));
}
There is only 2 way for an item to appear in the scene:
Add directly using addItem().
Or be the children of an item that is already on the scene.
In your case "rectangles" and "circles" are shown because they are children of CustomItem but "pi" is not so it fails, the solution is to pass to "this" as parent:
QGraphicsPixmapItem* pi = new QGraphicsPixmapItem(QPixmap(":/icons/image"), this);
Or
QGraphicsPixmapItem* pi = new QGraphicsPixmapItem(QPixmap(":/icons/image"));
pi->setParent(this);

Qt-context menu checkable property

I have a context menu option in my UI. where it has white and black theme.
void MainWindow::ShowContextMenu(const QPoint& pos)
{
QPoint globalPos = this->mapToGlobal(pos);
white=new QAction("White", this);
black=new QAction("Black", this);
QMenu myMenu;
theme=myMenu.addMenu(tr("&Theme"));
theme->addAction(white);
theme->addAction(black);
white->setCheckable(true);
black->setCheckable(true);
QActionGroup *grp= new QActionGroup(this);
grp->addAction(white);
grp->addAction(black);
black->setChecked(true);
grp->setExclusive(true);
QAction* selectedItem = myMenu.exec(globalPos);
}
I tried to add group action. Which has default exclusion effect. when i select white the black check should go. and viceversa.
But in my code black menu from the list is always checked. and on selecting white, white menu is not getting checked and black check has check mark.
some one provide me a solution for this.
I want the check mark should be changed and toggled.
In your ShowContextMenu slot you always create a new menu object and check its 'black' option. You should declare a menu object as a MainWindow member and init it once only:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
myMenu(0), white(0), black(0)
{
...
}
void Widget::initMenu()
{
white=new QAction("White", this);
black=new QAction("Black", this);
myMenu = new QMenu(this);
QMenu *theme= myMenu->addMenu(tr("&Theme"));
theme->addAction(white);
theme->addAction(black);
white->setCheckable(true);
black->setCheckable(true);
QActionGroup *grp= new QActionGroup(this);
grp->addAction(white);
grp->addAction(black);
black->setChecked(true);
grp->setExclusive(true);
}
void Widget::ShowContextMenu(const QPoint& pos)
{
if (!myMenu)
{
initMenu();
}
QPoint globalPos = this->mapToGlobal(pos);
QAction* selectedItem = myMenu->exec(globalPos);
}

QMDI SubWindows switching

I have an MDI application, with classes as
class MainWindow
{ GraphicsView *gv; };
class GraphicsView
{ Scene *scene; };
class Scene
I'm creating a new mdiSubWindow on every newfile() of MainWindow which creates a new pointer to the GraphicsView.
void MainWindow::newFile()
{
gv = new GraphicsView;
QMdiSubWindow *w = mdiArea->addSubWindow(gv);
mdiArea->setActiveSubWindow(w);
}
And the constructor of GraphicsView creates a new Scene.
GraphicsView::GraphicsView()
{
scene = new Scene;
setScene(scene);
}
Now when there are multiple subWindows created, I lose the ability to work in previous subWindows. Only the latest subWindow works as expected. For eg. I can draw QGraphicsItems only in the latest Sub Windows and not in the previous ones.
I think I should be using activeSubWindow() but couldn't figure out how to make every subWindow respond to the change of the tabs. How should I implement this?
To make it work.
I've created a QList<QPair>, for storing a pair of subwindow and view.
windowViewList.append(qMakePair(w, view));
Then subWindowActivated() signal is used to call the following function to update the view pointer.
void MainWindow::updatePointers()
{
QMdiSubWindow *m = mdiArea->activeSubWindow();
foreach (windowViewPair v, windowViewList)
{
if (m == v.first)
gv = v.second;
}
}

access to QGraphicsView on each tab (in QTabWidget)

I opened each Image in a new tab on QGraphicsScene and QGraphicsView by this
void MainWindow::on_actionOpen_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty()) {
QImage image(fileName);
if (image.isNull()) {
QMessageBox::information(this, tr("Master Measure"),
tr("Cannot load %1.").arg(fileName));
return;
}
scene = new QGraphicsScene;
view = new QGraphicsView;
view->setScene(scene);
tabWidget->addTab(view,"someTab");
scene->addPixmap(QPixmap::fromImage(image));
scene->setBackgroundBrush(QBrush(Qt::lightGray, Qt::SolidPattern));
QFileInfo fileInfo = fileName;
tabWidget->setTabText(ui->tabWidget->count()-1, fileInfo.baseName());
tabWidget->setCurrentIndex(ui->tabWidget->count()-1);
}
}
I want to draw something on each image by clicking.
so I did this by click press event
void MainWindow::mousePressEvent(QMouseEvent *event)
{
QPen pen(Qt::black);
QBrush brush(Qt::red);
pen.setWidth(6);
scene->addEllipse(0,0,1000,500,pen,brush);
}
it just draw Ellipse on last opened image (tab).
I don't know how to solve this problem.
I appreciate any idea.
Thank you.
Obviously scene variable points to the last created scene. When you create new scene, old pointer is lost because you don't save it anywhere. So you need to preserve all scene and view pointers somewhere and use the currently visible objects.
I advise you to create a QGraphicsView's subclass (let's call it MyView) that will be responsible to every tab's contents. Pass the filename to the constructor of this object. In the constructor create a scene and store it in a member variable. Reimplement MyView::mousePressEvent to perform drawing.
Then you can add new tabs like this:
MyView* view = new MyView(filename);
view ->addTab(view,"someTab");
When the user clicks a view, MyView::mousePressEvent method or the respective MyView object will be invoked. Each view will see only its own scene variable, and the respective scene will be edited.

Displaying two widgets in MainWindow

I am new to Qt. As it stands, I have a table with a button btn. When the button is clicked the setCentralWidget(view) takes over the window so I can no longer see the table obviously. But if I remove the setCentralWidget(view), nothing displays when I click the button.
Is there a way I can display both in the same window? Split or dock maybe?
(I have removed code that is irrelevant to my question)
MainWindow::MainWindow()
{
//etc
packet = new QTabWidget;
setCentralWidget(packet)
}
//other code
void MainWindow::create(const QString &a)
{
QTableWidget* table = new QTableWidget;
int tabIndex = packet->addTab(table, a);
packet->setCurrentIndex(tabIndex);
table->setRowCount(1);
table->setColumnCount(2);
table->setHorizontalHeaderLabels(QString("a;Simulator").split(";"));"));
table->setItem(0,0,new QTableWidgetItem(a));
QPushButton *btn = new QPushButton("load", this);
connect(btn, SIGNAL(clicked()), this, SLOT(sim()));
table->setCellWidget(0,1, btn);
}
void MainWindow::sim()
{
QGraphicsScene* scene = new QGraphicsScene(QRect(-10, -10, 100, 50));
QGraphicsView* view = new QGraphicsView();
scene->addText("Network");
view->setScene(scene);
view->setGeometry(QRect(10, 10, 100, 50));
setCentralWidget(view);
}
You should look at the QMdiArea class - it's designed to be used as the central widget of a Main Window that can have many inner widgets. It has a variety of layout styles as well - scroll down on that page to see the examples.
Hope that helps!
You should subclass QWidget. For example make your own MyWidget class. And this class will include a QGraphicsView and a QTabWidget in a splitter for example. And in your MainWindow set the central widget as an instance of MyWidget.

Resources