Update MainWindow for dialog - c++

I have a MainWindow with a menu that opens a dialog for registration. How can I update the tableView in the MainWindow after the registration?
Here is my MainWindow implementation:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
ui->setupUi(this);
}
void MainWindow::list()
{
qDebug() << "test";
QSqlQueryModel *model = new QSqlQueryModel();
//model->clear();
model->setQuery("SELECT test_qt FROM db_qt WHERE strftime('%Y-%m-%d', date)='"+dateTime.toString("yyyy-MM-dd")+"'");
model->setHeaderData(0, Qt::Horizontal, tr("qt_test"));
ui->tableView->setModel(model);
}
void MainWindow::on_actionMenu_triggered()
{
dialog_test->show();
}
Here is my Dialog implementation
Dialog_test::Dialog_test(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog_test)
{
ui->setupUi(this);
}
void Dialog_test::insert_date(){
QSqlQuery qry;
qry.prepare("INSERT INTO db_qt(test_qt) VALUES (?)");
qry.addBindValue(id);
if (qry.lastInsertId()>0){
QMessageBox::information(this,"test", "Success");
MainWindow *mw = new MainWindow(this);
mw->list(); // I call back list, but not update the tableView the MainWindow.
}
}

The following line in your code
MainWindow *mw = new MainWindow(this);
creates a new main window and updates the list of it. I assume this actually happens, but the window is never shown so you do not see any of it. What you actually want to do is update the list of your existing main window.
There are basically two ways of doing that. You can either obtain a pointer to the existing main window (which can be provided to the constructor of the dialog or a method of its own) or use the Signals and Slots concept of Qt which is the way to go in my opinion.
First of all, you define the signal in the header of the dialog:
...
signals:
void user_registered();
...
Then you emit the signal in your function
//MainWindow *mw = new MainWindow(this);
//mw->list();
emit this->user_registered();
Make sure the list() method is declared as a SLOT in the MainWindow header
Connect the signal in the MainWindow constructor to call the list() slot:
...
QObject::connect(this->dialog_test, SIGNAL(user_registered()), this, SLOT(list()));
...
With this approach, the dialog does not need to know the main window at all. It basically just tells anyone who is interested that a user registered and the main window acts on it completly by itself.

Related

QPlainTextEdit() ->setPlainText() keeps crashing

I'm trying to update a QPlainTextEdit() from either a button click, thread, etc. Somewhere from outside the MainThread and in Qt documentation it says it must used signals but I can't figure out how. If I try to do a CreateThread() or use a std::thread to update the
class MainWindow : public QMainWindow
{
Q_OBJECT
...
private slots:
handleButtonClick();
Thread();
...
private:
QPlainTextEdit *TextView;
}
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
...
TextView = new QPlainTextEdit();
TextView->setReadOnly(true);
TextView->setCursorWidth(0);
QPUshButton *UpdateButton = new QPushButton();
connect(UpdateButton, SIGNAL(released()), this, SLOT(handleButtonClick()));
....
}
MainWindow::handleButtonClick()
{
// eventually this will cause a crash, usually not imemdiately
TextView->insertPlainText("test");
}
MainWindow::Thread()
{
TextView->insertPlainText("test");
}
So as you can see, I want a way to update this QPlainTextEdit from outside the main thread without crashes. How can I do this? Thanks.
You are not allowed to do UI opeations like updating the text of a QTextEdit from outside the main thread. The solution to this is emitting a signal from the non-main thread, and have it connected to a slot in the main thread which does the UI work.

Qt creating MDI document window

