2016-07-08 2 views
0

Je suis assez nouveau à Qt. J'ai commencé il y a environ deux mois avec les applications QWidgets et tout allait bien. Maintenant j'ai un vrai problème. J'ai besoin d'intégrer ma logique C++ dans mon Qml Ui. Je vais poster mon code source depuis mon application QWidget et mon interface utilisateur écrite en Qml. Ce que je dois faire est de faire fonctionner mon application avec un Ui intégré Qml. Cela fonctionne bien avec QWidgets mais je n'ai aucune idée de comment l'intégrer dans Qml. J'ai cherché le net pendant 2 jours, mais je ne semble pas saisir les concepts. Compte tenu du fait que je suis complet noob concernant Qml, tout conseil serait grandement apprécié.Qt. Intégrer C++ et Qml

Voici mon C++/QWidgets Version:

têtes: mainwindow.h

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 

class MainWindow : public QMainWindow 
    { 
Q_OBJECT 

public: 
MainWindow(QMainWindow *parent = 0); 
~MainWindow(); 
}; 

#endif // MAINWINDOW_H 

addressbook.h

#ifndef ADDRESSBOOK_H 
#define ADDRESSBOOK_H 
#include <QMainWindow> 
#include <QWidget> 
#include <QTextEdit> 
#include <QPushButton> 
#include <QObject> 
#include <QLineEdit> 
#include <QLabel> 
#include <QListWidget> 
#include <QFrame> 
#include <QList> 
#include <QGridLayout> 
#include <QString> 
#include <QStringList> 
#include <QKeyEvent> 
#include <QCoreApplication> 

class AddressBook4 : public QWidget 
{ 
    Q_OBJECT 

public: 
    explicit AddressBook4(QWidget *parent = 0); 
    ~AddressBook4(); 
    struct Details 
    { 
     QString name; 
     QString street; 
     QString number; 
     QString notes; 
    }; 

signals: 

public slots: 

private slots: 
    void add(bool); 
    void onListWidgetItemClicked(const QModelIndex &index); 
    void importSql (bool); 
    void exportSql (bool); 

private: 
    QTextEdit *m_pNotesTextEdit; 
    QTextEdit *m_pDetailsTextEdit; 

    QLineEdit *m_pNameLineEdit; 
    QLineEdit *m_pStreetLineEdit; 
    QLineEdit *m_pNumberLineEdit; 

    QListWidget *m_pListWidget; 

    QPushButton *m_pAddbutton; 
    QPushButton *m_pImportbutton; 
    QPushButton *m_pExportbutton; 

    QFrame *m_pFrame; 
    QLabel *m_pAddAdress; 
    QLabel *m_pName; 
    QLabel *m_pStreet; 
    QLabel *m_pNumber; 
    QLabel *m_pDetails; 
    QLabel *m_pNotes; 
    QLabel *m_pAddresses; 

    QGridLayout *m_pGrid; 
    QString *line; 
    QListWidgetItem *item; 

    QList<Details> m_detailsList; 
}; 

#endif // ADDRESSBOOK_H 

fichiers RPC: mainwindow.cpp

#include "mainwindow.h" 
#include "addressbook.h" 

MainWindow::MainWindow(QMainWindow *parent) 
    : QMainWindow(parent) 
{ 
    AddressBook4 *addressbook4 = new AddressBook4(this); 
    setCentralWidget(addressbook4); 
} 

MainWindow::~MainWindow() 
{ 
} 

addressbook.cpp

#include "addressbook.h" 
#include "mainwindow.h" 
#include <QMainWindow> 
#include <QWidget> 
#include <QMessageBox> 
#include <QTextEdit> 
#include <QLabel> 
#include <QLineEdit> 
#include <QListWidget> 
#include <QGridLayout> 
#include <QFrame> 
#include <QPushButton> 
#include <QTextStream> 
#include <QtCore> 
#include <QString> 
#include <QTextStream> 
#include <QFile> 
#include <QStringList> 
#include <QtSql> 
#include <QCoreApplication> 
#include <QApplication> 

