I have a database in a separate widget class datbase.ui that I insert as tab in mainwindow.ui. I want that when initializing the connection in the class datbase.ui statusbar in mainwindow.ui to change depending.
datbase.cpp
void DatBase::on_pushButton_clicked()
{
QSqlDatabase ddbb = QSqlDatabase::addDatabase("QSQLITE");
ddbb.setDatabaseName(".../db/ddberdbsqlite");
if (ddbb.open()){
// It is necessary that this status is displayed in mainwindow.ui
// How to get access to gui mainwindow?
ui->statusBar->showMessage("Successful connection!");
}
else{
ui->statusBar->showMessage("Not Successful connection!");
}
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "datbase.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("Measurement DDEBR");
connect(ui->tabWidget, QTabWidget::currentChanged, this, MainWindow::showTabPageIndex);
DatBase *tabDatBase = new DatBase();
ui->tabWidget->insertTab(0, tabDatBase, "Data Base");
}
MainWindow::~MainWindow()
{
delete ui;
}
I have very simple QT Widgets app with QML. It looks like this:
Main ( no changes ):
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
QML:
import QtQuick 2.0
import QtQuick.Controls 2.11
Item {
Button {
text: "Ok"
}
}
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
widget = new QQuickWidget(this);
widget->setSource((QUrl(QStringLiteral("qrc:/test.qml"))));
widget->move(10,10);
widget->resize(400,400);
}
MainWindow::~MainWindow()
{
delete ui;
}
When I run this app from QTCreator, eveything is ok ( I see Button "ok" ). When I run this application from my folder on Desktop I don't see a Button ( my app of course is running ).
My folder on desktop with qmlTest app:
test.qml is in my qrc
First of all, I created about 20 push buttons using for loop. And named them using if else loop. Now, I want to connect each push buttons with the new dialog box. If I had used the design mode of QT, it would show me the name of the button when I press connect(ui->pushButton_0, SIGNAl(released()), SLOT(digit_pressed()) something like this. But, I don't know the name of the pushbutton I made as the for and if else loop made it. The connect(ui-> .......) also doesn't show any predictions. How can I link these push buttons and a new dialog box?
Here is my code:
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();
private:
Ui::MainWindow *ui;
private slots:
void on_pushButton_clicked();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QVBoxLayout>
#include "amputation.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->)
QPixmap pix("/home/skanda/Desktop/D4564.png");
ui->label_2->setPixmap(pix);
setWindowTitle("First Aid");
QVBoxLayout *lay = new QVBoxLayout();
int i;
for(i=0;i<25;i++)
{
if(i==0){
QPushButton *button = new QPushButton("Amputation");
lay->addWidget(button);
}
else if(i==1){
QPushButton *button = new QPushButton("Asthama");
lay->addWidget(button);
}
else if(i==2){
QPushButton *button = new QPushButton("Bleeding");
lay->addWidget(button);
}
else if(i==3){
QPushButton *button = new QPushButton("Burns");
lay->addWidget(button);
}
else if(i==4){
QPushButton *button = new QPushButton("Chest Pain");
lay->addWidget(button);
}
else if(i==5){
QPushButton *button = new QPushButton("Diarrhoea");
lay->addWidget(button);
}
else if(i==6){
QPushButton *button = new QPushButton("Drowning");
lay->addWidget(button);
}
else if(i==7){
QPushButton *button = new QPushButton("Epilepsy");
lay->addWidget(button);
}
else if(i==8){
QPushButton *button = new QPushButton("Fainting");
lay->addWidget(button);
}
else if(i==9){
QPushButton *button = new QPushButton("Fever");
lay->addWidget(button);
}
else if(i==10){
QPushButton *button = new QPushButton("Food Poisoning");
lay->addWidget(button);
}
else if(i==11){
QPushButton *button = new QPushButton("Fracture");
lay->addWidget(button);
}
else if(i==12){
QPushButton *button = new QPushButton("Head Injury");
lay->addWidget(button);
}
else if(i==13){
QPushButton *button = new QPushButton("Muscle Strain");
lay->addWidget(button);
}
else if(i==14){
QPushButton *button = new QPushButton("No breathing");
lay->addWidget(button);
}
else if(i==15){
QPushButton *button = new QPushButton("Nose bleed");
lay->addWidget(button);
}
else if(i==16){
QPushButton *button = new QPushButton("Poisoning");
lay->addWidget(button);
}
else if(i==17){
QPushButton *button = new QPushButton("Snake Bites");
lay->addWidget(button);
}
else if(i==18){
QPushButton *button = new QPushButton("Stroke");
lay->addWidget(button);
}
else if(i==19) {
QPushButton *button = new QPushButton("Sun Burn");
lay->addWidget(button);
}
else if(i==20) {
QPushButton *button = new QPushButton("Testicle Pain");
lay->addWidget(button);
}
else if(i==21) {
QPushButton *button = new QPushButton("Ulcer");
lay->addWidget(button);
}
else if(i==22) {
QPushButton *button = new QPushButton("Child delievery");
lay->addWidget(button);
}
else if(i==23) {
QPushButton *button = new QPushButton("Heart Attack");
lay->addWidget(button);
}
else {
QPushButton *button = new QPushButton("Gastric");
lay->addWidget(button);
}
}
ui->scrollContents->setLayout(lay);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked(){
Amputation amp;
amp.setModal(true);
amp.show();
}
**In these codes, I have tried my luck by creating on_pushButton_clicked() function. But, it was just a try. **
As in programming everything is cooking, :), let's see what are the ingredients of connect():
connect(sender, &Sender::signal, receiver, &Receiver::slot);
so sender would be the buttons, the signal is the clicked, the receiver itself, that is, this, and the slot on_pushButton_clicked
I see unnecessary if-else, everything can be reduced to a for:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QVBoxLayout>
#include "amputation.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pix("/home/skanda/Desktop/D4564.png");
ui->label_2->setPixmap(pix);
setWindowTitle("First Aid");
QVBoxLayout *lay = new QVBoxLayout();
QStringList names{"Amputation", "Asthama", "Bleeding", "Burns", "Chest Pain",
"Drowning", "Diarrhoea", "Epilepsy", "Fainting", "Fever",
"Food Poisoning", "Fracture", "Head Injury", "Muscle Strain",
"No breathing", "Nose bleed", "Poisoning", "Snake Bites",
"Stroke","Sun Burn", "Testicle Pain", "Ulcer", "Child delievery",
"Heart Attack", "Gastric"};
for(const QString & name: names)
{
QPushButton *button = new QPushButton(name);
lay->addWidget(button);
connect(button, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked)
}
ui->scrollContents->setLayout(lay);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked(){
Amputation amp;
amp.setModal(true);
amp.show();
}
Note:
avoid using the old style of connection, has many disadvantages, read the content of the following link for more information:
https://wiki.qt.io/New_Signal_Slot_Syntax
Make all these QPushButton members of a class such that they are created and destroyed properly rather than creating them in an loop.
Once you have each one as a separate member, then have a method InitializeConnections() and make all the connections under it using the Qt connect syntax.
If you believe these buttons are part of the MainWindow class, then your class can look something like this :
class MainWindow{
...
...
private :
// Will make connections of each button to it's respective slot.
void InitializeConnections();
private :
QPushButton *mAmputationButton;
QPushButton *mAsthmaButton;
//.. so on
};
And in MainWindow.cpp :
#include <QPushButton>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
mAmputationButton(new QPushButton("Amputation") ),
mAsthmaButton(new QPushButton("Asthama") )
{
InitializeConnections();
}
void MainWindow::InitializeConnections()
{
connect(mAmputationButton, &QPushButton::clicked, this, &MainWindow::amputation_slot );
connect(mAsthmaButton, &QPushButton::clicked, this, &MainWindow::asthma_slot );
// same way for others.
}
The slots that i have mentioned are just for example, connect it to the slot that you need it to be connected to.
UPDATE :
Here is a mini-implementation made using just the two buttons :
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QPushButton;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QPushButton *mAmputationButton;
QPushButton *mAsthmaButton;
private slots:
void on_pushButton_clicked();
};
MainWindow.cpp
#include "MainWindow.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
mAmputationButton( new QPushButton("Amputation" ) ),
mAsthmaButton( new QPushButton("Astham" ) )
{
setWindowTitle("First Aid");
QWidget *sampleWidget = new QWidget();
QVBoxLayout *lay = new QVBoxLayout();
lay->addWidget(mAmputationButton);
connect(mAmputationButton, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked );
connect(mAsthmaButton, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked );
lay->addWidget(mAsthmaButton);
sampleWidget->setLayout(lay);
setCentralWidget(sampleWidget);
}
MainWindow::~MainWindow(){}
void MainWindow::on_pushButton_clicked(){
QDialog *sampleDialog = new QDialog();
sampleDialog->setModal(true);
sampleDialog->show();
}
Note1 : In the slot on_pushbutton_clicked, I am just creating a new dialog and showing it. Just add your slot logic there and you will be good to go.
Note2 : It will be advisable to have all your connections in a single method such as Initialize Connections as already mentioned above.
Take this mini-implementation just as an example that you can work on top of rather than a copy-paste use of it.
I'm starting with Qt. Previously I did with Java Swing, where I accomplished this by Card Layout. I have MainWindow, Login Widget and Dashboard Widget.
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// set login screen on startup
QWidget *login = new Login(this);
setCentralWidget(login);
}
Login.cpp
#include "login.h"
#include "ui_login.h"
Login::Login(QWidget *parent) :
QWidget(parent),
ui(new Ui::Login)
{
ui->setupUi(this);
}
Login::~Login()
{
delete ui;
}
void Login::on_loginButton_clicked()
{
// some logic
// here I want to create Dashboard widget in central widget
// but method setCentralWidget() can't be called from here
}
You want to use signals and slots to communicate between the windows. QDialog provides three important signals in particular: accepted(), rejected(), finished(int). So you'll want to do something like this:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// set login screen on startup
QWidget *login = new Login(this);
connect(login, SIGNAL(finished(int)), this, SLOT(loginFinished(int)));
setCentralWidget(login);
}
MainWindow::loginFinished(int reason)
{
Login *login = qobject_cast<Login*>(sender());
if (!login) {
qDebug() << "something bad happened!";
return;
}
login->deleteLater();
setCentralWidget(someOtherWidget);
}
I have a tableView example:
Like when the data column status is S.
The background color of the table would be green and when N would be red.
Example of what I want:
My code:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
//Con Db...
model = new QSqlTableModel(this);
model->setTable("app");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->setHeaderData(0, Qt::Horizontal, tr("number"));
model->setHeaderData(1, Qt::Horizontal, tr("status"));
ui->tableView->setModel(model);
}
Could someone help me?
Reimplement, i.e. subclass QSqlTableModel and provide an implementation of the data function as per below. Note that the MySubClassedSqlTableModel implementation needs to be placed in a header file that is MOC'ed (normally automatically done).
#include <QSqlTableModel>
class MySubClassedSqlTableModel : public QSqlTableModel
{
Q_OBJECT
public:
MySubClassedSqlTableModel(QObject * parent = 0, QSqlDatabase db = QSqlDatabase())
: QSqlTableModel(parent,db) {;}
QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const
{
if(role==Qt::BackgroundColorRole)
{
const QVariant value(data(index,Qt::DisplayRole));
return QVariant(QColor(value.toString()=="S"?Qt::green:Qt::red));
}
return QSqlTableModel::data(index,role);
}
};
model = new MySubClassedSqlTableModel(this); //<==== use your model
model->setTable("app");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->setHeaderData(0, Qt::Horizontal, tr("number"));
model->setHeaderData(1, Qt::Horizontal, tr("status"));
ui->tableView->setModel(model);
Btw subclassing is something you need to do in most cases when you want to customize the behavior.