This is a tutorial code for Qt:
Header file:
#include <QMainWindow>
namespace Ui {
class Notepad;
}
class Notepad : public QMainWindow
{
Q_OBJECT
public:
explicit Notepad(QWidget *parent = 0);
~Notepad();
private:
Ui::Notepad *ui;
};
Source file:
#include "notepad.h"
#include "ui_notepad.h"
Notepad::Notepad(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Notepad)
{
ui->setupUi(this);
}
Notepad::~Notepad()
{
delete ui;
}
And in main,
#include "notepad.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Notepad w;
w.show();
return a.exec();
}
So when we do Notepad w, an object is already created on the stack, and why does the code still create another object on the heap using new and assign to a member?
The one on the stack is of type Notepad, and it's the application's main window. The dynamic one is of type Ui::Notepad. That's a class automatically generated by Qt's uic tool; it contains the widgets created in UI creator as data members.
In a way, you could say that Notepad is concerned with the logic and uses an instance of Ui::Notepad to provide the GUI for it.
Related
Update:
If I delete Q_OBJECT, and I do not use SLOT SINGAL, just use connect() like this:
connect(this, &QWidget::destroyed, this, &QWidget::myslot),
my code will run well without any warnings and errors.
I want to write a little code to instruct some classes, so I try to simplify my code. But I encountered some strange things. I cannot write a simple widget in my main.cpp. If I write the widget in mywidget.cpp and mywidget.h, the program runs well. If I want to write the widget in the main.cpp, what should I do?
This is my code.
#include <QApplication>
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
};
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
}
Widget::~Widget()
{
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
And the error information is:
Add following line to the end of main.cpp and rerun qmake:
#include "main.moc"
That will invoke moc tool for your main.cpp. It generates meta-object function definitions for your Widget class resolving your linker errors when you rebuild.
As stated in documentation:
Whenever qmake is run, it parses the project's header files and
generates make rules to invoke moc for those files that contain a
Q_OBJECT macro.
Thus, put the class declaration in a header file (e.g. widget.h) and the class definition in a source file with the same name (e.g. widget.cpp).
If you still want to make it work with signals you can remove the Q_OBJECT macro and use the QObject::connect()
for example:
#include <QApplication>
#include <QWidget>
#include <iostream>
class Widget : public QWidget
{
//Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
};
Widget::Widget(QWidget *parent) : QWidget(parent)
{
// say bey
QObject::connect(this,&Widget::destroyed,
[](){std::cout<<"bye"<<std::endl;});
}
Widget::~Widget()
{
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
I test it on Qt5.9.4
I have a problem in Qt. I want to use "ui" in another class function.
With this code:
void test::TextAp()
{
MainWindow::ui->QTextBrowser->append("Test");
}
I get these errors:
error C2227: left of '->qTextBrowser' must point to class/struct/union
error C2227: left of '->append' must point to class/struct/union
And with this code:
void test::TextAp()
{
Ui::MainWindow::QTextBrowser->append("Test");
}
I get this error:
error C2227: left of '->append' must point to class/struct/union
MainWindow.h:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Ui::MainWindow *ui;
private:
};
What can I do?
ps:Excuse my bad English, i'm French
If you are referring to default project created by Qt, ui can't be used as it is private. Make a MainWindow object and use it (like it is used in main()).
Now, if you have a QTextBrowser object created in MainWindow, call using that object and not class signature as:
ui->objTextBrowser->append("Test")
If "test" is class or struct it has to know about MainWindow object or in particular about it's child object TextBrowser.
Ui creates in the MainWindow constructor so, before using it you have to create it.
And in addition it's a bad practice to do what you want to do, the better solution is to connect signals from your test class (that have to be inherit from QObject) to slot of MainWindow
So bad practice looks:
//main.cpp
#include "test.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//instance of MainWindow
MainWindow w; // here constructor of MainWindow creates ui and all the childs
w.show();
//instance of test struct
test t;
//behind the design mode is creation of code with objects that you can create "manually" typing them
//to see the ui additional files just press Ctrl and mouse click (for example) on function ui->setupUi(this) in MainWindow constructor
//it's automatically generated code for ui created according to what you've created in design mode
//so here textBrowser pointer of object t is points to textBroswer of ui of object w
t.textBrowserFromTestStruct = w.findChild<QTextBrowser*>("textBrowser");
//get error if object f ui has no QTextBrowser named textBrowser
Q_ASSERT(t.textBrowserFromTestStruct);
//invoke t object function to append text to f textBrowser 10 times
for(int i = 0; i < 10; ++i)
t.TextAp("Hello World ");
return a.exec();
}
//test.h
#ifndef TEST_H
#define TEST_H
#include "mainwindow.h"
#include <QTextBrowser>
struct test
{
QTextBrowser *textBrowserFromTestStruct;
public:
void TextAp(QString text){textBrowserFromTestStruct->append(text);}
};
#endif // TEST_H
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Ui::MainWindow *getUI(){return ui;}
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);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
}
Read about signals and slots to get own solution of what you want using signals and slots. And of course read more about theory of C++ to understand what is private members of classes and structures, what is namespaces and scoping
Okay I'm using Qt Designer to build a GUI. I've managed to figure out how to make the menuBar and I've added some actions to the bar, but now I need to connect the actions to make them do something.
Specifically, on my file menu, I have the simple open action. I want this action to run a function that calls my QFileDialog and so on, but I don't know how to do this.
So, how do I connect my actionOpen to my static function?
I am using the latest Qt, 5.0.2
I'm a little frustrated here. This is obviously one of the most basic things someone might need to do, yet I cannot find any real solution to this anywhere on the web. From the lacking Qt wiki, to other people's questions, nobody really seems to have a clear answer. There are answers for older versions of Qt, yet in those old versions apparently signals couldn't connect to static functions, so those are irrelevant. And nobody seems to know how to do this through the Qt Designer. Also, nobody ever clarifies where to put what.
I have this line in my main.cpp file:
QObject::connect(actionOpen, &actionOpen::triggered, fileOpen)
I have an object called 'actionOpen' made in Qt Designer, there is a signal called triggered, and I have a function defined just below my main inside main.cpp called 'fileOpen'. This seems to follow the proper syntax, yet it throws many errors.
Also, I can repeatedly click build in Qt Creator and every single time it comes up with a different number of errors, disappearing and reappearing, without me even touching the code. I'm starting to think this IDE is sort of a POS.
EDIT:
Here are my files. Maybe this will help somewhat.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void fileOpen();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <iostream>
#include <fstream>
using namespace std;
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"
#include <iostream>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QObject::connect(ui->actionOpen, &QAction::triggered, &MainWindow::fileOpen);
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void fileOpen()
{
/*
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QString(),
tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));
if (!fileName.isEmpty()) {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
return;
}
QTextStream in(&file);
ui->textEdit->setText(in.readAll());
file.close();
}
*/
cout << "Hello!";
}
The second argument is incorrect. You should specify the class name, not object name. So it should be:
QObject::connect(actionOpen, &QAction::triggered, fileOpen);
Complete working example (tested):
void fileOpen() {
qDebug() << "ok";
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QMenu menu;
QAction* actionOpen = menu.addAction("test");
QObject::connect(actionOpen, &QAction::triggered, fileOpen);
menu.show();
return a.exec();
}
1.) Create regular slot and call the static function.
OR
2.) I suppose you could create a singleton Q_OBJECT class and connect to it - of course like option 1 you'd then make the call to whatever static/global function.
/**
* Pseudo-code!, the singleton should be in its own header file
* not in the global main.cpp file.
*/
class Singleton : public QObject
{
Q_OBJECT
public:
Singleton() : QObject() {}
static Singleton* getInstance() {
if(!_instance) _instance = new Singleton();
return _instance;
}
public slots:
void mySlot() { qDebug() << __FILE__ << " " << __FUNCTION__ << __LINE__;
}
private:
static Singleton* _instance;
};
Singleton* Singleton::_instance = NULL;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
Singleton* instance = Singleton::getInstance();
QObject::connect(&w, SIGNAL(destroyed()), instance, SLOT(mySlot()));
return a.exec();
}
I'm just trying my best to answer the question, but like many of the comments above - this isn't something that I've needed ever needed to do. I can say that QtCreator/Designer is a really amazing tool and as you overcome some of the learning curves it'll be less frustrating.
I want to have this code in one file, but can't figure out how to. I know it might not be good practice to do so but I am trying to learn qt, and would find it easier to understand the information if it were in one file.
This is the main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
This is the mainwindow.cpp
#include "mainwindow.h"
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
this is the mainwindow.h
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
By just copying everything in one file.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
It is usually not a good idea to define new classes in same file as your main. Generally you want new classes each in their own file or you would want to put several related classes together in a seperate file. There are a tonne of resources you can google related to best practices for this. I'd suggest you spend some time reading.
But since you asked... below is how you would do it for your example. If you do not define your class above the main, the compiler will complain because it won't know what a "MainWindow" is.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
#include essentially takes the contents of whatever file you choose and copy/pastes it at that location. The compiler then starts at the top of the file and works its way down to the bottom.
Knowing that, you should be able to just copy-paste the contents of the files in the order they are included.
mainwindow.h
mainwindow.cpp
main.cpp
The short answer is don't do this, you should define a class in its own header file and #include it to the main when you want to run it in the main. This allows you to reuse the class as you see fit throughout the program, its one of the tenets of Object Oriented programming, reusable code. For example
class A
{
public:
A();
~A();
void somePublicMethod();
private:
void somePrivateMethod();
};
If you include that class in your main when you compile that class to object code(assuming you know about implementing that class in a .cpp file) then when all the object files are linked to create the program the linker basically makes one big file with all the object code included in file to be fully compiled. I suggest you read up more on compiling and linking, essentially it boils down to three phases, preprocessing, compiling and linking. Learn more about Object Oriented programming and read up why it's a bad idea to just shove them all into one file. Every class should be in its own self contained .h file(unless its a tightly coupled class) so you can include them as you see fit. Hope this helps, have fun with Qt :)
I am new to the Qt framework and am trying to load another UI file when SubmitClicked. The file's name is Form.ui
//MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "form.h"
#include <QtCore/QCoreApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow:: SubmitClicked()
{
Form* f= new Form(this);
f->show();
f->raise();
f->activateWindow();
}
//Form.cpp
#include "form.h"
#include "ui_form.h"
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
}
Form::~Form()
{
delete ui;
}
This didn't work out! Can you tell me what's wrong?
The .ui file is simply where the code for GUI elements gets stored. This code is generated by the QtDesigner in most cases. It's similar to Visual Studio's .rc file and wizard generated GUI in function and form. This file will either be loaded at compile time which is the default or at runtime via the QUiLoader. If you want dynamically generated UI at runtime the latter is the option you need to look into starting with QtUiTools
On a side note the class Form does not exist in Qt so this is either a class you made or a typo. If you simply want to declare and show a window or dialog then derive from the appropriate base class and call show() or the appropriate method.
For example something simple like this where MainWindow is your own user defined class derived from QMainWindow:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);
QApplication app(argc, argv);
MainWindow mainWin;
mainWin.show();
return app.exec();
}
Edit:
Ah so Form is a QWidget class. Are you missing the Q_OBJECT macro in your Form class? You also generally only call setupUi once for the main window of the application to load your resources and such where as user defined subclasses it's often easier to define gui objects for the class programmatically.
//Form.h
class Form : public QWidget
{
Q_OBJECT // this is needed for the MOC aka qmake
public:
Form(QWidget *parent);
virtual ~Form();
private:
QTextEdit m_text;
};
//Form.cpp
#include "form.h"
Form::Form(QWidget *parent) : QWidget(parent)
{
setCentralWidget(&m_text);
}
Form::~Form()
{
}
It sounds almost like you're confusing your class object with your ui namespace files.