Multiple QWidets into one QMainWindow - c++

I am currently learing Qt, and I am stuck on the problem of using multiple QWidgets and one QMainWindow.
I have setup a project which contains 2 QWidgets and one QMainWindow. This is my idea of using it: design both QWidgets as needed, add them to the mainwindow object, connect the buttons to the correct slots and switch the centerwidget when needed. So I started off with one QMainWindow and then added two QWidgets, including the cpp file, the h file and the ui file. On both QWidgets I added one QPushButton, and called it pushButtonConvert.
Then I went to the cpp file attached to the QMainWindow (mainwindow.cpp) and did the following:
EpochToHuman * epochToHuman = new EpochToHuman();
HumanToEpoch * humanToEpoch = new HumanToEpoch();
Up until this point everything is fine. Now I want to connect the buttons to slots in the mainwindow object, but I can not find the buttons. epochToHuman->pushButtonConvert does not seem to exist, and I can not find any other way to get to the buttons. So am I thinking in a way that is not correct, according to Qt or am I missing something?
Another try at clarifying what I want:
I want to use the elements in a QWidget in QMainWindows' cpp file. I want to be able to do things like this:
//In object MainWindow.cpp
QWidget * a = new QWidget
//Let's say a is a custom widget with a label in it. This label is called Label
a->Label->setText("Hello, World!");
//This gives an error because a does not have a member called Label
//How can I change the text on the label of a?
//And I think if I will be able to change the text of this label, I will also be able to dance around with buttons as needed.

You can connect the pushButtonConvert button to MainWindow::convertFromEpochToHuman in the constructor of MainWindow, with:
connect(epochToHuman->ui->pushButtonConvert, SIGNAL(clicked(bool)), this, SLOT(convertFromEpochToHuman()));
You'll need to make the ui member public first, like you have done for HumanToEpoch.
You should move the declaration of your widgets into MainWindow.h:
// ...
private:
Ui::MainWindow *ui;
EpochToHuman * epochToHuman;
HumanToEpoch * humanToEpoch;
// ...
and initialise them like this:
epochToHuman = new EpochToHuman(this);
humanToEpoch = new HumanToEpoch(this);

Related

Qt5 ui, multiple windows: how can I access the Ui objects in Window 2 from Window 1

