Connect ui files from different classes
-
Hello!
I was wondering if I am able to change widgets from any class.If I use a MainWindow class I can simply use setCentralWidget function. But I want to use multiple .ui files with multiple classes and be able to load different .ui files for example when a button is clicked.
The idea is to make things more organized in stead of using QStackedWidget and a single MainWindow class.Thanks!
-
Hi @mpergand
Thanks for your advice about using QUiLoader. I tried following their documentation but got into an error.I wrote a simple code whenever a button is pressed
void MainMenu::on_LogIn_menu_PB_clicked() { QUiLoader loader; QFile file(":/forms/logInPage.ui"); file.open(QFile::ReadOnly); QWidget *myWidget = loader.load(&file, this); file.close(); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(myWidget); setLayout(layout); }
but I get an error:
QWidget::setLayout: Attempting to set QLayout "" on MainMenu "MainMenu", which already has a layout
With some AI help I managed to change the code to
void MainMenu::on_LogIn_menu_PB_clicked() { QUiLoader loader; QFile file(":/forms/logInPage.ui"); file.open(QFile::ReadOnly); QWidget *myWidget = loader.load(&file, this); file.close(); QLayout *existingLayout = centralWidget()->layout(); if (existingLayout) delete existingLayout; QVBoxLayout *layout = new QVBoxLayout(centralWidget()); layout->addWidget(myWidget); myWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); }
However that just loaded both .ui files at once.
I want to ask if I am mistaken and if so how can I make it appear a single ui file (by ui file I mean all the design inside) -
I tried using setCentralWidget:
void MainMenu::on_LogIn_menu_PB_clicked() { QUiLoader loader; QFile file(":/forms/logInPage.ui"); if (!file.open(QFile::ReadOnly)) { qDebug() << "Cannot open file:" << file.errorString(); return; } QWidget *myWidget = loader.load(&file, this); file.close(); if (!myWidget) { qDebug() << "Failed to load UI file"; return; } // Set the loaded widget as the central widget setCentralWidget(myWidget); }
Which gave me the wanted result however setCentralWidget is a function that can only be used from MainWindow class or from inheritance.
Is there any other way I can get that result without using setCentralWidget function
-
@DeadSo0ul said in Connect ui files from different classes:
Which gave me the wanted result however setCentralWidget is a function that can only be used from MainWindow class or from inheritance.
If you need to access the central widget from other classes, there's an ui design error somewhere.
I suspect you should use signal & slots instead.
Without further details, it's hard to say. -
@DeadSo0ul said in Connect ui files from different classes:
Is there any other way I can get that result without using setCentralWidget function
Show the custom built widgets directly. Nobody forces you to show your UI content as centralwidget.
But as @mpergand said, without further information it's hard to say what fits best in your case. -
@DeadSo0ul
Qt provides QStackedWidget as a convenient way to switch between showing one of a number of widgets. -
-
@DeadSo0ul
Sorry, I do not know you mean.QStackedWidget
holds any number ofQWidget
instances of any classes. Whatever you are doing with "it's own c++ class and .ui file to keep things more organized" can be done just as well with aQSW
as whatever you are doing presently with individual widgets and showing/hiding them yourself.QStackedWidget *sw = new QStackedWidget; sw->addWidget(new QWidget); sw->addWidget(new YourOwnWidgetClassCreatedViaUiFileOrAnyOtherWay);
-
@JonB
I think I understood you but didn't manage to make it work.
I made a public variable in my class of type QStackedWidget:public: explicit logIn(QWidget *parent = nullptr); ~logIn(); QStackedWidget *sw = new QStackedWidget;
Then I created the widget I want the application to redirect to:
LogIn::logIn(QWidget *parent) : QWidget(parent), ui(new Ui::logIn) { ui->setupUi(this); ui->password_LE->setEchoMode(QLineEdit::Password); this->setWindowTitle("Log In"); databaseManager = std::make_unique<DatabaseManager>(); databaseManager->openConnection(); db = databaseManager->getDatabase(); sw->addWidget(this); }
And finally tried to change the index of the QStackedWidget
void MainMenu::on_LogIn_PB_clicked() { logInWindow = new logIn(nullptr); logInWindow->sw->setCurrentIndex(0); }
Did I do anything wrong?
Please let me know.
Thanks! -
@DeadSo0ul
Your code for adding "pages" to a QSW look correct. But you don't seem to have actually added the QSW itself anywhere onto the UI to be visible, just like you would need to for anyQWidget
! QSW itself is aQWidget
, it just happens to show one of its child widgets at any one time So I would expect nothing to show in your code.The QSW does not belong in your
LogIn
class. It belongs on whatever widget you want to show the (choice of) widget instances, exactly where you would place the widgets and useshow
/hide()
if you were doing that yourself. Let's say that is the central widget on aQMainWindow
. Then over in your derived main window class you would have something like:#include <QWidget> #include "logIn.h" #include "someotherofyouruiclass.h" class MyMainWindow : QMainWindow; MyMainWindow::MyMainWindow(QWidget *parent /* = nullptr */) : QMainWindow(parent) { QStackedWidget *sw = new QStackedWidget(this); this->setCentralWidget(sw); sw->addWidget(new QTextEdit); // arbitrary, just to show what's possible sw->addWidget(new Login); // instance of your UI designed class sw->addWidget(new SomeOtherOfYourUiClass); // instance of a different UI designed class // you can do the following line here or e.g. in a main window button click slot sw->setCurrentIndex(1); // show your `Login` instead of the default one at index 0 };
If you are not attempting to show one of a choice of a widgets in the same place as each other then QSW is not your buddy. But I thought that is what you are wanting to do.