#define FISIER_ADRESE "C:\\Users\\max\\Documents\\workspace\\AddressBook5\\Addresses.db" 

AddressBook4::AddressBook4(QWidget *parent) 
    : QWidget(parent) 
{ 
    m_pGrid = new QGridLayout(this); 

    m_pFrame = new QFrame(this); 
    m_pGrid->addWidget(m_pFrame,1,0,8,4); 
    m_pFrame->setFrameShape(QFrame::StyledPanel); 

    m_pAddAdress = new QLabel("Add address", this); 
    m_pGrid->addWidget(m_pAddAdress,1,2); 
    m_pAddAdress->setAlignment(Qt::AlignRight | Qt::AlignVCenter); 

    m_pName = new QLabel("Name:", this); 
    m_pGrid->addWidget(m_pName,2,1); 
    m_pName->setAlignment(Qt::AlignLeft | Qt::AlignTop); 

    m_pNameLineEdit = new QLineEdit(this); 
    m_pGrid->addWidget(m_pNameLineEdit,2,2); 

    m_pStreet = new QLabel("Street:", this); 
    m_pGrid->addWidget(m_pStreet,3,1); 
    m_pStreet->setAlignment(Qt::AlignLeft | Qt::AlignTop); 

    m_pStreetLineEdit = new QLineEdit(this); 
    m_pGrid->addWidget(m_pStreetLineEdit,3,2); 

    m_pNumber = new QLabel("Number:", this); 
    m_pGrid->addWidget(m_pNumber,4,1); 
    m_pNumber->setAlignment(Qt::AlignLeft | Qt::AlignTop); 

    m_pNumberLineEdit = new QLineEdit(this); 
    m_pGrid->addWidget(m_pNumberLineEdit,4,2); 
    m_pNumberLineEdit->setFixedWidth(50); 

    m_pNotes = new QLabel("Notes:", this); 
    m_pGrid->addWidget(m_pNotes,6,1); 
    m_pNotes->setAlignment(Qt::AlignLeft | Qt::AlignTop); 

    m_pNotesTextEdit = new QTextEdit(this); 
    m_pGrid->addWidget(m_pNotesTextEdit,6,2); 

    m_pAddbutton= new QPushButton ("Add",this); 
    m_pGrid->addWidget(m_pAddbutton, 7,2,Qt::AlignBaseline); 

    m_pImportbutton= new QPushButton ("ImportSql",this); 
    m_pGrid->addWidget(m_pImportbutton, 7,4,Qt::AlignBaseline | Qt::AlignLeft); 
    m_pImportbutton->setFixedWidth(80); 
    m_pImportbutton->setShortcut(QKeySequence(Qt::Key_Insert)); 

    m_pExportbutton= new QPushButton ("ExportSql",this); 
    m_pGrid->addWidget(m_pExportbutton, 7,4,Qt::AlignBaseline | Qt::AlignRight); 
    m_pExportbutton->setFixedWidth(80); 

    m_pAddresses = new QLabel("Addresses", this); 
    m_pGrid->addWidget(m_pAddresses,1,4); 
    m_pAddresses->setAlignment(Qt::AlignRight | Qt::AlignVCenter); 

    m_pListWidget = new QListWidget(this); 
    m_pGrid->addWidget(m_pListWidget,2,4,3,1); 

    m_pDetails = new QLabel("Details", this); 
    m_pGrid->addWidget(m_pDetails,5,4); 
    m_pDetails->setAlignment(Qt::AlignRight | Qt::AlignVCenter); 

    m_pDetailsTextEdit = new QTextEdit(this); 
    m_pGrid->addWidget(m_pDetailsTextEdit,6,4); 
    m_pDetailsTextEdit->setReadOnly(true); 

    setLayout(m_pGrid); 

    connect(m_pAddbutton, SIGNAL(clicked(bool)), 
      this, SLOT(add(bool))); 
    connect(m_pListWidget, SIGNAL(clicked(QModelIndex)), 
      this, SLOT(onListWidgetItemClicked(const QModelIndex))); 
    connect(m_pImportbutton, SIGNAL(clicked(bool)), 
      this, SLOT(importSql(bool))); 
    connect(m_pExportbutton, SIGNAL(clicked(bool)), 
      this, SLOT(exportSql(bool))); 

} 

