Replace THIS when moving from MainWindow to function - c++

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)

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.

Using QList<QGraphicsItem*>

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);
^

How to hide a temporary search bar?

I have a window that contains a browser. Up is a toolbar. In the bottom of the window is a search bar.
Search bar has a close button [x].
When the user clicks the close button I want the bar to disappear.
I want the bar only appear when user press CTRL + F. I tried to connect the close butoon with .hide() command, but application crashes. I need help.
.cpp
DocumentationWin::DocumentationWin (QWidget * parent){
docs = new QTextBrowser( this );
//Prepare toolbar
toolbar = new QToolBar( this );
//add stuff to toolbar
//Prepare footer bar
searchlabel = new QLabel(tr("Find in page:"),this);
resultslabel = new QLabel("",this);
searchinput = new QLineEdit();
findprev = new QToolButton(this);
findprev->setArrowType(Qt::UpArrow);
connect(findprev, SIGNAL(clicked()), this, SLOT (clickFindPrev()));
findnext = new QToolButton(this);
findnext->setArrowType(Qt::DownArrow);
connect(findnext, SIGNAL(clicked()), this, SLOT (clickFindNext()));
QStyle *style = qApp->style();
QIcon closeIcon = style->standardIcon(QStyle::SP_TitleBarCloseButton);
QPushButton *closeButton = new QPushButton(this);
closeButton->setIcon(closeIcon);
closeButton->setFlat(true);
connect(closeButton, SIGNAL(clicked()), this, SLOT (clickCloseFind()));
QWidget *bottom = new QWidget;
QHBoxLayout *footer = new QHBoxLayout();
casecheckbox = new QCheckBox(tr("Case sensitive"),this);
footer->setContentsMargins(5,5,5,5);
footer->addWidget(searchlabel);
footer->addSpacing(3);
footer->addWidget(searchinput);
footer->addWidget(findprev);
footer->addWidget(findnext);
footer->addSpacing(10);
footer->addWidget(casecheckbox);
footer->addSpacing(10);
footer->addWidget(resultslabel);
footer->addStretch(1);
footer->addWidget(closeButton);
bottom->setLayout(footer);
//Prepare main layout
layout = new QVBoxLayout;
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
layout->addWidget(toolbar);
layout->addWidget(docs);
layout->addWidget(bottom);
this->setLayout(layout);
this->show();
}
void DocumentationWin::clickCloseFind(){
bottom->hide();
}
.h
class DocumentationWin : public QDialog
{
Q_OBJECT
public:
DocumentationWin(QWidget * parent);
protected:
virtual void keyPressEvent(QKeyEvent *);
private slots:
void clickCloseFind();
private:
QVBoxLayout* layout;
QToolBar* toolbar;
QTextBrowser* docs;
QBoxLayout* footer;
QLabel *searchlabel;
QLabel *resultslabel;
QLineEdit *searchinput;
QToolButton *findprev;
QToolButton *findnext;
QCheckBox *casecheckbox;
QWidget *bottom;
QPushButton *closeButton;
};
Ahh, the classic case of local variables hiding the members. There have been quite a few identical questions on SO about this. This is wrong:
QWidget *bottom = new QWidget;
You want:
bottom = new QWidget;
You'll run into these problems always because you dynamically allocate all the widgets - that's completely unnecessary.
Suggestions:
Hold the child widgets and layouts by value, don't dynamically allocate them.
Don't pass a parent to widgets that are managed by a layout. Every widget that is laid out will be automatically parented.
Don't redundantly call setLayout. A QLayout takes the widget to lay its children on as a constructor argument.
QWidget::hide() is a slot.
Many widgets take the text as a constructor argument.
If you don't have any arguments to pass to the constructor in a new expression, you can drop the parentheses (but we try to avoid these anyway):
searchinput = new QLineEdit; // not QLineEdit();
Widgets shouldn't usually show() themselves upon construction. No Qt widget does that. It's up to the widget's user to do it.
C++ overloads a method call syntax with construction syntax. To differentiate the two, prefer uniform initialization (Type{arg0, arg1, ...}) over old syntax that used ().
Here's how your code can look when you're using C++11. This compiles with either Qt 4 or Qt 5. If you don't target Qt 4, you should be using the new connect syntax, though.
As you can see, there isn't a single explicit dynamic allocation - that's how quite a bit of C++11 code will look, when the used types are sane.
// https://github.com/KubaO/stackoverflown/tree/master/questions/find-hide-38082794
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
class DocumentationWin : public QDialog
{
Q_OBJECT
public:
explicit DocumentationWin(QWidget * parent = 0);
private:
QVBoxLayout layout{this};
QToolBar toolbar;
QTextBrowser docs;
QWidget bottom;
QHBoxLayout footer{&bottom};
QLabel searchlabel{tr("Find in page:")};
QLabel resultslabel;
QLineEdit searchinput;
QToolButton findprev;
QToolButton findnext;
QCheckBox casecheckbox{tr("Case sensitive")};
QPushButton closeButton;
Q_SLOT void onFindPrev() {}
Q_SLOT void onFindNext() {}
};
DocumentationWin::DocumentationWin(QWidget * parent) : QDialog(parent) {
findprev.setArrowType(Qt::UpArrow);
connect(&findprev, SIGNAL(clicked()), this, SLOT(onFindPrev()));
findnext.setArrowType(Qt::DownArrow);
connect(&findnext, SIGNAL(clicked()), this, SLOT(onFindNext()));
auto style = qApp->style();
auto closeIcon = style->standardIcon(QStyle::SP_TitleBarCloseButton);
closeButton.setIcon(closeIcon);
closeButton.setFlat(true);
connect(&closeButton, SIGNAL(clicked(bool)), &bottom, SLOT(hide()));
footer.setContentsMargins(5,5,5,5);
footer.addWidget(&searchlabel);
footer.addSpacing(3);
footer.addWidget(&searchinput);
footer.addWidget(&findprev);
footer.addWidget(&findnext);
footer.addSpacing(10);
footer.addWidget(&casecheckbox);
footer.addSpacing(10);
footer.addWidget(&resultslabel);
footer.addStretch(1);
footer.addWidget(&closeButton);
layout.setContentsMargins(0,0,0,0);
layout.setSpacing(0);
layout.addWidget(&toolbar);
layout.addWidget(&docs);
layout.addWidget(&bottom);
}
int main(int argc, char ** argv) {
QApplication app{argc, argv};
DocumentationWin win;
win.show();
return app.exec();
}
#include "main.moc"

