I'm fairly new to Qt and I'm trying to work with Signals and Slots and I'm having a bit of trouble creating custom Slots:
public slots:
void resetUrl(){
this->load(QUrl("http://www.google.com"));
}
(Then, in my main.cpp)
#include <QWebView>
#include <QPushButton>
QWebView *web = new QWebView(mainwindow);
QPushButton *button = new QPushButton(mainwindow);
web->load(QUrl("http://www.yahoo.com"));
button->setText("Google");
QObject::connect(button, SIGNAL(clicked()), web, SLOT(resetUrl()));
Thats about all I got, any help is appreciated. What it says when I try to run this is "'class google' has no member named 'load'".
I'm sure your class has no load function, you want web->load(url) NOT this->load(url)
Related
I am new to Qt. I want to make a game with many different screens (e.g. Main Screen, Loading Screen...), but in a single window, switched by index in a QstackWidget. When switching to the Main Screen, it should play a background music continuously. Searching the web, I found QMediaPlayer with QMediaPlayerlist can do the trick. So I tried like this (using a basic QMainWindow to simplify the code):
QtWidgetApplication1.h
#pragma once
#include <QtWidgets/QMainWindow>
#include <QMediaPlayer>
#include <QMediaPlaylist>
class QtWidgetsApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtWidgetsApplication1(QWidget *parent = Q_NULLPTR);
void playAudio();
void stopAudio();
private:
QMediaPlayer* player;
QMediaPlaylist* playList;
};
QtWidgetApplication1.cpp
#include "QtWidgetsApplication1.h"
QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent)
: QMainWindow(parent)
{
playAudio();
}
void QtWidgetsApplication1::playAudio() {
player = new QMediaPlayer();
playList = new QMediaPlaylist();
playList->addMedia(QUrl::fromLocalFile("main_theme.mp3"));
playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
player->setPlaylist(playList);
player->play();
}
void QtWidgetsApplication1::stopAudio() {
player->stop();
delete player;
delete playList;
player = Q_NULLPTR;
playList = Q_NULLPTR;
}
main.cpp
#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtWidgetsApplication1 w;
w.show();
return a.exec();
}
Error:
It only plays the audio once, and shows an error message
QObject::startTimer: Timers can only be used with threads started with
QThread
Note:
I've tried (1.) using QMediaPlayer only and detecting QMediaPlayer::endOfMedia signal, (2.) QSound with a .wav file. First approach cannot get QMediaPlayer::endOfMedia signal but get QMediaPlayer::pauseState signal, however, I still fail to replay the audio. Second approach doesn't even play the audio and shows a QEventLoop error.
Enviroment:
Windows 10
Qt 5.15.2 MSVC2019 X64
Visual Studio 2019
Instead of adding QT += multimedia in the .pro file, which the projects in VS doesn't have, I tried to include those .lib to the project settings (Refer to How to add Qt libraries to visual studio). Actually, the best way to include QtMultiMedia is: go to
Extensions (in VS) > Qt VS tools > Qt Project Settings > General > Qt Modules and select the modules you want to include. By including the right modules, the problem I have faced has gone.
I am implementing a simple function where slider value is constantly displayed on label and qDebug(). I already got the label updated using signal/slots, but somehow the qDebug() thread is not working properly. I expected to see the console flooded with the value of the slider.
Below is my code:
SliderThread.h:
class HorizontalSliderThread : public QThread {
Q_OBJECT
public:
HorizontalSliderThread(Ui::MainWindow *ui);//in order to call slider value in HorizontalSliderThread class
~HorizontalSliderThread();
public slots:
void process();
private:
};
SliderThread.cpp
HorizontalSliderThread::HorizontalSliderThread(Ui::MainWindow *ui){
ui_global = *ui;
}
void HorizontalSliderThread::process(){
qDebug("Test Thread");
int value = ui_global.horizontalSlider_windowSize->value();
QObject::connect(ui_global.horizontalSlider_windowSize,SIGNAL(valueChanged(int)),ui_global.label_SliderWindowSize,SLOT(setNum(int)));//update value to label
qDebug()<<value; //update value in console
}
mainwindow.h
move Ui::MainWindow *ui; from private to public.
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThread* thread = new QThread;
HorizontalSliderThread* slider = new HorizontalSliderThread(ui);
slider->moveToThread(thread);
connect(thread, SIGNAL(started()), slider, SLOT(process()));
thread->start();
}
Current Output: qDebug() displays the value of slider once, label is updated constantly.
Expected Output: qDebug() displays the value of slider continuously, label is updated constantly.
Since label is updated when the slider is moved, then the signal/slot for this function is working, which means my thread should be working. Don't know what I'm doing wrong.
QThread implementation is reference from: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
I am fairly new to this, especially QThread, so if there is a better way to implement this function, please let me know!
Thanks a lot.
EDIT1: add slider->moveToThread(thread);
Well you've only connected the started() signal to your process() function, so your thread starts and it calls process, which dutifully shows your debug output and returns.
I suspect you want to call your process function every time the value changes, which would require another signal/slot connection (along these lines):
connect(ui_global.horizontalSlider_windowSize, SIGNAL(valueChanged(int)), thread, SLOT(setNum(int)));
Also, it looks like you intend for your HorizontalSliderThread to actually run in that separate thread you've created, in which case you'll need a call to QObject::moveToThread() in there, something along these lines:
slider->moveTothread(thread);
I have a basic doubt about how signals and slots actually work. Here's my code segment.
finddialog.cpp :
#include "finddialog.h"
#include <QtGui>
#include <QHBoxLayout>
#include <QVBoxLayout>
FindDialog::FindDialog(QWidget *parent) : QDialog(parent) {
//VAR INITIALIZATIONS
label = new QLabel(tr("Find &what:"));
lineEdit = new QLineEdit;
label->setBuddy(lineEdit);
caseCheckBox = new QCheckBox(tr("Match &case"));
backwardCheckBox = new QCheckBox(tr("Search &backward"));
findButton = new QPushButton("&Find");
findButton->setDefault(true);
findButton->setEnabled(false);
closeButton = new QPushButton(tr("&Quit"));
//SIGNALS & SLOTS
connect (lineEdit, SIGNAL(textChanged(const QString&)),this, SLOT(enableFindButton(const QString&)));
connect (findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
connect (closeButton,SIGNAL(clicked()), this, SLOT(close()));
//Layout
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
topLeftLayout->addWidget(lineEdit);
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addLayout(topLeftLayout);
leftLayout->addWidget(caseCheckBox);
leftLayout->addWidget(backwardCheckBox);
QVBoxLayout *rightLayout = new QVBoxLayout;
rightLayout->addWidget(findButton);
rightLayout->addWidget(closeButton);
rightLayout->addStretch();
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout(leftLayout);
mainLayout->addLayout(rightLayout);
//Complete window settings
setLayout(mainLayout);
setWindowTitle(tr("Find"));
setFixedHeight(sizeHint().height());
}
//Function Definition
void FindDialog::findClicked() {
QString text = lineEdit->text();
Qt::CaseSensitivity cs = caseCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
if(backwardCheckBox->isChecked())
emit findPrevious(text, cs);
else
emit findNext(text,cs);
}
void FindDialog::enableFindButton(const QString &text1) {
findButton->setEnabled(!text1.isEmpty());
}
With this code, how does the compiler know what is passed to enableFindButton(QString &) function. There are no function calls to enableFindButton(). In the connect statement there is a reference to enableFindButton() but isn't that more like a prototype because we are not providing the name of the variables to work with in its arguments?
connect (lineEdit, SIGNAL(textChanged(const QString&)),this, SLOT(enableFindButton(const QString&)));
Here only (const QString &) is the argument and a variable is not given. How does the application know what its argument is without passing it explicitly?
void FindDialog::enableFindButton(const QString &text1) {
findButton->setEnabled(!text1.isEmpty());
}
Here also &text1 is a reference argument. But to what ? I don't understand anything now after typing this all!
:-|
Qt is generating the code that makes it work when you build the project.
SIGNAL, SLOT, etc are preprocessor macros defined in qobjectdefs.h
These are then picked up by moc in QT when you build your project, and all the code required is generated, then compiled.
A decent page that explains this in more detail can be found here
C++ source code is processed by Qt meta object compiler (moc). It generates 'signatures' strings for QObject slots. Signatures contain method name and arguments (types, arguments' names do not matter in signatures). Whenever signal is emitted a signature match is performed directly (in case of direct connections) or in the event loop (for queued connections), and corresponding method is called. Moc compiler generates all necessary code that will match signatures and call the methods. If interested, look inside of one of those *.cxx files generated.
I just started using Qt and learned of QTimers. Unfortunately, they seem to give an error and I have not seen this error described online yet:
error: C2514: 'QTimer' : class has no constructors.
I have my QTimer declared in the private section of dialog.h :
QTimer* timer;
And I instantiate it as such:
timer = new QTimer(this);
in dialog.cpp.
As this error does not show many results in a google search I am convinced I did something unthinkably dumb, but I have no idea what it is that I did wrong. Could someone please explain to me what it was that I did?
So in your .h file you should have
QTimer * timer;
and in your constructor you should have
timer = new QTimer();
and at the top of your header file you should have:
#include <QTimer>
And you shouldn't have any of your own classes named QTimer.
Hope that helps.
I am just getting my feet wet with Qt, I am trying to pull the string from a QlineEdit and append it to a QTextBrowser after clicking a button(for simplicity/error checking I am just having it append the word appended at the moment).
The program runs, and the GUI gets brought up on the screen, but whenever I click the button, my program seg faults.
Here's my code, I cut a lot out that was unnecessary:
HEADER:
#ifndef TCD2_GUI_H
#define TCD2_GUI_H
//bunch of includes
class TCD2_GUI : public QWidget
{
Q_OBJECT
public:
TCD2_GUI(QWidget *window = 0);
//bunch of other members
QLineEdit *a1_1;
QTextBrowser *stdoutput;
public slots:
void applySettings(void);
private:
};
#endif // TCD2_GUI_H
and here is the snippet of the cpp of which causes the fault
QTextBrowser *stdoutput = new QTextBrowser();
stdoutput->append("Welcome!");
QObject::connect(apply, SIGNAL(clicked()), this, SLOT(applySettings()));
//------------------------------------------------------Standard Output END
//layout things
}
void TCD2_GUI::applySettings()
{
stdoutput->append("appended");
}
stdoutput in your applySettings() function refer to the member of the TCD2_GUI class whereas stdoutput in your piece of code where the crash happens is a local variable.
Try to add in your constructor by example:
stdoutput = new QTextBrowser();
andremove the following line from your piece of code:
QTextBrowser stdoutput = new QTextBrowser();
looking at the code provided, my guess would be stdoutput is declared twice. Once as a member of the *TCD2_GUI* class, second time as a local variable in the method (class constructor?) where you do layout. ApplySettings uses a class member which is not initialized, hence segmentation fault.
Changing your code to:
stdoutput = new QTextBrowser();
stdoutput->append("Welcome!");
QObject::connect(apply, SIGNAL(clicked()), this, SLOT(applySettings()));
might fix the problem.
hope this helps, regards