//Reads the user imput data from m_pNameLineEdit, m_pStreetLineEdit, m_pNumberLineEdit, 
//m_pNotesiTextEdit and creates a new QListWidget item every time when clicked. 
void AddressBook4::add(bool) 
{ 
    if ((m_pNameLineEdit->text().isEmpty()) || (m_pStreetLineEdit->text().isEmpty()) 
     || (m_pNumberLineEdit->text().isEmpty()) || (m_pNotesTextEdit->toPlainText().isEmpty())) 
    { 
     QMessageBox::warning(this, "Warning", "You need to complete all the fields"); 
    } else { 
     int index = m_pListWidget->count(); 
     m_pListWidget->addItem("address " + QString::number(index)); 

     Details detail; 
     detail.name = m_pNameLineEdit->text(); 
     detail.street = m_pStreetLineEdit->text(); 
     detail.number = m_pNumberLineEdit->text(); 
     detail.notes = m_pNotesTextEdit->toPlainText(); 

     m_detailsList.append(detail); 
    } 
} 

//Prints the data from every QListWidgetItem in the m_pDetailsTextEdit when clicked 
void AddressBook4::onListWidgetItemClicked(const QModelIndex &index) 
{ 
    m_pDetailsTextEdit->clear(); 
    m_pDetailsTextEdit->append("Name: " + m_detailsList.at(index.row()).name); 
    m_pDetailsTextEdit->append("Street: " + m_detailsList.at(index.row()).street); 
    m_pDetailsTextEdit->append("Nr.: " + m_detailsList.at(index.row()).number); 
    m_pDetailsTextEdit->append("Notes: " + m_detailsList.at(index.row()).notes); 
} 

//Imports data from the Sql database and attributes it to QListWidget items 
void AddressBook4::importSql(bool) 
{ 
    QSqlDatabase my_db = QSqlDatabase::addDatabase("QSQLITE"); 
    my_db.setDatabaseName(FISIER_ADRESE); 
    my_db.open(); 

    qDebug() << "Connected to database..." ; 

    QSqlQuery my_qry("SELECT * FROM Addresses"); 
    int idx_Name = my_qry.record().indexOf("Name"); 
    int idx_Street = my_qry.record().indexOf("Street"); 
    int idx_Number = my_qry.record().indexOf("Number"); 
    int idx_Notes = my_qry.record().indexOf("Notes"); 
    while (my_qry.next()) { 
     Details detail; 
     detail.name = my_qry.value(idx_Name).toString(); 
     //qDebug() << detail.name; 
     detail.street = my_qry.value(idx_Street).toString(); 
     //qDebug() << detail.street; 
     detail.number = my_qry.value(idx_Number).toString(); 
     //qDebug() << detail.number; 
     detail.notes = my_qry.value(idx_Notes).toString(); 
     //qDebug() << detail.notes <<"\n"; 
     m_detailsList.append(detail); 
     int index = m_pListWidget->count(); 
     m_pListWidget->addItem("address " + QString::number(index)); 
    } 
} 

//Reads through every QlistWidget item and inserts the containing data into the Sql database 
void AddressBook4::exportSql(bool) 
{ 
    QSqlDatabase my_db = QSqlDatabase::addDatabase("QSQLITE"); 
    my_db.setDatabaseName(FISIER_ADRESE); 

    if (!my_db.open()) { 
     QMessageBox::warning(this, "Warning", "Cannot connect to the database"); 
    } else { 
     qDebug() << "Connected to database..."; 
     QSqlQuery my_qry; 
     my_qry.prepare("CREATE TABLE IF NOT EXISTS Addresses (Name QSTRING, " 
         "Street QSTRING, Number QSTRING, Notes QSTRING)"); 
      if(!my_qry.exec()) 
      qDebug() << my_qry.lastError(); 
      else 
      qDebug() << "Table created!"; 

      for (int row = 0; row < m_pListWidget->count(); ++row) { 
       item = m_pListWidget->item(row); 
       Details detail = m_detailsList.at(row); 

      my_qry.prepare("INSERT INTO Addresses (Name, Street, Number, Notes) " 
          "VALUES (:Name, :Street, :Number, :Notes)"); 
      my_qry.bindValue(":Name", detail.name); 
      my_qry.bindValue(":Street", detail.street); 
      my_qry.bindValue(":Number", detail.number); 
      my_qry.bindValue(":Notes", detail.notes); 
      if(!my_qry.exec()) 
       qDebug() << my_qry.lastError(); 
      else 
       qDebug() << "Inserted!"; 
     } 
    } 

} 

