I have a problem with my Qt code. I wanted to write an program which are taking a coordinates of point and then that point is drawing in point with that coordinates. My program doesn't have any errors or warnings when i built it but it's crashing at start(MainWindow doesn't show). This is my code:
main.cpp
#include < QApplication >
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow win;
win.show();
return app.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QAction>
#include <QToolBar>
#include <QTextCodec>
#include <QObject>
#include <QDialog>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
#include "addpoint.h"
class MainWindow: public QMainWindow
{
Q_OBJECT
private:
QToolBar *AddToolbar;
QAction *AddPointAction;
AddPoint *AddPointDialog;
QLineEdit *x;
public:
MainWindow();
void createToolbar();
void createActionAdd();
signals:
public slots:
void PointClicked();
void DialogAccepted();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow()
{
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
createActionAdd();
createToolbar();
connect(AddPointAction, SIGNAL(triggered(bool)), this, SLOT(PointClicked()));
connect(AddPointDialog, SIGNAL(accepted()), this, SLOT(DialogAccepted()));
setMinimumSize(480, 320);
}
/**/
void MainWindow::createToolbar()
{
AddToolbar = new QToolBar;
AddToolbar->addAction(AddPointAction);
addToolBar(AddToolbar);
}
/**/
void MainWindow::createActionAdd()
{
AddPointAction = new QAction("Add Road", this);
x = new QLineEdit(this);
x->setFixedSize(100, 30);
x->move(100, 100);
}
/**/
void MainWindow::PointClicked()
{
AddPointDialog = new AddPoint(this);
AddPointDialog->setModal(true);
AddPointDialog->exec();
}
/**/
void MainWindow::DialogAccepted()
{
x->setText("abc");
}
addpoint.h
#ifndef ADDPOINT_H
#define ADDPOINT_H
#include <QWidget>
#include <QTextCodec>
#include <QDialog>
#include <QObject>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
class AddPoint : public QDialog
{
Q_OBJECT
private:
QLabel *XpointL;
QLineEdit *XPoint;
QPushButton *OKButton;
public:
AddPoint(QWidget *parent);
void createButton();
signals:
public slots:
};
#endif // ADDPOINT_H
addpoint.cpp
#include "addpoint.h"
AddPoint::AddPoint(QWidget *parent) :QDialog(parent)
{
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
createButton();
connect(OKButton, SIGNAL(clicked(bool)), this, SLOT(accept()));
setMinimumSize(320, 240);
}
/**/
void AddPoint::createButton()
{
XpointL = new QLabel("Point X:", this);
XpointL->setFixedSize(100, 30);
XpointL->move(10, 10);
XPoint = new QLineEdit(this);
XPoint->setFixedSize(180, 30);
XPoint->move(120, 10);
OKButton = new QPushButton("OK", this);
OKButton->setFixedSize(100, 30);
OKButton->move(200, 150);
}
After running the program i see in aplication output lap:
"The program has unexpectedly finished."
"C:\QT\build-xxx-Desktop_Qt_5_4_2_MSVC2013_64bit-Debug\debug\xx.exe crashed"
I note that i made some experiments with this code and i saw that i have problem with signal accpeted() at mainwindow.cpp. I don't know what can i do with this problem. I hope you will help me.
AddPointDialog is uninitialized pointer, it does not yet point to valid AddPoint in MainWindow's constructor. You cannot call connect on that. Its value will change later, when you do AddPointDialog = new AddPoint(this); and only then will you be able to call connect.
Simply, you should move your connect call to void MainWindow::PointClicked() after you've initialized your pointer. I'd also make AddPointDialog local to that function and store it on the stack (you don't use it anywhere else and you're leaking memory).
The code would be:
void MainWindow::PointClicked()
{
AddPoint AddPointDialog(this);
AddPointDialog.setModal(true);
connect(&AddPointDialog, SIGNAL(accepted()), this, SLOT(DialogAccepted()));
AddPointDialog.exec();
}
Related
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 would like to make some modifications of the main window from another file.
I created another ui file Form1Window (which open when a button is cliked in the MainWindow).
I want to call from the class Form1Window a function named test() of the MainWindow class
I succeed in calling function test() but I can't execute the whole content of the function (I can display a message but can't execute the part where I want to clear an edittext)
MainWindow.h
#include "form1window.h"
public slots:
void nettoyer();
private slots:
void openFrom1();
private:
Ui::MainWindow *ui;
From1Window *uiFrom1;
};
MainWindow.cpp
void MainWindow::openFrom1()
{
uiFrom1 = new From1Window(this);
uiFrom1->show();
}
void MainWindow::nettoyer(){
QMessageBox msgBox;
msgBox.setText("test");
msgBox.setIcon(QMessageBox::Information);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
ui->auteur->clear();
//THIS LINE HAS NO EFFECT WHEN CALLED FROM THE OTHER CLASS
}
form1window.cpp
#include "mainwindow.h"
#include "ui_form1window.h"
void From1Window::on_supprimer_clicked()
{
MainWindow *a=new MainWindow ();
a->test();
close();
}
I've read about the role of the pointer of MainWindow class (C++ /Qt Proper way to access ui from another class in qt //Edited) and I've also tried connect()
Thank for your help
//THIS LINE HAS NO EFFECT WHEN CALLED FROM THE OTHER CLASS
this->ui->auteur->clear();
The line will never executed unless you dismiss QMessageBox. This is because you triggered QMessageBox with exec() function. This function has its own event queue and does not return until finishes. You may set QMessageBox as modal and display it with show() method. In that case QMessageBox will not block execution of the the flow.
This problem can also happen with QDialog(s) if you display them with exec().
I provide you a simple two window signal/slot example:
main.cpp
#include "mainwindow.h"
#include "form.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Form f;
f.show();
return a.exec();
}
form.h
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QPushButton>
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
private:
QPushButton *pb;
};
#endif // FORM_H
form.cpp
#include "form.h"
#include "mainwindow.h"
#include <QDebug>
Form::Form(QWidget *parent) : QWidget(parent)
{
MainWindow *mw = new MainWindow();
pb = new QPushButton("clickME", this);
QObject::connect(pb, SIGNAL(clicked()), mw, SLOT(test()));
mw->show();
}
Form::~Form()
{
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void test();
private:
QLabel *l;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
l = new QLabel("test", this);
}
MainWindow::~MainWindow()
{
}
void MainWindow::test() {
qDebug() << "test called!" << endl;
l->setText("text changed");
}
This works for me.
output
I have 3 classes.
class with a mainwindow which comes from the designer(ui-file)
class wich will manage database stuff like inserts
controller class. I want to extend the whole thing to networkcommunication later.
My problem:
I want to connect a simple QPushButton ui->addbutton from the window class with a slot addEntry from the databaseclass, but I get this error :
ERROR: no matching function for call to
'generalControler::connect(QPushButton*, const char*, dbmanager*&,
const char*)'
mydb, SLOT(addEntry()));
//no difference with &mydb or *mydb
MainWindow(0x13f57988, name = "MainWindow") QPushButton(0x13f5f3e0, name = "addButton")
MainWindow(0x13f57988, name = "MainWindow") 0x13f5f3e0//<--?????
//<=Here u see the adresses printed with Qdebug(). top: mainwindowclass. bot: generalcontrolerclass
//why there is missing information after returning the adress of a 'ui->addButton' to another class? Is this maybe the problem?
main.cpp
#include <QApplication>
#include "generalcontroler.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
generalControler controler;
return a.exec();
}
generalcontroler.h
#ifndef GENERALCONTROLER_H
#define GENERALCONTROLER_H
#include <QApplication>
#include "mainwindow.h"
#include "dbmanager.h"
class generalControler : public QObject
{
Q_OBJECT
public:
generalControler();
};
#endif // GENERALCONTROLER_H
generalcontroler.cpp
#include "generalcontroler.h"
#include <QDebug>
generalControler::generalControler(){
MainWindow* window = new MainWindow;
window->show();
dbmanager* mydb= new dbmanager("path_to_my_database.db", window);
mydb->addEntry();
qDebug()<<window->getThis()<<window->getcloseButton();
connect(window->getaddButton(), SIGNAL(clicked()),
mydb, SLOT(addEntry()));
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QPushButton* getaddButton();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
ui->setupUi(this);
}
QPushButton* MainWindow::getaddButton()
{
return ui->addButton;
}
dbmanager.h
#ifndef DBMANAGER_H
#define DBMANAGER_H
#include <QSqlDatabase>
#include <QDebug>
#include "mainwindow.h"
class dbmanager: public QObject{
Q_OBJECT
public:
dbmanager(const QString& path);
public slots:
void addEntry();
private:
QSqlDatabase mydatabase;
};
#endif // DBMANAGER_H
dbmanager.cpp
#include "dbmanager.h"
dbmanager::dbmanager(const QString& path)
{
mydatabase = QSqlDatabase::addDatabase("QSQLITE");
mydatabase.setDatabaseName(path);
if (!mydatabase.open())
{
qDebug() << "Error: connection fail";
}
else
{
qDebug() << "Database: connection ok";
}
}
void dbmanager::addEntry()
{
qDebug()<<"addEntry success";
}
I was searching for 6 hours but I never saw such an example with 2 classes, a controler and an ui-file. Could anyone help me?
The connect looks good to me. Try if #include <QPushButton> in generalcontroler.cpp helps. If the compiler knows about QPushButton only by forward-declaration, it doesn't know that it's a QObject and thus the connect() signatures (with QObject* in it) don't match.
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.
I have a QTextEdit and I connected the textChanged() slot to a signal. How can I find the changes when the signal is emitted. For example, I want to save the cursor position and the character written when I write something.
In the slot that gets called when the signal is emitted you can get the text with QString str = textEdit->toplainText();. Also you can store the previous version of the string and compare to get the character that was added and its position.
Regarding the cursor position you can us QTextCurosr class as in this example:
widget.h file:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTextEdit>
#include <QTextCursor>
#include <QVBoxLayout>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private slots:
void onTextChanged();
void onCursorPositionChanged();
private:
QTextCursor m_cursor;
QVBoxLayout m_layout;
QTextEdit m_textEdit;
QLabel m_label;
};
#endif // WIDGET_H
widget.cpp file:
#include "widget.h"
#include <QString>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
connect(&m_textEdit, SIGNAL(textChanged()), this, SLOT(onTextChanged()));
connect(&m_textEdit, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPositionChanged()));
m_layout.addWidget(&m_textEdit);
m_layout.addWidget(&m_label);
setLayout(&m_layout);
}
Widget::~Widget()
{
}
void Widget::onTextChanged()
{
// Code that executes on text change here
}
void Widget::onCursorPositionChanged()
{
// Code that executes on cursor change here
m_cursor = m_textEdit.textCursor();
m_label.setText(QString("Position: %1").arg(m_cursor.positionInBlock()));
}
main.cpp file:
#include <QtGui/QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}