I have used QTimer quite a bit. But right now it is failing and I can't figure it why:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui/QPushButton>
#include <QtGui/QTextEdit>
#include <QtGui/QMessageBox>
#include <QtCore/QCoreApplication>
// Server
#include <sys/socket.h>
#include <netinet/in.h>
// Client
//#include <sys/socket.h>
//#include <netinet/in.h>
#include <netdb.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QPushButton *m_btn1;
QPushButton *m_btn2;
QTextEdit *m_txt1;
QTextEdit *m_txt2;
QTimer *timerDisplay;
void UpdateDisplay();
private slots:
void handleBtn1();
void handleBtn2();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_btn1 = new QPushButton("Start", this);
m_btn1->setGeometry(QRect(QPoint(10,20), QSize(100,50)));
connect(m_btn1, SIGNAL(released()), this, SLOT(handleBtn1()));
m_btn2 = new QPushButton("Send", this);
m_btn2->setGeometry(QRect(QPoint(110, 20), QSize(100, 50)));
connect(m_btn2, SIGNAL(released()), this, SLOT(handleBtn2()));
m_txt1 = new QTextEdit("hello",this);
m_txt1->setGeometry(QRect(QPoint(10,100), QSize(300, 50)));
timerDisplay = new QTimer(this);
connect(timerDisplay, SIGNAL(timeout()), this, SLOT(updateDisplay()));
timerDisplay->start(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handleBtn1()//Start
{
if (1){
QMessageBox *msgBox = new QMessageBox(0);
msgBox->setGeometry(QRect(QPoint(200,200),QSize(400,400)));
msgBox->setInformativeText(m_txt1->toPlainText());
msgBox->exec();
}
}
void MainWindow::handleBtn2()//Send
{
}
void MainWindow::UpdateDisplay()
{
static int c = 0;
QString strC = "number: " + QString::number(c, 'd', 0);
m_txt1 = strC;
}
You forgot to:
#include <QTimer>
in your cpp file. The reason the symbol is known is because some other header along the chain of includes is doing a forward declaration of QTimer, meaning you can declare QTimer pointers and references, but not actually instantiate it.
Needless to say, you shouldn't depend on even that. Instead, change:
QTimer *timerDisplay;
to:
class QTimer *timerDisplay;
and then #include <QTimer> in the cpp file.
Another problem is that your UpdateDisplay() function is not a slot, even though you're trying to connect a signal to it. So move the declaration of that function to the private slots: section.
Related
I want to get ListItem in ListWidget that I clicked. But I can't find the way. All the things say get from text but I want the clicked one. Also I'm new in qt and c++.
stackoverflow says add more detail but I don't know how to add more detail so I write this line to get enough "detail".
Here is my .h file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <string.h>
#include <QListWidgetItem>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
class rsu
{
public:
std::string id;
std::string name;
double coorx;
double coory;
std::string ip;
int port;
};
std::vector<rsu> r;
QListWidgetItem *rsuitem;
private:
Ui::MainWindow *ui;
private slots:
void addRSU();
void deleteRSU();
};
#endif // MAINWINDOW_H
And my .cpp file:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "string"
#include "string.h"
#include "QCheckBox"
#include "QString"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->rsuWidget->hide();
connect(ui->addRSU, SIGNAL(clicked()), ui->rsuWidget, SLOT(show()));
connect(ui->cancelRSU, SIGNAL(clicked()), ui->rsuWidget, SLOT(hide()));
connect(ui->saveRSU, SIGNAL(clicked()), this, SLOT(addRSU()));
}
MainWindow::~MainWindow()
{
delete ui;
delete rsuitem;
}
void MainWindow::addRSU()
{
rsu *baz = new rsu;
baz->id = ui->ID->text().toStdString();
baz->name = ui->Name->text().toStdString();
baz->coorx = ui->CoorX->text().toFloat();
baz->coorx = ui->CoorX->text().toFloat();
baz->ip = ui->IP->text().toStdString();
baz->port = ui->Port->text().toInt();
r.push_back(*baz);
rsuitem = new QListWidgetItem(QString::fromUtf8(baz->name.c_str()),ui->listRSU);
rsuitem->setFlags(rsuitem->flags() | Qt::ItemIsUserCheckable);
rsuitem->setCheckState(Qt::Unchecked);
}
void MainWindow::deleteRSU()
{
}
And my ui:
I have created a new class for qpushbutton, I am trying to establish signal slot communication between this class and my mainwindow class
connect(&MyPushButton, &pushbutton::pb_isChecked, this, &MainWindow::MainWindowPBClicked, Qt::DirectConnection);
I used this code but as output only
qDebug("pushButtonClicked");
I can get this output. After that, the slot I called with "emit" does not work.
void pushbutton::pushButtonClicked()
{
if (isChecked())
{
qDebug("pushButtonClicked");
**emit pb_isChecked();**
}
}
all code in my project;
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow ui;
ui.show();
return app.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include "pushbutton.h"
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 MainWindowPBClicked();
private:
Ui::MainWindow *ui;
};
#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);
pushbutton MyPushButton;
connect(&MyPushButton, &pushbutton::pb_isChecked, this, &MainWindow::MainWindowPBClicked, Qt::DirectConnection);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::MainWindowPBClicked()
{
qDebug("MainWindowPBClicked");
}
pushbutton.h
#ifndef PUSHBUTTON_H
#define PUSHBUTTON_H
#include <QWidget>
#include <QPushButton>
class pushbutton : public QPushButton
{
Q_OBJECT
public:
explicit pushbutton(QWidget *parent = nullptr);
public slots:
void pushButtonClicked();
signals:
void pb_isChecked();
};
#endif // PUSHBUTTON_H
pushbutton.cpp
#include "pushbutton.h"
#include "mainwindow.h"
pushbutton::pushbutton(QWidget *parent)
: QPushButton{parent}
{
setAcceptDrops(true);
connect(this, &QPushButton::clicked, [this]() {
pushButtonClicked();
});
}
void pushbutton::pushButtonClicked()
{
if (isChecked())
{
qDebug("pushButtonClicked");
emit pb_isChecked();
}
}
CASE 1: Not creating button in UI file:
In your class MainWindow, variable MyPushButton is a local variable that gets destroyed after it end its scope in constructor. You need to create a dynamic variable of pushButton like this:
pushbutton *MyPushButton = new pushButton(this);
connect(MyPushButton, SIGNAL(pb_isChecked()), this, SLOT(MainWindowPBClicked()), Qt::DirectConnection);
CASE 2: Creating button in UI file:
In this case you cannot use your custom signal pb_isChecked(). You will need to use standard QPushButton signal such as clicked()
connect(ui->MyPushButton, SIGNAL(clicked()), this, SLOT(MainWindowPBClicked()), Qt::DirectConnection);
I wrote this small test programm so I understand QT's Signals & Slots, aswell as Multithreading, better.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QString>
#include <QStringListModel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
Ui::MainWindow *ui;
public slots:
void change_stats(QString &msg);
void insert_list(QStringListModel *model);
private:
};
#endif // MAINWINDOW_H
worker.h
#ifndef WORKER_H
#define WORKER_H
#include "mainwindow.h"
#include <QObject>
#include <QString>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(MainWindow &mw);
signals:
QString statsmsg(QString);
QStringListModel heremodel(QStringListModel*);
public slots:
void wip_list();
void wip_status();
private:
MainWindow *w;
};
#endif // WORKER_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::change_stats(QString &msg)
{
ui->statusbar->showMessage(msg);
}
void MainWindow::insert_list(QStringListModel *model)
{
ui->listView->setSelectionMode(QListView::SingleSelection);
ui->listView->setModel(model);
}
worker.h
#include "worker.h"
#include <QThread>
#include <QStringListModel>
#include <vector>
#include <chrono>
#include "ui_mainwindow.h"
#include <sstream>
Worker::Worker(MainWindow &mw)
{
w = &mw;
QThread *thread = new QThread;
this->moveToThread(thread);
connect(thread, SIGNAL(started()), this, SLOT(wip_status));
connect(w->ui->pushButton, SIGNAL(clicked()), this, SLOT(wip_list()));
connect(this, SIGNAL(heremodel(QStringListModel*)), w, SLOT(insert_list(QStringListModel*)));
connect(this, SIGNAL(statsmsg(QString)), w, SLOT(change_stats(QString)));
thread->start();
}
void Worker::wip_list(){
QStringListModel *model = new QStringListModel();
QStringList list;
std::string row = "row nr.";
for(int i = 1; i <= 10; i++){
std::stringstream rows;
rows << row << i;
list << QString::fromStdString(rows.str());
}
model->setStringList(list);
emit heremodel(model);
}
void Worker::wip_status(){
std::vector<QString> connecting = {"Connecting", "Connecting.", "Connecting..", "Connecting..."};
QString msg = "Connecting";
std::chrono::milliseconds interval = std::chrono::milliseconds(300);
while(1){
for(int i = 0; i <= 3; i++){
msg = connecting[i];
emit statsmsg(msg);
std::this_thread::sleep_for(interval);
}
}
}
main.cpp
#include "worker.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
Worker worker(w);
w.show();
return a.exec();
}
But when I run Debug it gives me this error:
error: C2280: 'QStringListModel &QStringListModel::operator =(const QStringListModel &)': attempting to reference a deleted function
I'm new here so please don't be too harsh, also if you spot something wrong not relevant to the question, please tell me. Thanks in advance for replying to my question!
Your heremodel signal is declared to return a QStringListModel by value...
QStringListModel heremodel(QStringListModel*);
Hence the error as QObject is non-copyable.
Change the signal signature to...
void heremodel(QStringListModel*);
I am trying to connect a signal from a second QMainWindow to the mainwindow. It doesn't say anything about a problem connection when the program is launched, but It doesn't work. I am not very familiar with C++ and Qt so maybe is something simple.
My code consists on a Mainwindow used as a SCADA with Start, stop, On, off buttons. In the second qmainwindow I created a terminal where you can type, start,stop... There, I would like to emit a signal to my MainWindow which is in charge of controlling the multiple threads and windows. The problem is that I cannot connect to my slot. I present here a simple overview of this two pieces of code.
Terminal. h
#ifndef TERMINAL__H
#define TERMINAL__H
#include <QMainWindow>
#include <QTextEdit>
#include <QLineEdit>
#include <QObject>
namespace Ui {
class Terminal_;
}
class Terminal_ : public QMainWindow
{
Q_OBJECT
public:
explicit Terminal_(QWidget *parent = 0);
~Terminal_();
signals:
void turnonPLC_terminal();
public slots:
void newline();
private:
Ui::Terminal_ *ui;
QTextEdit* mTerminal;
QLineEdit* mInput;
};
#endif // TERMINAL__H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "terminal_.h"
#include "terminal_help.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Terminal_ *terminal;
public slots:
void turnon_terminal();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "terminal_.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
terminal = new Terminal_(this);
connect(terminal, SIGNAL(turnonPLC_terminal()), this, SLOT(turnon_terminal()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::turnon_terminal(){
turnonPLC=1;
}
terminal_.cpp
#include "terminal_.h"
#include "ui_terminal_.h"
#include <QDockWidget>
#include <QWidget>
#include <QLineEdit>
QString on=("on");
Terminal_::Terminal_(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Terminal_)
{
ui->setupUi(this);
mTerminal = new QTextEdit();
setCentralWidget(mTerminal);
mInput = new QLineEdit();
QDockWidget* qdw = new QDockWidget;
qdw->setWidget(mInput);
addDockWidget(Qt::BottomDockWidgetArea, qdw);
connect (mInput, SIGNAL(returnPressed()),
this, SLOT(newline()));
}
Terminal_::~Terminal_()
{
delete ui;
}
void Terminal_::newline(){
QString command = mInput->text();
if (command==on){
emit turnonPLC_terminal();
}
}
Thanks
The signal-slots part in the code works perfectly. (compiled and tested with some small modifications)
After entering "on" (not On as written in question)
Terminal_::newline() slot called, turnonPLC_terminal() is fired and finally
void MainWindow::turnon_terminal() is called.
However, there are some small details the header file is called terminal_.h, not Terminal.h turnonPLC is not defined. terminal is created by not displayed (no show-call).
I guess, there are simply some many small logic errors. Try to use debugger or trace the chain of expected calls with qDebug.
I have a QTabWidget which contains a QPlainTextEdit. I have managed to add action to the QTabWidget so that whenever a new tab opens, a new QPlainTextEdit is also added in the new tab. See code.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPlainTextEdit>
#include <QMessageBox>
#include <QAction>
#include <QTextCursor>
#include <iostream>
#include <QKeyEvent>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("Tilde");
current_tab = 1;
on_action_New_triggered();
ui->tabWidget->setTabsClosable(true);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_action_New_triggered()
{
QString newTab = "Tab " + QString::number(current_tab);
ui->tabWidget->addTab(new QPlainTextEdit, newTab);
ui->tabWidget->setCurrentIndex(current_tab - 1);
current_tab++;
editor = qobject_cast<QPlainTextEdit *>(ui->tabWidget->currentWidget());
editor->setFocus();
/*connect(editor->document(), SIGNAL(cursorPositionChanged(QTextCursor)),
this, SLOT(on_editor_cursorPositionChanged()));*/
}
void MainWindow::on_actionNew_document_triggered()
{
on_action_New_triggered();
}
void MainWindow::on_action_Exit_triggered()
{
QMessageBox msg;
msg.addButton(QMessageBox::Yes);
msg.addButton(QMessageBox::No);
msg.setText("Exit program?");
int selection = msg.exec();
if (selection == QMessageBox::Yes)
qApp->exit(0);
}
// highlight current line
void MainWindow::on_editor_cursorPositionChanged()
{
QTextEdit::ExtraSelection highlight;
highlight.cursor = editor->textCursor();
highlight.format.setProperty(QTextFormat::FullWidthSelection, true);
highlight.format.setBackground( QColor(240, 246, 217) );
QList<QTextEdit::ExtraSelection> extras;
extras << highlight;
editor->setExtraSelections(extras);
}
The commented code gives compiler error:
QMetaObject::connectSlotsByName: No matching signal for
on_editor_cursorPositionChanged()
I have added the function in the header file.
Header file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPlainTextEdit>
#include <QTextCursor>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_action_New_triggered();
void on_actionNew_document_triggered();
void on_action_Exit_triggered();
void on_editor_cursorPositionChanged();
private:
Ui::MainWindow *ui;
QPlainTextEdit *editor;
qint8 current_tab;
};
#endif // MAINWINDOW_H
Could it be that your signature for the SLOT is wrong?
/*connect(editor->document(), SIGNAL(cursorPositionChanged(QTextCursor)),
this, SLOT(on_editor_cursorPositionChanged()));*/
Should be?
connect(editor->document(), SIGNAL(cursorPositionChanged(QTextCursor)),
this, SLOT(on_editor_cursorPositionChanged(QTextCursor)));
Also, the naming convention you are using for that slot might be conflicting here with your manual connection. Qt may be trying to use the connectSlotsByName mechanism on your SLOT by matching the name: on_<member>_<signal>
In this case, the current signature of that SLOT on_editor_cursorPositionChanged() would match with the QPlainTextEdit editor member. And then you are manually connecting the document to it with the wrong signature. You probably should create another slot that is named more normally docCursorPosChanged(QTextCursor)