Using QList<QGraphicsItem*> - c++

I am using a developer defined QGraphicsScene pointer from the "dialog/mainwindow" class called wavesScene to return a QList of QGraphicsItem*'s using QGraphicsScene::items. Something seems to be wrong with my syntax, it says that the list "graphicsItemList" is never used/declared.
Here is my code, any ideas as to how I would properly implement this methodology
relevant code inside mainwindow/segyView.h
QGraphicsScene *wavesScene;
Constructor code *I think, may be called something different
SEGYView::SEGYView(QWidget *parent)
:QMainWindow(parent),
ui(new Ui::SEGYView)
{
ui->setupUi(this);
wavesScene = new QGraphicsScene(this);
ui->PixmapView->setScene(wavesScene);
}
Code inside slider_value_changed() slot
QList<QGraphicsItem*> graphicsItemList(wavesScene->items());
QGraphicsPixmapItem pixmapItem(graphicsItemList.at(0));
QPixmap wavesPixmap = pixmapItem.pixmap();
QPixmap wavesPixmapScaled = wavesPixmap.scaled((newSliderValue*INITIAL_WAVES_PIXMAP_X_SIZE), 1250);
pixmapItem.setPixmap((wavesPixmapScaled));
wavesScene->addItem(&pixmapItem);
relevant code inside actionOpen on triggered() slot
wavesScene->addItem(pixmapGraphicsItem);
ui->PixmapView->setScene(wavesScene);
Error is "graphicsItemList" was not declared in this scope
QGraphicsPixmapItem* pixmapItem = graphicsItemList.at(0);
^

Related

Use this outside of constructor

MainWindow::MainWindow(QWidget *parent, GraphicalUI *graphicalUI) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QLabel *label = new QLabel("Label", this);
label->setPixmap(graphicalUI->textures["background"]);
label->setStyleSheet("background-color: black;");
}
void buildWindow(Level *level, GraphicalUI *graphicUI) {
QGridLayout layout = QGridLayout(this);
}
The problem here is found in the buildWindow() function. Obviously I cannot just use
QGridLayout(this). But I want the MainWindow to be the parent of my QGridLayout.
How do I do this? Also, the buildWindow function is going to be called externally.
this is an implicit argument to all member functions. Which means it is available in all member functions not just the constructor. It's just a pointer to the current object.
Since the buildWindow function is not a member function of MainWindow(which I do not recommend) you can pass the address of the MainWindow instance to buildWindow function. By default MainWindow is instantiated in the main.cpp file when you create a new GUI project in Qt Creator.
like:
void buildWindow(Level *level, GraphicalUI *graphicUI, MainWindow* window) {
QGridLayout* layout = new QGridLayout(window);
}
But:
In your code:
void buildWindow(Level *level, GraphicalUI *graphicUI) {
QGridLayout layout = QGridLayout(this);
}
variable layout is a local variable in the scope of this function. When your code reaches the end of function (closing brackets), your QGridLayout layout object is destroyed. In order to avoid this, you should use pointers and the new keyword.
QGridLayout *layout = new QGridLayout(this);
now leyout is just a pointer to a QGridLayout object. This object is destroyed if you call delete layout; manually or the parent object (in this case your mainwindow object) get's destroyed.
But now the problem is you can't access this QGridLayout later on from other functions because the pointer layout will be lost at the end of this function. I recommend using a class member variable like:
private:
QGridLayout *layout;
in your header file and initialize if inside your function like:
void MainWindow::buildWindow(Level *level, GraphicalUI *graphicUI) {
layout = new QGridLayout(this);
}
Make sure you don't use the layout pointer before calling this function.
void MainWindow::buildWindow(Level *level, GraphicalUI *graphicUI) {
QGridLayout* layout = new QGridLayout(this);
}
Thats the solution.
The function is also required to exist in the header of the class.

Qt - QLineEdit doesn't update the page and URL