AddressBook4::~AddressBook4() 
{ 
} 

main.cpp

#include <QApplication> 
#include "addressbook.h" 
#include "mainwindow.h" 
#include <QMainWindow> 
#include <QWidget> 
#include <QTextStream> 
#include <QString> 
#include <QTextStream> 
#include <QFile> 
#include <QStringList> 
#include <QtCore> 
#define STYLE_SHEET "C:\\Users\\max\\Documents\\workspace\\AddressBook4\\stylesheet.css" 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 

    MainWindow w; 
    w.setWindowTitle("AddressBook4"); 
    w.show(); 

    //QFile file (STYLE_SHEET); 
    //if (file.open(QFile::ReadOnly | QFile::Text)) { 
     // QTextStream in(&file); 
     //QString styleStr = in.readAll(); 
     //qDebug() << styleStr; 
     //file.close(); 
     //a.setStyleSheet(styleStr); 
    //} 

    return a.exec(); 
} 

Et maintenant, je vais poster ma version QtQuick.

têtes: buttons.h

#ifndef BUTTONS_H 
#define BUTTONS_H 

#include <QObject> 
#include <QDebug> 

class Buttons : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit Buttons(QObject *parent = 0); 

public slots: 
    void addClicked(const QStringList &in); 
    void exportClicked(); 
    void importClicked(); 
}; 

#endif // BUTTONS_H 

fichiers Cpp: main.cpp

#include <QApplication> 
#include <QQmlApplicationEngine> 
#include "buttons.h" 
#include <QQmlContext> 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 

    QQmlApplicationEngine engine; 
    engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 

    Buttons buttons; 

    engine.rootContext()->setContextProperty("buttons", &buttons); 

    return app.exec(); 
} 

buttons.cpp

#include "buttons.h" 
#include <QApplication> 
#include <QObject> 
#include <QString> 
#include <QDebug> 

Buttons::Buttons(QObject *parent) : 
    QObject(parent) 
{ 
} 
void Buttons::addClicked(const QStringList &in) 
{ 
    qDebug() << in; 
} 

void Buttons::exportClicked() 
{ 
    qDebug() << "Works"; 
} 

void Buttons::importClicked() 
{ 
    qDebug() << "Works"; 
} 

et mon fichier main.qml

import QtQuick 2.4 
import QtQuick.Controls 1.3 
import QtQuick.Layouts 1.3 