qt use widget crash

I have a class :
class gameClientInteraction : public QMainWindow
with, in the .h :
private :
QTextEdit* console;
my constructor is like this :
gameClientInteraction::gameClientInteraction()
{
// Menus
QMenu *menuFichier = menuBar()->addMenu("&Jeu");
QAction *actionQuitter = new QAction("&Quitter", this);
menuFichier->addAction(actionQuitter);
connect(actionQuitter, SIGNAL(triggered()), qApp, SLOT(quit()));
// View
QGraphicsView *theGraphicsView = new QGraphicsView(this);
theGraphicsView->setFixedSize(605,605);
QTextEdit* console = new QTextEdit(this);
console->setGeometry(0,625,600,100);
console->setReadOnly(true);
console->append("Bienvenue !");
setCentralWidget(theGraphicsView);
//Scene
theGraphicsView->setScene(m.afficheMap());//afficheMap give me a QGraphicsScene*
}
I have this function that crash my program when I launch it (it 's okay when I comment the instruction).
void gameClientInteraction::msgConsole(QString msg){
console->append(msg);
}
So why is it crashing with this instruction?
You've hidden the class member variable console in your constructor by declaring a local pointer with the same name. In other words, this:
QTextEdit* console = new QTextEdit(this);
should be this:
console = new QTextEdit(this);
As an alternative, consider using an initialization list:
gameClientInteraction::gameClientInteraction() : console(new QTextEdit(this))
{
// constructor code goes here
console->setGeometry(0,625,600,100);
console->setReadOnly(true);
console->append("Bienvenue !");
}

Qt No matching function for call to mainWindow::connect()

I'm trying to connect a combo box value and a label such that when the combo box changes the label reflects that. I have googled my heart out trying to find an answer but, as of yet, nothing has worked; I still get the error:no matching function for call to mainWindow::connect(QComboBox*&, const char [38], QString*, const char [26])
I have tried QObject::connect, QWidget::connect and anything else dealing with Qt, but to no avail.
Creating a label that says the combo box value is not my final intention for the program. Rather, I wish to get it working with a simple label then change it to what I want it to display (thus the tempLabel).
mainwindow.h:
class MainWindow : public QMainWindow
{
public:
MainWindow();
private slots:
QString getClass(QComboBox *box);
};
mainwindow.cpp:
MainWindow::MainWindow()
{
QString qMathClassName;
QComboBox* mathClassCombo = new QComboBox;
QLabel* label = new QLabel(qMathClassName);
// omitting layout code...
connect(mathClassCombo, SIGNAL(currentIndexChanged(const QString &)),
&qMathClassName, SLOT(getClass(mathClassCombo)));
}
QString MainWindow::getClass(QComboBox *box)
{
return box->currentText();
}
Any help would be greatly appreciated!
You are connecting a signal to a slot with a different signature. You have to change your slot to something like
getClass(const QString &)
to match currentIndexChanged signal.
I think you need to read Qt's signals and slots documentation. Again, if you've already done so. Pay special attention to their examples.
I think that you had these misconceptions about Qt in C++:
That QLabel takes a reference to a QString, and that it will update its text when that string changes. It won't. QLabel will display the value of the string when you give it the string. That is the only time it will update.
That objects constructed on the stack will not be destroyed at the end of the function. They will not. At the end of the constructor, qMathClassName will be destroyed and any reference to it will become invalid. Thus, you'd not want to make a connection to it, even if you could.
That the third argument of QObject::connect is a pointer to a place to put the return value for the slot. It's not. The third argument is a pointer to the QObject on which to call the slot. The return value of a slot is unused for any calls made to it via QObject::connect.
That you can bind values to slots in your connection. Unfortunately not. Within the SLOT macro, you must put the function signature of the slot. You may not reference any variables. The arguments section must have only class names. That is SLOT(getClass(QComboBox*)), not SLOT(getClass(mathClassCombo)).
The simplest way to ensure the contents of a combo box are displayed in a label are this:
QComboBox* mathClassCombo = new QComboBox;
QLabel* tempLabel = new QLabel;
connect(mathClassCombo, SIGNAL(currentIndexChanged(const QString&)),
tempLabel, SLOT(setText(const QString&)));
If you want to do something more complicated, I recommend just making a slot on your window that can handle those complications. For example:
mainwindow.h:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
private slots:
void updateLabelText(const QString& className);
private:
QComboBox* mathClassCombo;
QLabel* tempLabel;
}
mainwindow.cpp:
MainWindow::MainWindow()
{
mathClassCombo = new QComboBox;
tempLabel = new QLabel;
// omitting layout code...
connect(mathClassCombo, SIGNAL(currentIndexChanged(const QString&)),
this, SLOT(updateLabelText(const QString&)));
}
void MainWindow::updateLabelText(const QString& className)
{
QString newLabelString = className + " is the best class ever!";
tempLabel->setCurrentText(newLabelString);
}