Here, I am just trying to obtain the changed int value from QSpinBox by using SIGNAL and SLOTS because I need to use this int variable in my another function. I mean if the user changes QSpinBox values, it changes the value of int variable.
I know this SIGNAL will be SIGNAL(valueChanged(int)), but I got confused about what the SLOT will be in this case. I really got stack on this point.
EDIT:
What I have tried is following. MainWindow.h is
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void setFrame(int frame);
MainWindow.cpp is following. To check how it is working I tried to display the int in a QLabel.
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->spinBox, SIGNAL(valueChanged(int)), this, SLOT(setFrame(int frame)));
}
void MainWindow::setFrame(int frame)
{
ui->label->setText(QString::number(frame));
}
Can anyone fix this regarding how to get the changed int value from QSpinBox?
Thanks in advance.
As the documentation states (in this document about QObject Class):
Note that the signal and slots parameters must not contain any variable names
So your mistake is specifying the variable name in the slot SLOT(setFrame(int frame)). As you must only use the variable type, it would be instead SLOT(setFrame(int)).
Anyway, if that's the only objective of the connect, I would rather do:
connect(ui->spinBox, SIGNAL(valueChanged(int)), ui->label, SLOT(setNum(int)));
That way, you don't even need the method setFrame in your MainWindow and labels already have a way to show numbers instead of strings.
Hope this helps!
Related
I'm new to any form of programming but have to do a project with Qt for my "programming for engineers" course where we simultaneously learn the basics of c++.
I have to display a text from one lineEdit to a lineEdit in another window.
I have a userWindow that opens from the mainWindow and in this userWindow I have a lineEdit widget that displays the current selected user as a QString (from a QDir object with .dirName() ). But now I have to display the same String in a lineEdit in the mainWindow as well.
From what I've read I have to do this with "connect(...)" which I have done before with widgets inside a single .cpp file but now I need to connect a ui object and signal from one window to another and I'm struggling.
My idea /what I could find in the internet was this:
userWindow.cpp
#include "userwindow.h"
#include "ui_userwindow.h"
#include "mainwindow.h"
#include <QDir>
#include <QMessageBox>
#include <QFileDialog>
#include <QFileInfo>
QDir workingUser; //this is the current selected user. I tried defining it in userWindow.h but that wouldn't work how I needed it to but that's a different issue
userWindow::userWindow(QWidget *parent) : //konstruktor
QDialog(parent),
ui(new Ui::userWindow)
{
ui->setupUi(this);
QObject::connect(ui->outLineEdit, SIGNAL(textChanged()), mainWindow, SLOT(changeText(workingUser) //I get the error " 'mainWIndow' does not refer to a value "
}
[...]
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QDir>
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void changeText(QDir user); //this is the declaration of my custom SLOT (so the relevant bit)
private slots:
void on_userButton_clicked();
void on_settingsButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "userwindow.h"
#include "settingswindow.h"
#include "click_test_target.h"
#include "random_number_generator.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
[...]
}
[...]
//here I define the slot
void MainWindow::changeText(QDir user)
{
QString current = user.dirName();
ui->userLine->insert("The current working directory is: "); //"userLine" is the lineEdit I want to write the text to
ui->userLine->insert(current);
}
I know I'm doing something wrong with the object for the SLOT but can't figure out how to do it correctly.
If anyone could help me I would be very grateful.
Alternatively: perhaps there is another way to mirror the text from one lineEdit to another over multiple windows. If anybody could share a way to do this I would be equally grateful. Is there maybe a way to somehow define the variable "QDir workingUser;" in such a way as to be able to access and overwrite it in all of my .cpp files?
Thank you in advance for any help. Regards,
Alexander M.
"I get the error 'mainWindow' does not refer to a value"
I don't see you having any "mainWindow" named variable anywhere,
but you also mentioned that the MainWindow is the parent, which means you could get reference anytime, like:
MainWindow *mainWindow = qobject_cast<MainWindow *>(this->parent());
Also, your signal-handler (changeText(...) slot) should take QString as parameter (instead of QDir), this way you handle how exactly the conversion is handled, in case users type some random text in input-field (text-edit).
void changeText(const QString &input);
Finally, you either need to specify type:
QObject::connect(ui->outLineEdit, SIGNAL(textChanged(QString)), mainWindow, SLOT(changeText(QString));
Or, use the new Qt-5 syntax:
connect(ui->outLineEdit, &QLineEdit::textChanged,
mainWindow, &MainWindow::changeText);
You can create new signal (same params as lineEdit's textChanged) to userWindow which is connected to the textChanged signal of the lineEdit. Then connect that signal userWindow to mainWindow's slot.
//In userWindow.h
signals:
void textChanged(const QString&);
//In userWindow.cpp
connect(ui.lineEdit, &QLineEdit::textChanged, this, &userWindow::textChanged);
//In mainWindow.cpp
connect(userWindow, &userWindow::textChanged, this, &mainWindow::onTextChanged
Then in onTextChanged write the same text to mainWindow's lineEdit
Background
I am writing a media player application in Qt. I have subclassed QMediaPlayer and created a new SLOT which is capable of interpreting an int and passing it as qint64 to QMediaPlayer::SetPosition(qint64).
QMediaPlayer::PositionChanged fires a signal to the cslider slider_playback (a horizontal slider subclass). This makes the slider move as a song is playedback. There are also some subclassed labels (clabel) which receive signals regarding the song duration and song playback position.
Problem
The problem i have occurs when I build & run, I receive the following error:
Starting /home/daniel/DeveloperProjects/build-Player-Desktop_Qt_5_9_1_GCC_64bit-Debug/Player...
QObject::connect: No such slot QMediaPlayer::set_playback_position(int) in ../Player/mainwindow.cpp:23
QObject::connect: (sender name: 'slider_playback')
The slider should be able to control the position of the playback. The offending line of code is preceeded by a '// Player seek' comment in the file.
I think the error indicates that the base class is being referred to for the SLOT, whereas the slots is actually part ofthe derived class.
Why is this error occuring and what action would resolve the issue? The slots in my clabel and cslider classes work without issue. The difference is that those classes have constructors and destructors. I have not implemented a constructor in the QMediaPlayer subclass as I do not want to override the base class constructor.
cmediaplayer.h (full file)
#ifndef CMEDIAPLAYER_H
#define CMEDIAPLAYER_H
#include <QMediaPlayer>
//#include <QObject>
class cmediaplayer : public QMediaPlayer
{
Q_OBJECT
public slots:
void set_playback_position(int);
};
#endif // CMEDIAPLAYER_H
cmediaplayer.cpp (full file)
#include "cmediaplayer.h"
void cmediaplayer::set_playback_position(int v) {
this->setPosition( (qint64)v );
}
mainwindow.h (full file)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMediaPlayer>
#include "cmediaplayer.h"
#include "clabel.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QPalette m_pal;
QString media_file_str="/usr/share/example-content/Ubuntu_Free_Culture_Showcase/Jenyfa Duncan - Australia.ogg";
//QMediaPlayer * player ;
cmediaplayer * player; // My custom type
private slots:
void on_pushButton_pressed();
void on_pushButton_released();
void on_button_playback_clicked();
};
mainwindow.cpp (full file)
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
ui->setupUi(this);
//player = new QMediaPlayer;
player = new cmediaplayer; // My custom type
// set max time on playback slider
connect(player, SIGNAL(durationChanged(qint64)), ui->slider_playback, SLOT(set_qint64_max(qint64)));
// st max time on playback label
connect(player, SIGNAL(durationChanged(qint64)), ui->label_track_length, SLOT(setIntText(qint64)));
// set slider playback position
connect(player, SIGNAL(positionChanged(qint64)), ui->label_track_position, SLOT(setIntText(qint64)));
// Player seek
connect(ui->slider_playback,
SIGNAL(valueChanged(int)),
player,
SLOT(set_playback_position(int)));
// Player volume
connect(ui->slider_volume,SIGNAL(valueChanged(int)),player,SLOT(setVolume(int)));
ui->slider_volume->setValue(50); // set player initial value
}
MainWindow::~MainWindow() {
delete ui;
delete player;
//delete playlist;
}
void MainWindow::on_pushButton_pressed() {
m_pal=this->palette().color(QPalette::Background);
QPalette pal=palette();
pal.setColor(QPalette::Background,Qt::gray);
this->setAutoFillBackground(true);
this->setPalette(pal);
player->setMedia(QUrl::fromLocalFile(media_file_str));
player->setPlaybackRate(1);
player->play();
}
void MainWindow::on_pushButton_released() {
QPalette pal=m_pal;
this->setAutoFillBackground(true);
this->setPalette(pal);
//player->stop();
}
void MainWindow::on_button_playback_clicked()
{
//player->play();
}
Qt creates a new class that implements the actual connection between the slots and the signals but many times this one is not updated. The classes they refer to have a name similar to moc_xxx.cpp and these are created in the build folder.
To force them to update we must click on the make clean submenu that is located in the Menu Build of QtCreator, and then run qmake in the same menu.
Or you can manually remove the build folder and compile it back
Perhaps, it could help somebody. I had a similar issue when trying to use a SLOT function in the connect call. Even though the slot was declared and defined in the subclass, the connect function not recognize it, issuing a message which says that the slot function is not part of the base class.
In my case, the problem was that I didn't place the Q_OBJECT in the beginning of the class declaration. After that, I had to clean (otherwise, various errors occur in compilation step) and build the project again to had the slot function working properly.
I'm really stuck on one problem that I want to solve. the problem is that I have a Class for QMainWindow which holds the Ui variable for that form. Now I want to be able to edit that Form using the Ui variable in that class on a QDialog cpp file. I probably sound really stupid and I really have no idea how I should explain this, but I have code which maybe can help.
MainWindow.h:
#include "ui_mainwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
Ui::MainWindow *ui;
}
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"
Dialog *dialog;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
dialog = new Dialog(this);
dialog->show();
}
QDialog.cpp:
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
Ui::MainWindow *mainui;
void Dialog::on_pushbutton_clicked(){
mainui->label->setText("test");
}
So as you can see from the above code, it shows that I have a pointer to the Ui variable however its uninitialised, therefore it would lead to a SIGSEGV error, so how to do Initialize this pointer? any help here is highly appreciated, and even though this is probably really simple I just don't know what to do. (I have looked at other questions but I couldn't quite grasp what to do, so please explain what I am to do before linking me to a similar question. Also, I have left out the Dialog.h file as I didn't think it was needed, please tell me if I need to show it, thanks!).
Generally in C++ you should practice what is called encapsulation - keep data inside a class hidden from others that don't need to know about it. It's not good to have multiple pointers to the UI object as now all those other objects have to know how the main window UI is implemented.
In this case, what I would recommend is to use Qt's signals and slots mechanism to allow the dialog to tell the main window what you need it to do. That has the advantage that if you add more dialogs, or change how things are implemented in the main window, you don't need to alter the signal slot mechanism, and the details are hidden cleanly.
So - for your dialog, add a signal like this in the header file
class Dialog : QDialog
{
Q_OBJECT
signals:
void setTextSignal(QString text);
}
and in your main window header, add a slot.
class MainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void setTextSlot(const QString &text);
}
now in your method where the button is pressed,
void Dialog::on_pushbutton_clicked()
{
emit setTextSignal("test");
}
and in your main window
void MainWindow::setTextSlot(const QString &text)
{
mainUi->label->setText(text);
}
The final part is to connect the signal and slot together, which you would do in your main window function where you create the dialog:
void MainWindow::on_pushButton_clicked()
{
dialog = new Dialog(this);
connect(dialog, SIGNAL(setTextSignal(QString)), this, SLOT(setTextSlot(QString)));
dialog->show();
}
You can see there are many advantages to this; the Dialog no longer needs a pointer to the main window UI, and it makes your code much more flexible (you can have other objects connected to the signals and slots as well).
Short answere - your can't! If you want to create a new instance of the ui, you would have to do:
MainWindow::Ui *ui = new MainWindow::UI();
ui->setupUi(this);
However, the this-pointer for a UI created for a QMainWindow based class must inherit QMainWindow - thus, you can't.
In general, it is possible if you create your Ui based on a QWidget instead of a QMainWindow, since both inherit QWidget.
Alternativly, you could try the following:
QMainWindow *subWindow = new QMainWindow(this);
subWindow->setWindowFlags(Qt::Widget);
MainWindow::Ui *ui = new MainWindow::UI();
ui->setupUi(subWindow );
//... add the mainwindow as a widget to some layout
But I would guess the result will look weird and may not even work in the first place.
Started learning the basics of Qt a few days ago and my question involves the following:
- Qt designer (UI)
- promoted classes
With Qt designer (or even without it I believe), to "catch signals" or create an event, we can do something like create a private slot like this: "on_[widget_name]_[signal_name]." The following code works and I have no problems here:
#include "custom.h"
#include "ui_custom.h"
#include <QDebug>
CustomWidget::CustomWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::CustomWidget)
{
ui->setupUi(this);
// ui->horizontalLayout->setContentsMargins(0,0,0,0);
// ui->horizontalLayout->setAlignment(Qt::AlignLeft);
}
CustomWidget::~CustomWidget()
{
delete ui;
}
void CustomWidget::on_widthInput_valueChanged(int value){
qDebug() << "test";
}
My question is Is there a way to define the same on_[widget]_[signal] event in a promoted class?
In other words, pretend there is a GCWidget::GCWidget(QWidget *parent) : QWidget(parent) but it is only a promoted class from Qt Designer. It has the same void function on_widthInput_valueChanged but unfortunately, "test" will not be outputted.
The reason I want to do this is obviously, I don't want to have all my code polluted in one parent class for my UI. I read that the idea of the promoted class is to give me the possibility of separating these classes but when I created that same "on_..." function, it did not work. Any thoughts?
This might come off as a very stupid question, but I have to write a very simple program, consisting of a line edit and push button.
This program has to be able to take inputs(numbers) from the user in the line edit area and every time the push button is pressed, store the number values within an array of size 10.
I have some experience with C++ but am just generally very confused with the GUI aspects of Qt. The GUI stuff is just way over my head so I apologize again if this is trivial! But if anyone could help me figure out how to do this you would be the coolest.
Thanks!
Things need to do
set a button and a lineedit either in ui or in constructor of mywindows.
set validator for int.
declare a slot for button, to pass the int in lineEdit to your data structure.
fixed array is not enough to store all the user input, you need to think about whether you need is a list, a dynamic array, a fixed array of stack or queue.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QList>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QList<int> m_list;
};
#endif // MAINWINDOW_H
mainwindows.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lineEdit->setValidator(new QIntValidator(0, 9999, this));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
m_list.append(ui->lineEdit->displayText().toInt());
qDebug() << m_list;
}
Put lineEdit and button on form in Qt Designer or create it by yourself:
Create slot in header:
private slots:
void mySlot();
//do connection in dialog's constructor
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(mySlot()));
//Write slot
void Dialog::mySlot()
{
QString str = ui->lineEdit->text()
//now str contains all your text you can put it in different arrays.
}
text() return QString, but if you sure that it is double, then call toDouble() method
QString str = ui->lineEdit->text().replace(",",".")
double var = str.toDouble();
Moreover you can set QDoubleValidator to lineEdit and user can input only double in this lineEdit. Search in web what validator is and use setValidator() method to set it to lineEdit.