I've got a small problem with my web browser project. Whenever I enter the URL address (via QLineEdit), the browser doesn't show the page, and whenever I change the page (via click on-site with starting page included) the address doesn't show up on the URL bar.
Here's my mainwindow.cpp code. The program executes and exits with code 0. I tried using qDebug inside the functions (changeUrlBar(QUrl) and setUrl()) and it turns out that the program enters these functions but they don't do anything. Every advice would be very appreciated.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
browserView(new QWebEngineView),
urlBar(new QLineEdit)
{
ui->setupUi(this);
//
// initialization of widgets and layouts
// widgets
QWidget *browserWindow = new QWidget(this);
QLineEdit *urlBar = new QLineEdit;
QProgressBar *progressBar = new QProgressBar;
// WebEngineView - actual web browser
QWebEngineView *browserView = new QWebEngineView(parent);
// layouts
QVBoxLayout *mainLayout = new QVBoxLayout;
QHBoxLayout *topBarLayout = new QHBoxLayout;
// push buttons
QPushButton *buttonBack = new QPushButton("Back");
QPushButton *buttonForward = new QPushButton("Forward");
QPushButton *buttonReload = new QPushButton("Reload");
//
// creating the widgets and layouts
// top bar
topBarLayout->addWidget(buttonBack);
topBarLayout->addWidget(buttonForward);
topBarLayout->addWidget(buttonReload);
topBarLayout->addWidget(urlBar);
// main layout of the browser
mainLayout->addLayout(topBarLayout);
mainLayout->addWidget(progressBar);
mainLayout->addWidget(browserView);
browserWindow->setLayout(mainLayout);
setCentralWidget(browserWindow);
//
// connecting slots and signals
// internal connections
connect(buttonBack, SIGNAL(clicked()), browserView, SLOT(back()));
connect(buttonForward, SIGNAL(clicked()), browserView, SLOT(forward()));
connect(buttonReload, SIGNAL(clicked()), browserView, SLOT(reload()));
connect(browserView, SIGNAL(loadProgress(int)), progressBar, SLOT(setValue(int)));
// browser connections
connect(browserView, SIGNAL(urlChanged(QUrl)), this, SLOT(changeUrlBar(QUrl)));
connect(urlBar, SIGNAL(editingFinished()), this, SLOT(setUrl()));
// set starting page
browserView->load(QUrl("https://www.wikipedia.org"));
}
void MainWindow::setUrl()
{
browserView->load(QUrl::fromUserInput(urlBar->text()));
}
void MainWindow::changeUrlBar(QUrl)
{
urlBar->setText(browserView->url().toString());
}
MainWindow::~MainWindow()
{
delete ui;
delete browserView;
delete urlBar;
}
Your actual problem is that you've defined two local variables (urlBar and browserView) that are hiding the declaration of MainWindow::urlBar and MainWindow::browserView.
Those local objects are the ones added to the user interface, but in the slots you are using the member objects (those that were not included in the UI). Even when they are initialized in the constructor, they are not neither receiving user input nor being displayed on the user interface.
MainWindow::MainWindow(QWidget *parent) :
// ...
QLineEdit *urlBar = new QLineEdit; // <-- local variable hiding member declaration
QProgressBar *progressBar = new QProgressBar;
// WebEngineView - actual web browser
QWebEngineView *browserView = new QWebEngineView(parent); // <-- local variable hiding member declaration
// ...
void MainWindow::changeUrlBar(QUrl)
{
urlBar->setText(browserView->url().toString()); // <-- urlBar and browserView are members
}
Moral: avoid hiding or be conscious about it ;). Some tricks used to reduce this are to always access member through this (this->urlBar), or using a different notation for members (like m_urlBar or urlBar_). Also, many compilers should warn about this.
I feel like an idiot now because I managed to solve this issue and the only thing to do was to delete following lines:
QLineEdit *urlBar = new QLineEdit;
QWebEngineView *browserView = new QWebEngineView(parent);
As these objects were already initialised.

crash when calling new operator outside constructor in qt

