I started working on the GUI for an application in C++ using the Qt-Creator and Designer. I always added the new files (cpp, h, ui) by using the dialog that Qt provides.
Here's what I get now:
moc_basewidget.obj:-1: Error: LNK2019: unresolved external signal ""public: void __cdecl BaseWidget::onNewProjects(void)" (?onNewProjects#BaseWidget##QEAAXXZ)" in function ""private: static void __cdecl BaseWidget::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)" (?qt_static_metacall#BaseWidget##CAXPEAVQObject##W4Call#QMetaObject##HPEAPEAX#Z)".
Here's my BaseWidget.h:
#ifndef BASEWIDGET_H
#define BASEWIDGET_H
#include <QWidget>
#include "mainmenu.h"
#include "projectlist.h"
namespace Ui {
class BaseWidget;
}
class BaseWidget : public QWidget
{
Q_OBJECT
public:
explicit BaseWidget(QWidget *parent = 0);
~BaseWidget();
public slots:
//called in MainMenu
void onProjects();
private:
Ui::BaseWidget *ui;
MainMenu * mainMenu;
ProjectList * projectList;
};
#endif //BASEWIDGET_H
And my BaseWidget.cpp:
#include "basewidget.h"
#include "ui_basewidget.h"
BaseWidget::BaseWidget(QWidget *parent) : QWidget(parent), ui(new Ui::BaseWidget) {
ui->setupUi(this);
//add all the widgets
this->mainMenu = new MainMenu(this);
ui->stackedWidget->addWidget(mainMenu);
this->projectList = new ProjectList(this);
ui->stackedWidget->addWidget(projectList);
}
BaseWidget::~BaseWidget()
{
delete ui;
}
void BaseWidget::onProjects()
{
ui->stackedWidget->setCurrentWidget(this->projectList);
}
And finally, my .pro file:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = GUI
TEMPLATE = app
SOURCES += main.cpp\
basewidget.cpp \
mainmenu.cpp \
projectlist.cpp
HEADERS += basewidget.h \
mainmenu.h \
projectlist.h
FORMS += basewidget.ui \
mainmenu.ui \
projectlist.ui
I've read about it for hours now. I tried cleaning the build-directory and rebuilding, but it always comes down to this.
Related
I have linking problems by creating a Qt C++ plugin to extend the functionality of my application. The code compiles and everithing works, but only as long as I use the Qt library classes, like QString for example. The moment I give to the plugin's class a reference to an object from the classes defined in the host app, the project is not linked anymore. Creating the plugin I follow the procedure from the Qt documentation and take into consideration the given examples - echo and plug&paint. However, such case is not covered there.
update
Here is the error:
myPlugin.obj:-1: error: LNK2019: unresolved external symbol "public: class QString __cdecl myClass::answer(void)const " (?answer#myClass##QEBA?AVQString##XZ) referenced in function "public: virtual class QString __cdecl myPlugin::echo(class myClass *)" (?echo#myPlugin##UEAA?AVQString##PEAVmyClass###Z)
And here is the project that causes it:
plugtest.pro
TEMPLATE = subdirs
SUBDIRS += \
host \
plugin
host.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = host
TEMPLATE = app
SOURCES += main.cpp\
MainWindow.cpp \
myClass.cpp
HEADERS += MainWindow.h \
myClass.h \
plugInterface.h
FORMS += MainWindow.ui
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
#include <QPluginLoader>
#include <QDir>
#include "myClass.h"
#include "plugInterface.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_button_clicked();
private:
bool loadPlugin();
Ui::MainWindow *ui;
plugInterface *m_interface;
myClass *m_class;
};
#endif // MAINWINDOW_H
myClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
class myClass : public QObject
{
Q_OBJECT
public:
explicit myClass(QObject *parent = 0);
QString answer() const;
void setAnswer(const QString &str);
private:
QString m_answer;
};
#endif // MYCLASS_H
plugInterface.h
#ifndef PLUGINTERFACE_H
#define PLUGINTERFACE_H
#include <QString>
#include "myClass.h"
class plugInterface
{
public:
virtual ~plugInterface() {}
virtual QString echo(myClass *value) = 0;
};
#define PlugInterface_iid "example.suite.app.PluginInterface"
Q_DECLARE_INTERFACE(plugInterface, PlugInterface_iid)
#endif // PLUGINTERFACE_H
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
if (!loadPlugin())
{
QMessageBox::information(this, "Error", "Could not load the plugin");
}
m_class = new myClass(this);
m_class->setAnswer("Good!");
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::loadPlugin()
{
QDir pluginsDir(qApp->applicationDirPath());
if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
pluginsDir.cd("plugins");
foreach (QString fileName, pluginsDir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
if (plugin) {
m_interface = qobject_cast<plugInterface *>(plugin);
if (m_interface)
return true;
}
}
return false;
}
void MainWindow::on_button_clicked()
{
ui->lineResult->setText(m_interface->echo(m_class));
}
myClass.cpp
#include "myClass.h"
myClass::myClass(QObject *parent) : QObject(parent)
{
}
QString myClass::answer() const
{
return m_answer;
}
void myClass::setAnswer(const QString &str)
{
m_answer = str;
}
plugin.pro
TEMPLATE = lib
CONFIG += plugin
QT += widgets
INCLUDEPATH += ../host
HEADERS = myPlugin.h
SOURCES = myPlugin.cpp
TARGET = $$qtLibraryTarget(myPlugin)
DESTDIR = ../plugins
myPlugin.h
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include <QObject>
#include "plugInterface.h"
class myPlugin : public QObject, plugInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "example.suite.app.PluginInterface")
Q_INTERFACES(plugInterface)
public:
QString echo(myClass *value) Q_DECL_OVERRIDE;
};
#endif // MYPLUGIN_H
myPlugin.cpp
#include "myPlugin.h"
QString myPlugin::echo(myClass *value)
{
return value->answer();
}
The solution that worked for me is to make the myClass a part of a library and include it dynamically in both the plug-in and the host. However, I am curious if this could be done without creating a library.
I am having some issues with starting a timer-based object from a dll with the event loop. Therefore I made a minimal example and this is my output:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is MainWindow(0x28fe08), parent's thread is QThread(0x1222aab0), current thread is QThread(0x121421c8)
QObject::startTimer: Timers can only be used with threads started with QThread
MainWindow thread: 0x1222aab0
DllThreadTest thread: 0x121421c8
I am using Windows 8 and Qt5.3.2.
So my questions are:
Why is the object that I create from the dll inside a different thread than the MainWindow? As you can see in the code, I am not using threads.
I can not pass this as a parameter when creating the object from my library as you can see in the first error message. See my example below.
I guess that when I solve the thread-issue, I also solve the timer-problem.
Example:
dllthreadtest.h
#ifndef DLLTHREADTEST_H
#define DLLTHREADTEST_H
#include <QObject>
#include <QTimer>
#if defined TEST_BUILD_DLLTHREADTEST
#define TEST_COMMON_DLLSPEC Q_DECL_EXPORT
#else
#define TEST_COMMON_DLLSPEC Q_DECL_IMPORT
#endif
class TEST_COMMON_DLLSPEC DllThreadTest : public QObject
{
Q_OBJECT
public:
explicit DllThreadTest(QObject *parent = 0);
signals:
public slots:
void onTimeOut();
private:
QTimer timer;
};
#endif // DLLTHREADTEST_H
dllthreadtest.cpp
#include "dllthreadtest.h"
#include <QDebug>
DllThreadTest::DllThreadTest(QObject *parent) :
QObject(parent)
{
timer.start(1000);
}
void DllThreadTest::onTimeOut()
{
qDebug()<<"time out";
}
DllThreadTest.pro
QT += core
QT -= gui
TARGET = DllThreadTest
CONFIG += console
CONFIG -= app_bundle
CONFIG += debug_and_release build_all
CONFIG(debug, debug|release) {
win32: TARGET = $$join(TARGET,,,d)
}
TEMPLATE = lib
DEFINES += TEST_BUILD_DLLTHREADTEST
SOURCES += main.cpp \
dllthreadtest.cpp
HEADERS += \
dllthreadtest.h
I am building it and then including the library in a newly created default project that just creates a QMainWindow. There I instantiate a DllThreadTest-object.
DllImportTest.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = DllImportTest
TEMPLATE = app
INCLUDEPATH += \
$$PWD/libs/
win32{
LIBS += -L$$PWD/libs/ -ldllthreadtest
}
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
maindwindow.cpp (only class of DllImportTest.pro)
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dllthreadtest.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton,SIGNAL(clicked()),
this,SLOT(onButtonClick()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onButtonClick()
{
dllThreadTest_=new DllThreadTest;
qDebug()<<"MainWindow thread:"<<this->thread();
qDebug()<<"DllThreadTest thread:"<<dllThreadTest_->thread();
}
main.cpp (entry point of DllImportTest)
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
I'm new to Qt and am trying to figure out how to add a custom widget I've created to my main window.
The widget is pretty simple - I just used Qt Designer to create the default widget (I'm calling it Editor) and then added a button to it. Next I included the header of my custom widget in mainwindow.h and added a pointer to it in my MainWindow class. So far, so good. But when I try to create a new instance of Editor, I get the error:
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "public: __cdecl Editor::Editor(class QWidget *)" (??0Editor##QEAA#PEAVQWidget###Z) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow##QEAA#PEAVQWidget###Z)
What do I need to do to be able to link my code?
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "editor.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
Editor *editor;
};
#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);
editor = new Editor(0);
}
MainWindow::~MainWindow()
{
delete ui;
delete editor;
}
editor.h:
#ifndef EDITOR_H
#define EDITOR_H
#include <QWidget>
namespace Ui {
class Editor;
}
class Editor : public QWidget
{
Q_OBJECT
public:
explicit Editor(QWidget *parent = 0);
~Editor();
private:
Ui::Editor *ui;
};
#endif // EDITOR_H
editor.cpp:
#include "editor.h"
#include "ui_editor.h"
Editor::Editor(QWidget *parent) :
QWidget(parent),
ui(new Ui::Editor)
{
ui->setupUi(this);
}
Editor::~Editor()
{
delete ui;
}
CustomWidgetTest.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = CustomWidgetTest
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
editor.cpp
HEADERS += mainwindow.h \
editor.h
FORMS += mainwindow.ui \
editor.ui
I have a Qt project made by Qt creator.
I let the creator itself generate a private slots function fx. on_pushbutton_clicked().
This function is declared in header, the function itself is in the cpp file created by the Qt creator.
When I move the function from cpp file generated by Qt creator to another cpp file (it is added in the project, it has the same includes as the generated cpp.
When I try to compile it, I get lnk2019 error.
Is there any way to have slots functions in different files?
I am using VC compiler.
Okay, here is extract from the code. (it is quite long)
gui.h
#ifndef GUI_H
#define GUI_H
#include <QMainWindow>
#include "buffer.h"
#include <string>
#include <map>
#include <math.h>
#include <sstream>
#include <stdlib.h>
#include "qcustomplot.h"
#include <limits>
#include <time.h>
#include <random>
namespace Ui {
class GUI;
}
class GUI : public QMainWindow
{
Q_OBJECT
public:
explicit GUI(QWidget *parent = 0);
~GUI();
private slots:
void on_setall_clicked();
void on_integrace_button_clicked();
void on_elipsy_button_clicked();
void on_grafy_button_clicked();
private:
Ui::GUI *ui;
};
#endif // GUI_H
gui.cpp
#include "gui.h"
#include "ui_gui.h"
double drand(double from, double to){
double f = (double)rand()/RAND_MAX;
return from + f * (to - from);
}
GUI::GUI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::GUI)
{
ui->setupUi(this);
srand(time(0));
}
GUI::~GUI()
{
delete ui;
}
void GUI::on_setall_clicked(){...};
void GUI::on_grafy_button_clicked(){...};
void GUI::on_integrace_button_clicked(){...};
elipsy.cpp
#include "gui.h"
void GUI::on_elipsy_button_clicked(){...};
GUI.pro
#-------------------------------------------------
#
# Project created by QtCreator 2013-03-27T09:01:31
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
TARGET = GUI
TEMPLATE = app
SOURCES += main.cpp\
gui.cpp \
solve_rpn.cpp \
shunting_yard.cpp \
qcustomplot.cpp \
elipsy.cpp \
grafy.cpp \
integrace.cpp
HEADERS += gui.h \
buffer.h \
qcustomplot.h
FORMS += gui.ui
And the error code it gives me when i try to compile with the function elipsy_button_clicked() in file other than gui.cpp
moc_gui.obj:-1: Chyba:LNK2019: unresolved external symbol "private: void __cdecl GUI::on_elipsy_button_clicked(void)" (?on_elipsy_button_clicked#GUI##AEAAXXZ) referenced in function "private: static void __cdecl GUI::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)" (?qt_static_metacall#GUI##CAXPEAVQObject##W4Call#QMetaObject##HPEAPEAX#Z)
debug\GUI.exe:-1: Chyba:LNK1120: 1 unresolved externals
Well, in case you need the entire sourcecode, I uploaded it
http://seed.gweana.eu/public/GUI.7z
FIXED: The file was ignored by the project, running qmake again solved the issue. Many thanks for the answers :)
One of the problems is that you exported the slot methods to elipsy.cpp where on line 14 you try to use: ui ... which is defined in ui_gui.h included only in gui.cpp, but forward declared in gui.h (which you include of course in elipsy.cpp) so this should give you a compilation error. Solution: include ui_gui.h in elipsy.cpp. If it doesn't give you a compilation error try to rebuild the application.
Secondly, your drand function is defined in gui.cpp but not in any header file (easily fixable, modify gui.h)...
After fixing these two issues the compilation was ok for me.
So, a few recommendations:
Leave the things as they are when comes to Qt ... you will just mess up your head when moving things around.
have a separate "module" for utilities, such as drand
(PS: Nice app :) )
Generally slots are declared in a header file like,in my Counter.h :
#include <QObject>
class Counter : public QObject
{
Q_OBJECT
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value);
....
Now in Counter.cpp(and it has to include Counter.h), i will define this function like any other normal function.
So in this case everything will work correctly.Does that answers your question?
So I've been developing a small ACARS (plane tracking system) for the VATSIM network and apart of this entails using the FSUIPC library to interact with Flight Sim X. I have the program working beautifully in VS2010 but when I attempt to use any functions from FSUIPC I get the error:
"mainwindow.obj:-1: error: LNK2019: unresolved external symbol FSUIPC_Open referenced in **function "public: void __cdecl MainWindow::connectFSUIPC(void)" (?connectFSUIPC#MainWindow##QEAAXXZ)"**
From some research I've learnt that this is a library load error and for the life of me I can't figure out how to get it working. Below is the code for all files I am using.
AcarsTest.pro
#-------------------------------------------------
#
# Project created by QtCreator 2013-12-16T23:56:06
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = AcarsTest
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
INCLUDEPATH += "D:/Windows/QT/Tools/QtCreator/bin/AcarsTest/"
LIBS += -LD:/Windows/QT/Tools/QtCreator/bin/AcarsTest/ -lFSUIPC_User
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <Windows.h>
#include <FSUIPC_User.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void connectFSUIPC();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp
#include <Windows.h>
#include "mainwindow.h"
#include <QApplication>
#include "FSUIPC_User.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
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::connectFSUIPC()
{
DWORD dwResult;
if(FSUIPC_Open(SIM_ANY, &dwResult))
{
}
}
try change code like this
your code:
LIBS += -LD:/Windows/QT/Tools/QtCreator/bin/AcarsTest/ -lFSUIPC_User
replace by
win32:LIBS += "D:/Windows/QT/Tools/QtCreator/bin/AcarsTest/FSUIPC_User.lib"