I am trying to create a MDI document program. I have a question on creating the subwindow.
This is my mainwindow constructor:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle(tr("MDI"));
workspace = new QMdiArea;
setCentralWidget(workspace);
//fileNew();
createActions();
createMenus();
createToolbars();
statusBar()->showMessage(tr("Done"));
enableActions();
}
The interesting point is the fileNew(); function. It is a private slot function actually which I want to invoke when "New File" button is triggered. Here is the private slot fileNew() function:
void MainWindow::fileNew()
{
DocumentWindows* document = new DocumentWindows;
workspace->addSubWindow(document);
}
This function works perfectly when I call from the mainwindow constructor. However, there is a problem when I call it from the createActions(); function which uses a signal-slot mechanism.
Here is my createActions()
void MainWindow::createActions()
{
newAction = new QAction(QIcon(":/Image/NewFile.png"),tr("&New"),this);
newAction->setShortcut(tr("Ctrl+N"));
newAction->setToolTip(tr("Open new document"));
connect(newAction, SIGNAL(triggered(bool)), this, SLOT(fileNew()));
}
No subwindow is created even the SLOT is triggered. Subsequently, I find out that if I add document->show();, everything works well.
void MainWindow::fileNew()
{
DocumentWindows* document = new DocumentWindows;
workspace->addSubWindow(document);
document->show();
}
My question is: Why the show() function is needed in a SLOT but not in the constructor?
PS. DocumentWindows is just a class inherits QTextEdit.
This problem has nothing to do with the class of the widgets one is using. It is unrelated to documents, MDI, or the main window. After you add a child widget to a widget that is already visible, you must explicitly show it. Otherwise, the widget will remain hidden.
All widgets are hidden by default. When you initially show the MainWindow, all of its children are recursively shown too. When you later add a child MDI widget, it remains hidden. When widgets are added to layouts, they are shown by default - but your widget is managed by the MDI area, not by a layout.
This is a minimal test case demonstrating your issue:
// https://github.com/KubaO/stackoverflown/tree/master/questions/widget-show-32534931
#include <QtWidgets>
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QWidget w;
w.setMinimumSize(200, 50);
QLabel visible{"Visible", &w};
w.show();
QLabel invisible{"Invisible", &w};
invisible.move(100, 0);
return app.exec();
}

Handling multiple windows in Qt

I use QStackedWidget to handle multiple windows/forms in a Qt application
according to this question.
I use this pattern:
Add all widget objects to the QStackedWidget in mainwindow.cpp
Get signal from sub-window on request to change window
mainwindow replaces the window (it updates the QStackedWidget in the right slot)
My question :
is this the right way to do this? I have a lot of windows in my applications and want to ensure this is the common best practice.
This pattern means that i have pointers to all of the windows in my main window.
piece of my code:
mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mnuWin = new Menu();
singlePulseWin = new SinglePulse();
repetitive = new Repetitive();
treatmentType = new TreatmentType();
//... and so on ....
connect(mnuWin,&Menu::updateMainWindowStackWidget,this,&MainWindow::onChangeWindowRequested);
connect(singlePulseWin,&SinglePulse::updateMainWindowStackWidget,this,&MainWindow::onChangeWindowRequested);
connect(repetitive,&Repetitive::updateMainWindowStackWidget,this,&MainWindow::onChangeWindowRequested);
connect(treatmentType,&TreatmentType::updateMainWindowStackWidget,this,&MainWindow::onChangeWindowRequested);
//... and so on ....
ui->pagesWidget->addWidget(mnuWin);
ui->pagesWidget->addWidget(singlePulseWin);
ui->pagesWidget->addWidget(repetitive);
ui->pagesWidget->addWidget(treatmentType);
//... and so on ....
ui->pagesWidget->setCurrentIndex(0);
}
void MainWindow::onChangeWindowRequested(int ind) //slot
{
ui->pagesWidget->setCurrentIndex(ind);
}
menu.cpp :
void Menu::on_btnMenuSinglePulse_clicked()
{
emit updateMainWindowStackWidget(1);
}
void Menu::on_btnMenuRepetitive_clicked()
{
emit updateMainWindowStackWidget(2);
}
void Menu::on_btnMenuBurst_clicked()
{
emit updateMainWindowStackWidget(3);
}
QStackedWidget is a good way to deal with Multi-window .why not put the buttons in the mainWindow ,so that you can change the pagesWidget's currentWidget more convenient instead of create signal-slot

Qt build menu for touch screen

