I know this question has been asked a few time, (http://stackoverflow.com/questions/4436511/display-a-form-in-qt)
I am trying to open an existing form in my Qt C++ project.
it needs to be a subform instead of QDialog box.
both forms have a .ui, .h and .cpp file with them.
in my mwindowtest.cpp I have
//this is used to handle the button click to open the new form
connect(btnConnect, SIGNAL(click()), this, SLOT(openNewWindow()));
for function is:
void mWindowTest::openNewWindow(){
mForm = new dialog (this);
mForm->show();
}
in my mwindowtest.cpp I have:
#include <dialog.h> //second form
class dialog;
I'm now getting the error mForm was not declared in this scope.
but I am not sure what to declare mForm as in my Header file.
any tips would be greatly appreciated.
Thanks
In your mywindowtest.hpp you have to declare the pointer first:
// mytestwindow.hpp
// ...
private:
dialog* mForm;
// ...
// mytestwindow.cpp
void mWindowTest::openNewWindow()
{
mForm = new dialog (this);
form->show();
}
Or you declare it directly in your cpp, but then it is no member and only known in openNewWindow().
void mWindowTest::openNewWindow()
{
dialog* form = new dialog (this);
form->show();
}
When you work with Qt you should know the basics of C++. This example is one of those basics. Use Google and read some stuff about pointer tutorials and dynamic memory allocation.
Hope that helps. :)
In your example you will have memory leak since each time button btnConnect is clicked you will reallocate memory for your form, without deleting the previous first.
Concerning your problem, we need to know how is declare dialog in dialog.h to be able to really help you.
In your mywindowtest.cpp you have included the file and redefined the class. Try to put
class dialog
in your hpp file and
#include <dialog.h>
in your cpp file.
Hope that helps
Edit:
In your slot:
delete mForm;
mForm = new dialog();
dialog->show();
It's the minimum to avoid memory leaks; And don't forget to delete mForm in MyWindowTest destructor too if not null;
Related
This might be a simple question for most of your experts but I've been banging my head on this for the last few hours.
I have this layout which I declare in the header file like this:
private:
QVBoxLayout *vlayout;
I then initialize it in the constructor:
QVBoxLayout *vlayout = new QVBoxLayout();
ui->mainscroll_menu->setWidgetResizable(true);
ui->mainscroll_menu->widget()->setLayout(vlayout);
vlayout->setSpacing(1);
vlayout->setAlignment(Qt::AlignTop);
vlayout->setMargin(0);
I then try to use it inside a slot for example:
void MainWidget::on_pushButton_clicked()
{
vlayout->addWidget(menuitem);
}
This will compile ok but it will fail during runtime and crash my application. Upon running the debugging, it shows that it crashes when I try to use vlayout.
If I initialize the layout inside the slot, it will then work without crashing but that comes with other issues as I have to initialize the layout for each and everytime I want to use it.
What am I doing wrong?
The problem is this line in the constructor:
QVBoxLayout *vlayout = new QVBoxLayout();
This is creating a local variable in the constructor that is shadowing the member variable by the same name. When you try to use the member variable in any other method, you end up using an uninitialized value - hence the crash.
The fix is to simply change the line to:
vlayout = new QVBoxLayout();
I have a Qt application on Linux.
I'd like to program custom keyboard shortcuts such as CTRL-Q which will then call a subroutine which quits the program.
How can I do this?
Try this:
new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close()));
You can create it in the contructor of your form. This allows to avoid polluting your class with a pointer to access the shortcut. You may still want to add a pointer to the shortcut if you want to access it later on. The shortcut will be deleted when the application exits, since it is parented to it. It automatically does the connection, you don't have to do it manually.
Also note that there is no default Ctrl+Q sequence on Windows, but there is one on Linux and MacOS.
Since CTRL-Q may have a menu item or toolbar entry, too, I think you're looking for QAction.
See this:
http://doc.qt.digia.com/4.6/qaction.html#shortcut-prop
LE:
Example of QAction at work:
QAction *foo = new QAction(this);
foo->setShortcut(Qt::Key_Q | Qt::CTRL);
connect(foo, SIGNAL(triggered()), this, SLOT(close()));
this->addAction(foo);
Just create a new Qt GUI project (I used QtCreator) and add that code to the main window's constructor and it should work as expected.
Please note that there is no need of freeing the memory since the Qt framework will take care of that when the app closes.
For the modern Qt (5.9 as of now):
void MainWindow::bootStrap()
{
// create shortcut
QShortcut *shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this);
// connect its 'activated' signal to your function 'foo'
QObject::connect(shortcut, &QShortcut::activated,
this, &MainWindow::foo);
}
// somewhere in the code, define the function 'foo'
void MainWindow::foo()
{
qDebug() << "Ctrl+Q pressed.";
}
Don't forget to #include <QShortcut>.
Further info: http://doc.qt.io/qt-5/qshortcut.html
this is a sample to create file menu and exit action and connection between signal and slot.
QMenu *fileMenu = new QMenu(trUtf8("&File"));
QAction *actionExit = new QAction(tr("E&xit"));
//set "ctrl+q shortcut for exit action
actionExit->setShortcut(tr("CTRL+Q"));
//connect triggered signal of actionExit to close slot
connect(actionExit, SIGNAL(triggered()), this, SLOT(close()));
//add actionExit into file menu
fileMenu->addAction(actionExit);
i trying to created a Qt application multilanguage with Qt linguist.
I place this code in an function of my MainWindow :
translator.load(":/lang/English");
qApp->installTranslator(&translator);
ui->retranslateUi(this);
With the QTranslator declare in my MainWindow.h and all my string i want translate enclose by tr() . But with that, all QObject added dynamicaly by the code of my MainWindow.cpp, for example the title of a QTableWidget, are not translated.
If i place an other translator in my main.cpp, all my string are translate but i must created language button in my application and so i can't place translator in main.cpp.
Do you have an idea to help me?
Thx for your answers.
Gat
When you add a translation in your application using qApp->installTranslator(& aTranslator) then all the following calls to QObject::tr() (and similar functions) will look up in the translator for a translated text. So you should call retranslateUi() after qApp->installTranslator(). Actually you might event not call it there, you may reimplement QWidget::changeEvent() and intercept any QEvent::LanguageChange event.
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
// Someone called qApp->installTranslator() with a new translation.
// Let's update the user visible strings.
// This function was created by uic from the Designer form.
// It translates all user visible texts in the form.
ui->retranslateUi(this);
// This function must be written by you. It translates other user visible
// texts that are not in the form. See down for an example.
this->retranslateUi();
break;
default:
break;
}
}
ui->retranslateUi() just calls QObject::tr() for each user visible string in the ui. It is called automatically at the end of setupUi() and populates the form's widgets with translated text (have a look, it is defined by uic in ui_MainWindow.h file). You may want to take a similar approach with other user visible texts, like the title of a QTableWidget. All the strings are set in a function (named perhaps retranslateUi() for consistency) which is called at application starts (or, better, after the relevant widgets are created) and every time a new translations is loaded.
MainWindow::MainWindow(QWidget * parent)
: QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Creates other widgets, but do not set their user visible texts.
tableWidget = new QTableWidget(this);
...
someControl = new QLineEdit(this);
someOtherControl = new QSpinBox(this);
someModel = new MyModel(this);
...
// Ok, *now* we set their texts.
this->retranslateUi();
}
...
void MainWindow::retranslateUi()
{
// This function will be called (either manually or automatically by
// `changeEvent()`) when a new translator has installed, hence all the `tr()`
// calls will return the right translation for the last installed language.
QStringList labels;
labels.append(tr("First column"));
labels.append(tr("Second column"));
labels.append(tr("Third column"));
tableWidget->setHorizontalHeaderLabels(labels);
someControl->setText(tr("Control name"));
someOtherControl->setText(tr("Other control name"));
// Perhaps you have a model that need to be retranslated too
// (you need to write its `retranslateUi()` function):
someModel->retranslateUi();
...
}
Also, please note that if you are doing something like
void MainWindow::someFunction()
{
...
QTranslator translator;
translator.load(":/lang/English");
qApp->installTranslator(& translator);
...
}
as soon as that function returns the variable translator gets destroyed, so next time QObject::tr() is called the address stored with qApp->installTranslator(& translator) will be invalid. So you must allocate translator on the heap with new (and possibly deleting it with delete when you do not need it anymore). An exception is if you are doing that in main() before calling QCoreApplication::exec() since that function is blocking and will not return until application is closed.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
...
QTranslator translator;
translator.load(":/lang/English");
app.installTranslator(& translator);
...
app.exec(); // This function will return only on application's exit.
// Hence `translator` will outlive the application, there is
// no need to worry about it.
}
From what I understand to make dialog Modeless you have to allocate it on the heap. By Doing something like this:
MyDialog* dlg = new MyDialog(this);
dlg->show();
dlg->raise();
Since exec() ignores Modal Property. However now there is a memory leak since nothing deallocates memory pointed to by dlg pointer until the application is closed. I found one solution here http://tinf2.vub.ac.be/~dvermeir/manuals/KDE20Development-html/ch08lev1sec3.html#ch08list09 at the end of the page and was wondering whether there was a less cumbersome way having Modeless dialog.
You can use the attribute Qt::WA_DeleteOnClose to destroy the window when it is closed/hidden, and QWeakPointer (or QPointer) with a static variable to track the existence of the window inside the slot/function which opens it:
void MyWindow::openDialog() {
static QWeakPointer<MyDialog> dlg_;
if (!dlg_)
dlg_ = new MyDialog(this);
MyDialog *dlg = dlg_.data();
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->show();
dlg->raise();
dlg->activateWindow();
}
I'd schedule it for deletion at the time it's work is finished by using deleteLater:
void MyDialog::MyDialog(QWidget *parent) {
// ...
connect(this, SIGNAL(finished(int)), SLOT(deleteLater)));
}
This approach will preclude you from examining it after the finished signal has been emitted (unless you can guarantee that any accesses happen before everything gets back to the event loop when the deletion is actually performed).
Personally, I would choose between either using
dlg->setAttribute(Qt::WA_DeleteOnClose);
or making the dialog a -dynamically allocated- member i.e. creating it only once:
// constructor
: dialog_(0)
// member function
{
if (! dialog_)
dialog_ = new MyDialog(this);
dialog_->show();
dialog_->raise();
}
This way the dialog is deleted when the parent dies, and only needs to be constructed once.
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