Qt method call from another class? - c++

I got two windows(two classes), one window that opens another when i click a button.
then the user inputs something into the newly opened window and then transfer that information to the first window when a button is clicked
The problem is I can't seem to send something to the second window so i can send the user input back to the main window. I read a few places that I should use Q_object but not really sure how that works
I should mention that I am new to Qt and didn't know about the designer there is in qt creator before i was way to ahead with the program.
Hope you have some ideas to how I can do this
edit1:
I should show the relevant code i have
Mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
//alot of stuff not relevant right now creating different stuff
changeProfile= new QPushButton("ændre valgte profil",this);
profileList = new QComboBox(this);
cProfile = new CreateProfile;
connect(changeProfile,SIGNAL(clicked()),this,SLOT(ProfileChange()));
}
void MainWindow::ProfileChange()
{
file pfile(profileList->currentText().toStdString());
string tempName = pfile.read(light);
cProfile->setValue(light,tempName);
cPr
ofile->show();
}
void MainWindow::setProfileList(QString Pname_)
{
bool found = 0;
for (int i = 0;i<5;i++)
{
if (Pname_ ==profileList->itemText(i))
found = 1;
}
if (found !=1)
profileList->addItem(Pname_);
}
createProfile.cpp
CreateProfile::CreateProfile(QWidget *parent)
:QMainWindow(parent)
{
//alot of other irrelevant stuff here
saveP = new QPushButton("Save",this);
connect(saveP,SIGNAL(clicked()),this,SLOT(saveProfile()));
}
void CreateProfile::saveProfile()
{
temp = pName->text();
file pFile(temp.toStdString());
bool lights[2] = {light1->checkState(),light2->checkState()};
if (temp.length() == 0)
{
MessageBox(NULL,"Du har ikke skrevet noget navn ind\n Prov igen","Error",MB_ICONWARNING+MB_SETFOREGROUND);
}
else
{
pFile.save(lights);
//call function setProfileList
this->hide();
}
}
If that makes sence, If you need the .h file too i can show them also
I need to call setProfileList from the mainwindow in the function saveprofile(there is in createprofile window) or if there is a way i can change the combobox in the wainwindow from the createprofile window?
edit 2:
mainwindow.h
#include "createprofile.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void ProfileChange();
//some other button clicks
public:
CreateProfile *cProfile;
void setProfileList(QString Pname_);
//other irelevant stuff
private:
// and some private members
};
createProfile.h
class CreateProfile : public QMainWindow
{
Q_OBJECT
public slots:
void saveProfile();
public:
explicit CreateProfile(QWidget *parent = 0);
~CreateProfile();
//and other stuff there isnt relevant
};

You are looking for the Qt signal-slot mechanism, namely:
class SecondWindow : public QMainWindow
{
Q_OBJECT
public:
SecondWindow(QWidget *parent = Q_NULLPTR) : QObject(Q_NULLPTR)
{
// ...
connect(secondWindowButton, SIGNAL(clicked(bool)), SLOT(handleClicked()));
// ...
}
public slots:
void SecondWindow::handleClicked()
{
// Gather information from the UI as you wish
firstWindow->foo();
}
// ...
}
or, if you have a container class for the windows, you could handle it in there, too, as follows:
connect(secondWindow->myButton, SIGNAL(clicked(bool)), SLOT(handleClicked()));

I found a very different way to do this, so I have made a QComboBox in the constructor of createProfile.cpp and then I have access to the profileList this way.

Related

QSystemTrayIcon balloon message not showing on El Capitan

I want to display balloon messages with QSystemTrayIcon in my qt app on mac.
The tray icon appears in the right corner of the menu bar of mac. The problem is the balloon message won't show on El Capitan (10.11.6), but it does on Sierra (10.12) and High Sierra (10.13).
The Qt Tray Icon example works just fine on El Capitan though.
QSystemTrayIcon::isSystemTrayAvailable() and QSystemTrayIcon::supportsMessages() both return true.
I don't know what to do anymore. Here's my code:
custom tray icon class (.h)
class MyTrayIcon
{
public:
MyTrayIcon(QObject* parent = nullptr);
~ MyTrayIcon();
void balloonMsg(const QString& title, const QString& message);
QSystemTrayIcon* sysTrayIcon = nullptr;
};
custom tray icon class (.cpp)
MyTrayIcon::MyTrayIcon(QObject* parent)
{
sysTrayIcon = new QSystemTrayIcon(QIcon("my_icon.png"), parent);
}
MyTrayIcon::~MyTrayIcon()
{
delete sysTrayIcon;
}
void MyTrayIcon::balloonMsg(const QString& title, const QString& message)
{
sysTrayIcon->show(); // the icon does show
sysTrayIcon->showMessage(title, message); // the message doesn't show
}
Main window class (.h)
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Ui::MainWindow *ui;
MyTrayIcon* mTrayIcon = nullptr;
public slots:
void btnClicked();
}
Main window class (.cpp)
MainWindow::MainWindow() : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
mTrayIcon = new MyTrayIcon(this);
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(btnClicked()));
}
void MainWindow::btnClicked()
{
mTrayIcon->balloonMsg("my title", "my message");
}
Thanks in advance !