I'm having a question about a weird (At least it was unexpected for me) behavior (It crashes) of qt when initializing pointers on a member class different than the constructor. I am attaching part of my code:
In mainwindow.h:
class MainWindow : public QMainWindow
{
...
private:
QPixmap *qpm_s1_yaw;
QPainter *s1_yaw_painter;
...
}
In mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
...
initGraph(qpm_s1_yaw, s1_yaw_painter, ui->YAW1);
...
}
void MainWindow::initGraph(QPixmap *map, QPainter *painter, QLabel *label)
{
map = new QPixmap(label->size());
map->fill(Qt::white);
painter = new QPainter(map);
... doing some stuff ...
label->setPixmap(*map); // ++(Remember this LINE)++
}
That actually works, but when I comment the line:
label->setPixmap(*map)
and instead set the Pixmap in the constructor (MainWindow::MainWindow) by writing:
ui->YAW1->setPixmap(*qpm_s1_yaw)
I got a segmentation Fault.
Could someone explain what is wrong with it? To make it work I had to initialize all the pointers in the constructor (and commenting those line in the classs member initGraph), like this:
qpm_s1_yaw = new QPixmap(ui->YAW1->size());
s1_yaw_painter = new QPainter(qpm_s1_yaw);
initGraph(qpm_s1_yaw, s1_yaw_painter, ui->YAW1);
ui->YAW1->setPixmap(*qpm_s1_yaw);
Thanks
This is a trivial misunderstanding of how C++ works, nothing to do with Qt.
Your code lies to you: you can equally well write: initGraph(0, 0, ui->YAW1). You're initializing local variables instead of class members. The values you pass as the first two arguments are not used for anything.
It's also completely unnecessary to hold the pixmap and the painter by pointer. Hold the pixmap by value, and only instantiate a painter for it when you do the painting.
Holding a painter to a pixmap when you're not painting on it can cause unnecessary copies of the pixmap to be made when the pixmap is consumed (read from): a pixmap with an active painter is considered "dirty".
What you should do then is to hold pixmaps by value and you can return the new value from initGraph - this decouples initGraph from the detail of the surrounding class where the pixmaps are stored. The user of initGraph has an option of not storing the pixmap, and e.g. querying the label itself for it.
class MainWindow : public QMainWindow
{
Ui::MainWindow ui; // hold by value
...
QPixmap qpm_s1_yaw; // hold by value
QPixmap initGraph(QLabel *label) {
QPixmap pixmap{label->size()};
pixmap.fill(Qt::white);
QPainter painter{&pixmap};
//... doing some stuff ...
label->setPixmap(pixmap);
return pixmap;
}
public:
explicit MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
ui.setupUi(this);
gpm_s1_yaw = initGraph(ui.YAW1);
}
};

Qt Update QPixmapItem in QGraphicsScene

I want to have an image in my main window with the buttons laid out on top of the image. I am using view, scene and pixmap item but when I try to change the pixmap item in the slot function, I crash.
Here is an example of what I have:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
//scene, view, pixitem and button are private variables in header
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *view = new QGraphicsView(scene);
QGraphicsPixmapItem *pixitem = new QGraphicsPixmapItem;
pixitem->setPixmap(QPixmap(":/img/this.png"));
scene->addItem(pixitem);
QPushButton *button = new QPushButton(view);
this->connect(button,SIGNAL(clicked()),this,SLOT(slot()));
this->setCentralWidget(view);
}
void MainWindow:slot()
{
pixitem->setPixmap(QPixmap(":/img/that.png"));
}
Possible duplicate but this solution did not work for me:
Qt Update Pixmap of QGraphicsPixmapItem
You have shadowed the member variable pixitem because you are using
QGraphicsPixmapItem *pixitem = new QGraphicsPixmapItem;
The pixitem added to the scene will be reference by the local variable, not by the member variable. Just change to
pixitem = new QGraphicsPixmapItem;
In the constructor, you create the pixmap item:
QGraphicsPixmapItem *pixitem = new QGraphicsPixmapItem;
Then in the slot you call
pixitem->setPixmap(QPixmap(":/img/that.png"));
In order to compile successfully, you must have a QGraphicsPixmap* as a member of the class. Therefore, I conclude that this is NULL, or at least, invalid due to the creation of the item on the pointer in the constructor.
Assuming this is correct and you have indeed declared pixitem in the header of the class, change the creation in the constructor to: -
pixitem = new QGraphicsPixmapItem;

Replace THIS when moving from MainWindow to function

I have moved the following code from the MainWindow constructor to a function within the MainWindow.
void allFilters(QStringList list){
QWidget *w = new QWidget(this);
w->setFixedSize(300,200);
QVBoxLayout *vbox = new QVBoxLayout;
foreach(QString filt, list){
QCheckBox *checkbox = new QCheckBox(filt, this);
checkbox->setChecked(true);
vbox->addWidget(checkbox);
connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(cbstate(int)));
}
w->setLayout(vbox);
w->show();
}
this is now causing me problems. I assume there is an alternative but I'm unaware of what it is?
Hopefully someone can help me!
It looks like allFilters isn't a member function within MainWindow. this is only valid within non-static member functions as it points to the instance of the object.
You'll need to define it like
void MainWindow::allFilters(QStringList list)