i want to build a QT application for windows/android.
I have one mainwindow in which i have different buttons to call submenus, as you can see on the pictures. What do you think is the best implementation for that?
I thought about replacing the central widget
Using QStackwidget
Or open a new widget on the same position and size and close after.
What do you think? Do you have some favourite implementation or do i miss some important?
Edit
My Mainwindow constructor
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_stacked = new QStackedWidget;
HomeScreen *homescreen=new HomeScreen(m_stacked);
Control *manual=new Control(m_stacked);
m_stacked->addWidget(homescreen);
m_stacked->addWidget(manual);
this->setCentralWidget(m_stacked);
}
Implementation of every Screen
class HomeScreen : public QWidget
{
Q_OBJECT
public:
explicit HomeScreen(QStackedWidget* stack, QWidget *parent = 0);
~HomeScreen();
private slots:
void on_pushButton_clicked();
private:
Ui::HomeScreen *ui;
QStackedWidget *m_stacks;
};
HomeScreen::HomeScreen(QStackedWidget* stack,QWidget *parent) :
m_stacks(stack),QWidget(parent),
ui(new Ui::HomeScreen)
{
ui->setupUi(this);
}
HomeScreen::~HomeScreen()
{
delete ui;
}
void HomeScreen::on_pushButton_clicked()
{
m_stacks->setCurrentIndex(1);
}
What is your solution to change the current Widget, inside a widget of the QStackwidget? I used the solution above what do you think about it?
QStackedWidget was made right for that, I don't see any reason why you should incline to other options. You can always removeWidget(widget) and delete widget; if you want to free the memory of some rarely used menu.
Edit:
Your code is fine, there can be only a few enhancements made. You can create enum for your indexes in some separate header file.
Option 1:
If you use only QStackedWidget as a parent menu, you can adjust the constructor:
HomeScreen(QStackedWidget* parent) :
QWidget(parent),
ui(new Ui::HomeScreen)
{
ui->setupUi(this);
}
If you'd want to access QStackedWidget and change an index, you spare m_stacks pointer and use the parent: dynamic_cast<QStackedWidget*>(parent())->setCurrentIndex(1 /* or enum */);.
Option 2:
Leave index changing to the parent MainWindow. Each menu will have a request signal:
signals:
void goToMenuRequest(int index /* or enum */);
which you connect to m_stacked's setCurrentIndex in the constructor of MainWindow.
Not a big things, but It'll make coding easier.

Emit signal between two classes in Qt

A am trying to make a program that takes a signal from one class and with activation of that signal I want to activate a slot in second class.
In my case the first class is the mainWindow class, this class is subClass of QMainWindow, and in this class is the slot that I want to activate.
This is mainWindow.cpp:
mainWindow::mainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::mainWindow)
{
ui->setupUi(this);
}
mainWindow::~mainWindow()
{
delete ui;
}
void mainWindow::slotForStatusBarMessage(QString string)
{
statusBar()->showMessage(string);
}
The second class is the mainWidget class and it is a subclass of QWidget.
This is mainWidget.cpp:
mainWidget::mainWidget(QWidget *parent) :
QWidget(parent)
{
buttonAddNewRecord=new QPushButton("Add new record", this);
layoutButton=new QHBoxLayout();
layoutButton->addWidget(buttonAddNewRecord);
layoutMain=new QVBoxLayout();
layoutMain->addLayout(layoutButton);
functionDatabaseOpen();
setLayout(layoutMain);
}
The signal is emited from functionDatabaseOpen() function:
if (sqlDatabase.open())
{
emit signalForShowMessageInStatusBar("true");
}
else
{
emit signalForShowMessageInStatusBar("false");
}
I have made all the settings to the database but i didnt copy here because of space.
I have tried to make connection inside main.cpp but it seems it dosent work.
QObject::connect(mw, SIGNAL(signalForShowMessageInStatusBar(QString)), w, SLOT(slotForStatusBarMessage(QString)));
I cant make this signal/slot connection between classes to work. Can you give me any help.
If you have any question about the code please ask. Sorry for the bad english,I am not a native english speaker.
Thank you very much for your help.
You are emitting the signal from the constructor of mainWidget, and since the connection is only done after you return from that constructor, the signal doesn't go anywhere.
The easiest fix, not knowing what the rest of the code looks like, would be to move the call to functionDatabaseOpen() in main() after the signal/slot connection is made.