How to access this variable Qt?

Sorry the question is going to be long. I dont know how to shorten this. I am new to Qt. With a little bit of experience in c++, I thought I should start with Qt to make my programs graphical. I chose a single user library management software as a personal project.
I made a book class to get and set the name, author and uid of the book. I then made a library class to manage a vector of books. It can add presently only add a book and get a book at a particular index.
So, the code so far works fine. But I then tried to add GUI.
In the mainwindow constructor, i just added two predefined books to the library class object. The main window has 3 Line-edits to show the name, author, and uid of each book. It has two buttons "next" to show the next Book and "previous" to show the previous book.
I wanted a feature to add the book. So, created File menu and added Add Book using the Design menu. I went to slot.
What i want is to create a second window to ask for the name, author and uid of the new book. The fact is my library class object contains the details of all the books. How do i access that object so as to call addBook() function to add the book.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "library.h"
#include "dialog.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
library getLib();
private slots:
void on_next_clicked();
void on_previous_clicked();
void on_actionAdd_book_triggered();
private:
Ui::MainWindow *ui;
int currentIndex;
library l;
Dialog* d;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
book b;
b.setAuthor("Ruskin Bond");
b.setName("The Jungle Book");
b.setUid("123456789");
l.addBook(b);
b.setAuthor("Savi Sharma");
b.setName("This is not your story");
b.setUid("789456123");
l.addBook(b);
b = l.getBook(0);
ui->lineEdit->setText(QString::fromStdString(b.getName()));
ui->lineEdit_2->setText(QString::fromStdString (b.getAuthor()) );
ui->lineEdit_3->setText(QString::fromStdString(b.getUid()));
currentIndex = 0;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_next_clicked()
{
++currentIndex;
if(currentIndex < l.numOfBooks())
{
book b;
b = l.getBook(currentIndex);
ui->lineEdit->setText(QString::fromStdString(b.getName()));
ui->lineEdit_2->setText(QString::fromStdString(b.getAuthor()));
ui->lineEdit_3->setText(QString::fromStdString(b.getUid()));
}
}
void MainWindow::on_previous_clicked()
{
--currentIndex;
if(currentIndex >= 0)
{
book b;
b = l.getBook(currentIndex);
ui->lineEdit->setText(QString::fromStdString(b.getName()));
ui->lineEdit_2->setText(QString::fromStdString(b.getAuthor()));
ui->lineEdit_3->setText(QString::fromStdString(b.getUid()));
}
}
void MainWindow::on_actionAdd_book_triggered()
{
d = new Dialog(this);
d->show();
}
Dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_pushButton_clicked();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include <QMessageBox>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::on_pushButton_clicked()
{
QString temp = ui->lineEdit->text(),
temp_2 = ui->lineEdit_2->text(),
temp_3 = ui->lineEdit_3->text();
if(temp == "" || temp_2 == "" || temp_3 == "")
QMessageBox :: warning(this, "Warning!", "One of the lines is empty");
else
{
book b(temp.toStdString(), temp_2.toStdString(), temp_3.toStdString());
//how do i add the book?
}
}
This is what that appears:
Your answer
I hope the addBook in library class is to add the book into the list. You can create one connection which will pass the details of the book as follow from Dialog to Mainwindow:-
In Dialog class create one signal which will send the details of the book. For example in Dialog.h in class Dialog declare signal like this:-
signals:
void bookDetailsEntered(book b);
In Dialog.cpp emit this signal in on_pushButton_clicked():-
void Dialog::on_pushButton_clicked()
{
QString temp = ui->lineEdit->text(),
temp_2 = ui->lineEdit_2->text(),
temp_3 = ui->lineEdit_3->text();
if(temp == "" || temp_2 == "" || temp_3 == "")
QMessageBox :: warning(this, "Warning!", "One of the lines is
empty");
else
{
book b(temp.toStdString(), temp_2.toStdString(), temp_3.toStdString());
emit bookDetailsEntered(b);
}
}
Now in MainWindow.h declare one slot which will receive the details of the book like this:-
private slots:
void onBookDetailsEntered(book b);
and in MainWindow.cpp create connection from the signal in Dialog.h to the slot in Mainwindow like this:-
void MainWindow::on_actionAdd_book_triggered()
{
d = new Dialog(this);
connect(d,SIGNAL(bookDetailsEntered(book)),
this,SLOT(onBookDetailsEntered(book)));
// FYI, You can use Dialog here like Dialog d(in stack instead of heap).
// By this the d variable will get destroyed once the d is out of scope.
// Here you're creating the multiple instance of Dialog(each time when you show Dialog which will consume more memory)
}
void MainWindow::onBookDetailsEntered(book b)
{
library.addBook(b);
}
I hope i answered your question.
you need to show the dialog in your on_actionAdd_book_triggered(). i.e.
d->show();

Qt: Context menu / connect with parameters

I have a problem connecting context menu actions in Qt. I know there are plenty of similar questions around, nevertheless I couldn't find a solution yet.
I have a series of plots built using QCustomplot.
What I want to do is to create a context menu when right-clicking on the background of each plot listing all the signal present in the graph. By clicking an entry of this menu, the corresponding signal should be hidden (if currently visible) or made visible (if hidden).
Now, I've defined a class called PlotHandler of which I paste the relevant parts here below:
plotHandler.cpp
#include "plothandler.h"
PlotHandler::PlotHandler(QStringList groupNames, int startIdx, QWidget *parent) :
QWidget(parent), scrolling(false), refreshing(true)
{
pPlot = new QCustomPlot(this);
pPlot->setContextMenuPolicy(Qt::CustomContextMenu);
connect(pPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
}
void PlotHandler::contextMenuRequest(QPoint pos)
{
int i;
QMenu *menu = new QMenu(this);
for(i=0; i<pGroup->getDataLength(); i++)
{
QAction *menuEntry;
menuEntry = new QAction(pPlot->graph(i)->name(), this);
menuEntry->setProperty("graphIdx", i);
menu->addAction(menuEntry);
connect(menuEntry, SIGNAL(triggered()), this, SLOT(addRemoveGraph()));
}
menu->popup(pPlot->mapToGlobal(pos));
}
void PlotHandler::addRemoveGraph()
{
QAction *selectedSignal = qobject_cast<QAction *>(sender());
int tmp = selectedSignal->property("graphIdx").toInt();
if (pPlot->graph(tmp)->visible())
{
pPlot->graph(tmp)->setVisible(false);
}
else
{
pPlot->graph(tmp)->setVisible(true);
}
}
plotHandler.h
class PlotHandler : public QWidget
{
Q_OBJECT
public:
explicit PlotHandler(QStringList groupNames, int startIdx, QWidget *parent = 0);
QString groupRequested();
private:
QCustomPlot *pPlot;
public slots:
void contextMenuRequest(QPoint pos);
void addRemoveGraph();
}
The menu is correctly showed with the right entries and when I click on an action addRemoveGraph is called. In debug it gives back the following message:
The inferior stopped because it triggered an exception. Stopped in
thread 0 by: Exception at 0x5d6c2f9a, code: 0xc0000005: read access
violation at: 0x0, flags=0x0.
trying to execute
int tmp = selectedSignal->property("graphIdx").toInt();
Could anyone point me towards the right direction?
Thanks in advance
You use QObject::setProperty but QAction doesn't have a property named "graphIdx". When you attempt to read the "graphIdx" property from QAction you will always get an invalid QVariant.
int tmp = selectedSignal->property("graphIdx").toInt();
// tmp always is 0;
You can use QAction::setData if you need to store only one property. Otherwise, use QObject::setProperty to set a custom property on any QObject. QAction is a QObject.
Here below the solution that solved the issue.
plotHandler.cpp
#include "plothandler.h"
PlotHandler::PlotHandler(QStringList groupNames, int startIdx, QWidget *parent) :
QWidget(parent), scrolling(false), refreshing(true)
{
pPlot = new QCustomPlot(this);
pPlot->setContextMenuPolicy(Qt::CustomContextMenu);
connect(pPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
}
void PlotHandler::contextMenuRequest(QPoint pos)
{
int i;
QMenu *menu = new QMenu(this);
for(i=0; i<pGroup->getDataLength(); i++)
{
QAction *menuEntry;
menuEntry = new QAction(pPlot->graph(i)->name(), this);
menuEntry->setData(i);
menu->addAction(menuEntry);
}
connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(addRemoveGraph(QAction*)));
menu->popup(pPlot->mapToGlobal(pos));
}
void PlotHandler::addRemoveGraph(QAction *selectedSignal)
{
int tmp = selectedSignal->property("graphIdx").toInt();
if (pPlot->graph(tmp)->visible())
{
pPlot->graph(tmp)->setVisible(false);
}
else
{
pPlot->graph(tmp)->setVisible(true);
}
pPlot->replot();
}
plotHandler.h
class PlotHandler : public QWidget
{
Q_OBJECT
public:
explicit PlotHandler(QStringList groupNames, int startIdx, QWidget *parent = 0);
QString groupRequested();
private:
QCustomPlot *pPlot;
public slots:
void contextMenuRequest(QPoint pos);
void addRemoveGraph();
}
Thanks everyone for your help.

QConnect find no such slot on QCombobox by Qt Creater

I create a window which inherits from QWidget
I set a grid layout to that Window
I make a function called handleHeroChange(int index) in public slot inside that window
I add a Qcombobox to call the function handleHeroChange(int index).
Qtcreator keeps telling:
**QObject::connect: No such slot QWidget::handleHeroChange(int) in ../Testing/Window.cpp:92**
What did i do wrong?
THE CODE:
//Window.h
class Window : public QWidget
{
QGraphicsPixmapItem* avatar;
QGraphicsTextItem* heroNameItem;
QGraphicsTextItem* heroStrItem;
QGraphicsTextItem* heroDexItem;
QGraphicsTextItem* herointelItem;
public:
Window(QWidget *parent = 0);
public slots:
void handleHeroChange(int);
};
//Window.cpp
Window::Window(QWidget *parent)
: QWidget(parent)
{
QGridLayout *grid = new QGridLayout(this);
QComboBox *comboHeroClass = new QComboBox();
comboHeroClass->addItem("Witcher");
comboHeroClass->addItem("Maurander");
comboHeroClass->setCurrentIndex(1);
grid->addWidget(comboHeroClass, 2,3,1,1);
QComboBox::connect(comboHeroClass, SIGNAL(currentIndexChanged(int)),this, SLOT(handleHeroChange(int)));
}
void Window::handleHeroChange(int index){
QPixmap myImage;
if(index == 0){
}else if(index == 1){
}
}
class Window : public QWidget
{
Q_OBJECT
Add Q_OBJECT macro without semicolon to your class and rebuild your project.
Without this macro moc cannot find your class and doesn't create your slot(and some other things) That's why you get your error: you see your slot but it doesn't exist and you get runtime error

QListWidget cannot add an item dynamically

In my Qt application, I want to add a new item dynamically into a listview. Besides I also used Signal & Slot to transfer data between forms so I have created 2 following forms:
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void ReceivedData(QString item);
private slots:
void on_btnAdd_clicked();
void on_btnCancel_clicked();
private:
Ui::MainWindow *ui;
void SetUpListName();
};
addform.h
class AddForm : public QDialog
{
Q_OBJECT
public:
explicit AddForm(QWidget *parent = 0);
~AddForm();
signals:
void SendData(QString item);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::AddForm *ui;
MainWindow *main_window;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
SetUpListName();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::SetUpListName()
{
// Add 5 new elements
for (int i = 0; i < 5; i++) {
QString item = "Item " + QString::number(i);
ui->lwListItem->addItem(item);
}
}
void MainWindow::on_btnAdd_clicked()
{
// Open Add Form
AddForm add;
add.setModal(true);
add.exec();
}
void MainWindow::on_btnCancel_clicked()
{
this->close();
}
void MainWindow::ReceivedData(QString item)
{
// Check to receive data
qDebug() << "Item: " << item;
// Add a new item to list items
ui->lwListItem->addItem(item);
}
addform.cpp
AddForm::AddForm(QWidget *parent) :
QDialog(parent),
ui(new Ui::AddForm)
{
ui->setupUi(this);
main_window = new MainWindow();
connect(this, SIGNAL(SendData(QString)), main_window, SLOT(ReceivedData(QString)));
}
AddForm::~AddForm()
{
delete ui;
}
void AddForm::on_pushButton_clicked()
{
// Send data via Signal & Slot
emit SendData(ui->txtName->text());
}
void AddForm::on_pushButton_2_clicked()
{
this->close();
}
When I run the application, I got the data from Add form but the list view doesn’t add this item.
Does someone have any solutions?
Thanks!
P/S: You can download my source code at here
You are connecting the signal to the wrong object's slot. In the constructor of AddForm, you are creating a new MainWindow and connecting the signal to it's slot which means that the signal does not reach your real MainWindow, and the ReceivedData slot is adding the item to the wrong QListWidget. What you should do is this:
void MainWindow::on_btnAdd_clicked()
{
// Open Add Form
AddForm add;
connect(&add, SIGNAL(SendData(QString)), this, SLOT(ReceivedData(QString)));
add.setModal(true);
add.exec();
}
and remove the creation of a new MainWindow and corresponding connect call from the constructor of AddForm.