I know this is very clunky and I'm probably doing a lot of wrong things but so far everything I saw on the net gives back the same errors: invalid use of non-static data member ui.
So in the MainWindow, I have a comboBox named hometeam, and I want to display the currentText on a Qlabel named label which is on another Form Class called Dialog
I figured they're both private members so I added friend class MainWindow and friend class dialog in the respective headers (I know this is pretty wrong but it's the last thing I tried), I included the "ui_mainwindow" and "ui_dialog" in the .cpp files, and here's the bit of code I'm trying:
ui->label->setText(MainWindow::ui->hometeam->currentTex());
Keep in mind that I don't want a QDialog, the second window will do a lot more than a display, I just want to access the objects from a different window. Slots and signals give the same error.
Thanks !
I think the proper way to do that, is to add a function to your MainWindow class:
QString hometeamText() const
{
return ui->hometeam->currentTex();
}
This way you can access the information you need without violating encapsulation rules, but you need an instance of MainWindow to do it, and sure must keep a pointer to it in your Dialog class:
class Dialog
{
private:
MainWindow * mainwindow;
public:
void setMainWindow(MainWindow * w) { mainWindow = w; }
then somewhere (e.g. in main) you can do something like:
MainWindow mainwindow;
Dialog dialog;
dialog.setMainWindow(&mainWindow);
and from inside your Dialog class, wherever you need it:
ui->label->setText(window->hometeamText());

How to make a QVBoxLayout available globally

I am trying to make a QVBoxLayout available globally in Qt. I cannot access it from any other functions.
void MainWindow::on_actionF451_triggered()
{
QVBoxLayout *compLay = new QVBoxLayout(ui->scrollArea);
I have created it in this function then below have added tons of widgets, but need to be able to clear these widgets in another function.
Thanks
If you want a variable compLay to be accessed anywhere in your MainWindow class, then define it in mainwindow.h's definition of MainWindow class (after Q_OBJECT macro) like this: QVBoxLayout *compLay;
and you can change compLay within MainWindow class however you like:
void MainWindow::on_actionF451_triggered(){
compLay = new QVBoxLayout(ui->scrollArea);
or you can make return type of void MainWindow::on_actionF451_triggered() not void, but QVBoxLayout * and return your layout directly (but you will need to correct the connect statement then (i assume, that you don't have one and it is autoconnected) and connect it to slot, where you will need this layout to clean or modify or remember )

My widget doesn't show on the mainwindow. qt

in my program the senario is like this, user opens a xml file, the program reads it. Show the units and tests and when the user clicks on the desired test, the program needs to show its step. Since the number of steps always change i need to add the widget by code and delete them. But when i try to add a widget by code and set its position it doesn't show up on the main window. ( i am doing this with a seperate class just make things look neater)
Here is my sample code;
void CStepPanel::addstep()
{
QLabel *label1 = new QLabel("step1");
label1->move(450,50);
}
Do you know doesnt it work ? And how can i do that. Since i am new to qt and programming i am having a hard time about this.
Your widget should have a parent to be shown in an other widget or dialog. You should set a parent for the label. If you want it to be displayed on the main window then a pointer to your QMainWindow should be kept in the class CStepPanel (It could be assigned in the constructor of CStepPanel) :
QMainWindow * mainWindow;
And the addstep is like :
QLabel *label1 = new QLabel("step1");
label1->setParent(mainWindow);
label1->move(450,50);

QT QTextEdit setText crashes

I've created a qt widgets application. Using the design mode I've created a QTextEdit and indicated that in the header file:
...
QT_BEGIN_NAMESPACE
class QAction;
class QMenu;
class QTextEdit;
QT_END_NAMESPACE
...
private:
Ui::MainWindow *ui;
QTextEdit *textEdit_2;
};
There is also a slot which is triggered by pushing a button. What it has to do is to insert some text into textEdit_2 after the button is pushed, still the program crashes.
In mainwindow.cpp:
void MainWindow::on_action_4_triggered()
{
textEdit_2->setText("text");
}
I've also tried
textEdit_2->setText(QString("text"));
which anyway doesn't work. What's the problem?
textEdit_2->setText("text");
The problem is that you are trying to ignore the actual text widget created in QtDesigner and invent another as a class member. This is not going to fly as you seem to want it.
In order to reuse the text widget from the UI that you created with the graphical tool, you would need to reuse the ui object as follows:
ui->textEdit_2->setText("text");
Please also note that you do not need to construct QString explicitly like this:
textEdit_2->setText(QString("text"));
This will be all automatic for you.

New window doesn't show

I have a button, when it is clicked a new window show with a QLineEdit, and a QLabel on it, my connection between the button and the function works fine, but the new window doesn't show.
void windowManager::addQuestionDialog(){
QWidget window(&parent);
QLineEdit question;
QLabel label;
QVBoxLayout layout;
layout.addWidget(&question);
layout.addWidget(&label);
window.setLayout(&layout);
window.resize(200,200);
window.setWindowTitle(QObject::trUtf8("Kérdés bevitele..."));
window.show();
}
You need to create class tag variables for the new window and the stuff you want to put into it, than create the objects themselves with the new keyword in the function, because if you create all of these simply in a function, than they will created in the stack, and you should know that after a function returns/finishes, the stack to that function is deleted (with your new window and the stuff on it too).
Include the headers for the classes you want to use in your windowManager header file:
#include <QDialog>
#include <QLineEdit>
#include <QLabel>
#include <QVBoxLayout>
Then add the tag variables to the private part:
private:
QDialog *window;
QLineEdit *question;
QLabel *label;
QVBoxLayout *layout;
In your button's click event set the tag variables, and create the UI setup:
void windowManager::addQuestionDialog()
{
window = new QDialog();
question = new QLineEdit();
label = new QLabel();
layout = new QVBoxLayout();
layout->addWidget(question);
layout->addWidget(label);
window->setLayout(layout);
window->resize(200,200);
window->setWindowTitle(QObject::trUtf8("Kérdés bevitele..."));
window->show();
}
Also don't forget that you should use -> instead of . for calling functions here, because these tag variables are pointers. Also that's the reason why you don't need to use the & operator to get their address.
Also keep in mind that you should delete these objects, because C++ doesn't delete these automatically for you. You should delete everything you new. A good place to do this is in the destructor in your windowManager class. Just check if the tag variables are not NULL (if there is an object) before you try to delete them, otherwise errors may occur.
A better solution is to pass a parent pointer as the constructor's parameter, so this way Qt will delete them as they are closed, because if the parent is destroyed, the children will be destroyed too.
As an extra, you don't have to set manually where does the objects are go, because Qt will now it from the hierarchy (in some cases).
In this case your button's click event function would look like this:
void windowManager::addQuestionDialog()
{
window = new QDialog(this);
question = new QLineEdit(window);
label = new QLabel(window);
layout = new QVBoxLayout(window);
//The following two lines are optional, but if you don't add them, the dialog will look different.
layout->addWidget(question);
layout->addWidget(label);
window->resize(200,200);
window->setWindowTitle(QObject::trUtf8("Kérdés bevitele..."));
window->show();
}
You create the window QWidget object on the stack. Therefore, this object will be deleted when the call to the function addQuestionDialog finishes. Change the code to create the new window widget using "new", and arrange it to be deleted after it was closed. Some possible solutions are presented here:
destructors in Qt4