ApplicationWindow { 
    visible: true 
    title: "AddressBookQml" 
    property int margin: 11 


    GridLayout { 
     id: mainLayout 
     anchors.fill: parent 
     anchors.margins: margin 


     GroupBox { 
      id: gridBox 
      title: "Add address" 
      Layout.fillWidth: true 
      Layout.fillHeight: true 

      GridLayout { 
       id: gridLayout 
       rows: 5 
       columns: 2 
       flow: GridLayout.TopToBottom 
       anchors.fill: parent 

       Label { text: "Name" } 
       Label { text: "Street" } 
       Label { text: "Number" } 
       Label { text: "Notes"} 
       Button { 
        text: "Add " 
        onClicked: buttons.addClicked("Name:" + textfield_1.text + "Street:" + 
                 textfield_2.text + "Number:" + 
                 textfield_3.text + "Notes:" + textArea_1.text) 

       } 

       TextField { 
        id: textfield_1 
        Layout.fillWidth: true 
       } 
       TextField { 
        id: textfield_2 
        Layout.fillWidth: true 
       } 
       TextField { 
        id: textfield_3 
       } 
       TextArea { 
        id: textArea_1 
        Layout.rowSpan: 1 
        Layout.fillHeight: true 
        Layout.fillWidth: true 
       } 

      } 
     } 

     GroupBox { 
      id: gridBox2 
      Layout.fillWidth: true 
      Layout.fillHeight: true 

      GridLayout { 
       id: gridLayout2 
       rows: 5 
       flow: GridLayout.TopToBottom 
       anchors.fill: parent 

       GridLayout { 
        id: gridLayout4 
        rows: 2 

        flow: GridLayout.TopToBottom 
        anchors.fill: parent 

        Label { text: "Addresses" } 

        ListModel { 
         id: model 
         ListElement { 
          name: 'Address 1' 

         } 
         ListElement { 
          name: 'Address 2' 
         } 

        } 

        ScrollView { 
         ListView { 
          id: list 
          anchors.fill: parent 
          model: model 


          Layout.rowSpan: 1 
          Layout.fillHeight: true 
          Layout.fillWidth: true 

          delegate: Component { 
           Item { 
            width: parent.width 
            height: 15 
            Column { 
             Text { text: name } 
             //Text { text: 'Number:' + number } 
            } 
            MouseArea { 
             anchors.fill: parent 
             onClicked: list.currentIndex = index 
            } 
           } 
          } 
          highlight: Rectangle { 
           color: "white" 
           Text { 
            anchors.centerIn: parent 
           } 
          } 
          focus: true 
          onCurrentItemChanged: console.log(model.get(list.currentIndex).name + ' selected') 
         } 
        } 
       } 

       Label { text: "Detalii" } 

       TextArea { 
        Layout.rowSpan: 2 
        Layout.fillHeight: true 
        Layout.fillWidth: true 
        readOnly: true 
       } 

       GroupBox { 
        id: gridBox3 
        Layout.fillWidth: true 

        GridLayout { 
         id: gridLayout3 
         rows: 1 
         flow: GridLayout.LeftToRight 
         Button { 
          text: "ExportSql " 
          onClicked: buttons.exportClicked() 
         } 
         Button { 
          text: "ImportSql " 
          onClicked: buttons.importClicked() 
         } 
        } 
       } 
      } 
     } 
    } 
} 
+2

Code beaucoup trop! Pouvez-vous s'il vous plaît poser une question plus spécifique: qu'avez-vous essayé et avec quoi êtes-vous réellement coincé? – LordWilmore

+0

Vous devrez exposer les données à votre interface utilisateur (Widgets ou QML) en utilisant un modèle. Voir [cette question sur les modèles et QML] (http://stackoverflow.com/q/18616497/1329652), et [cette question connexe] (http://stackoverflow.com/q/19324641/1329652), et [ceci un] (http://stackoverflow.com/a/19302329/1329652). –

+0

À tout le moins, s'il vous plaît remplacer les tonnes d'inclus avec les inclusions de seulement les modules que vous utilisez, sans leurs dépendances. Dans la plupart des cas, vous n'avez besoin que de "#include " et "#include ".Vos inclusions sont pleines de redondances, cela gonfle le code sans raison. –

Répondre

1

En C++, vous pouvez définir les propriétés que vous pouvez utiliser de QML

class MyQuickView : public QQuickView { 
    MyQuickView(){ 
    rootContext()->setContextProperty('mySelf',  this); 
    rootContext()->setContextProperty('myProperty', 5); 
    setSource(QUrl.fromLocalFile(myQmlFile.qml)); 
    mySignal.connect 
    } 

    public slots: 
    void mySlot(int i); 
}; 

En QML, vous pouvez appeler la fente et lecture de la propriété

Item { 
    Button { 
    onClicked: mySelf.mySlot(mySelf.myProperty); 
    } 
} 

Ici vous pouvez trouver comment connecter un C++ signaler à un emplacement QML:

https://stackoverflow.com/a/8840945/264359