2016-07-08 6 views
0

Я довольно новичок в Qt. Я начал около двух месяцев назад с приложений QWidgets, и все шло гладко. Теперь у меня настоящая проблема. Мне нужно интегрировать мою логику C++ в мой Qml Ui. Я отправлю свой исходный код из приложения QWidget adreesbook и моего пользовательского интерфейса, написанного в Qml. Мне нужно сделать, чтобы мое приложение работало с интегрированным UI Qml. Он отлично работает с QWidgets, но я не знаю, как его интегрировать в Qml. Я искал сеть в течение 2 дней, но я, похоже, не понимаю понятия. Учитывая тот факт, что я полный noob в отношении Qml, вам будет очень благодарен любой совет.Qt. Интеграция C++ и Qml

Вот моя версия C++/QWidgets:

Заголовки: 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 

CPP файлы: 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(); 
} 

А теперь я буду размещать свою версию QtQuick.

Заголовки: 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 

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"; 
} 

И мой 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

слишком много кода! Не могли бы вы задать более конкретный вопрос: что вы пробовали и с чем вы фактически застряли? – LordWilmore

+0

Вы хотите выставить данные в свой пользовательский интерфейс (будь то Widgets или QML на основе) с использованием модели. См. [Этот вопрос о моделях и QML] (http://stackoverflow.com/q/18616497/1329652) и [этот связанный вопрос] (http://stackoverflow.com/q/19324641/1329652) и [это один] (http://stackoverflow.com/a/19302329/1329652). –

+0

По крайней мере, замените тонны включений, включая только модули, которые вы используете, без их зависимостей. В большинстве случаев вам нужно только '#include ' и '#include '.Ваши включения полны избыточностей, это увеличивает код без причины. –

ответ

1

В C++ вы можете определить свойства, которые можно использовать с 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); 
}; 

В QML вы можете вызвать слот и прочитать свойство

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

Здесь вы можете найти, как подключить C++ сигнал к слоту QML:

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

Смежные вопросы