2012/06/17

[QML/Qt] Lecture 03. QML에서 Qt Class의 Method를 호출하자.

Lecture 02.에서 만든 환경을 그대로 이용해서, QML에서 Qt Class의 메소드를 호출하는 방법을 알아봅니다.

Q_PROPERTY로 등록한 프로퍼티는 변수처럼, 읽고, 쓸 수 있는 기능을 하는 것으로 생각을 하면, 클래스의 특정 함수를 QML에서 호출하는 것은 Q_INVOKABLE을 이용할 수 있습니다.


class MyObject : public QObject
{
  Q_OBJECT
public:
  explicit MyObject(QString n, QObject *parent = 0);
  Q_PROPERTY (QString myName READ getName WRITE setName NOTIFY nameChanged)
  QString getName(void) { return name; }
  void    setName(QString n) { name = n; nameChanged();}
  Q_INVOKABLE QString getMyNameByMethod(QString param, int value)
  {
      qDebug() << __FUNCTION__ << " param:" << param << ", value:" << value;
      return name;
  }
 
signals:
  void nameChanged();
 
public slots:
private:
  QString name;
 
};


위에 녹색으로 표시한 것이 일반 Public 함수를 QML에서 보이도록 Q_INVOKABLE로 만든 함수입니다.

이 함수는 Qt의 다른 클래스에서도 Public 함수로 호출을 할 수 있으며, 이 클래스가 QDeclarativeView의 rootContext에 Property로 등록이 되면, 이 함수를 QML에서 호출 할 수 있습니다.
즉, Qt/QML의 Meta system에서 Q_INVOKABLE로 선언된 함수를 등록을 해 두므로, QML에서 호출 할 수 있게 되는 것입니다.
QML에서는 어떻게 호출은 하는가.
아래에 Main함수에서 MyObject를 Property인 “myObject”로 등록을 했습니다.

  DeclarativeView view;
  MyObject myObject("David Bae");
  view.rootContext()->setContextProperty("myObject", &myObject);
  view.setSource(QUrl("../QLecture/qml/QLecture/main.qml"));
  view.show();


그리고 QML에서 myObject의 getMyNameByMethod함수를 호출할 수 있게 됩니다.

   onClicked: {
       var name = myObject.getMyNameByMethod("nameFromQML", 50);
       console.log("[QML] getMyName:"+ name)
       idButtonText.text = name;
   }


위와 같이 호출을 할 수 있게 되고, 파라미터를 넘기거나, 리턴값을 받아 올 수 있습니다.

[QML/Qt] Lecture 02. Property를 등록하자.

Lecture 01에서 만든 환경에서, Class인 MyObject를 만들고, 거기에 Property 인 name을 등록을 하자. 그리고, 내용을 MyObject에서 이름을 가져와서, QML에서 표시를 해 보자.

1. QObject에서 상속받은 MyObject 클래스를 만들자.
 Menu > File > New File or Project 를 선택하고, C++인 Class를 선택하자.
 이름은 MyObject로 하고, QObject에서 상속을 받도록 만들자.
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
class MyObject : public QObject
{
  Q_OBJECT
public:
  explicit MyObject(QObject *parent = 0);

signals:
public slots:

};
#endif // MYOBJECT_H

: 기본적으로 클래스를 만들면 위와 같이 기본 클래스가 만들어진다.

2. 만든 MyObject에 name을 추가하고,  Q_PROPERTY로 등록하자.
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
class MyObject : public QObject
{
  Q_OBJECT
public:
  explicit MyObject(QString n, QObject *parent = 0);
  Q_PROPERTY (QString myName READ getName WRITE setName NOTIFY nameChanged)
  QString getName(void) { return name; }
  void    setName(QString n) { name = n; nameChanged();}
 
signals:
  void nameChanged();
 
public slots:
private:
  QString name;
 
};
#endif // MYOBJECT_H

: 위에 녹색으로 배경이 된 부분이 추가된 부분이 된다.
QML에서 myName이라는 프로퍼티이름으로 name을 읽을 수 있는데,
text: myObject.myName 이라고 쓰면, getName()이 호출되어서, 값을 넘겨주게 되고,
myObjectt.myName = “david” 라고 하면, setName(..)이 호출되어 값을 설정하게 된다.
설정될 때, nameChange() 시그널을 발생시켜서, QML에서 바인딩 된 다른 곳에서도 데이터가 변경이 된다. 이건 Property Binding과 Signa/Slot을 설명하고 나면 자세하게 알게 된다.
여기서는 nameChange라는 함수를 통해서, QML에서 자동으로 값을 읽어가게 된다는 것을 알고 가자.

3. Main에서 MyObject의 인스턴스를 만들고, view의 rootContext에서 이것을 등록하자.
#include <QApplication>
#include <QDeclarativeContext>
#include <QDeclarativeView>
#include "myobject.h"
Q_DECL_EXPORT int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  QDeclarativeView view;
  MyObject myObject("David Bae");
  view.rootContext()->setContextProperty("myObject", myObject);
  view.setSource(QUrl("../QLecture/qml/QLecture/main.qml"));
  view.show();
  return app.exec();
}

main함수에서 “myObject”로 view의 rootContext에 등록을 했으므로, QML에서 “myObject”라는 이름을 사용하면, 다른 QML콤포넌트의 id에 접근하듯이 등록된 클래스에 접근을 할 수 있게 된다.
view의 setSource를 통해서 QML파일을 등록하기 전에, rootContext에 “myObject”라는 이름으로 myObject를 등록을 하면, setSource에서 등록되는 QML에서는 myObject라는 이름으로 사용할 수 있게 된다.


4. QML에서 등록된 MyObject를 읽어와서, 내부의 Name을 읽어서 화면에 표시를 하자.
QML에서 myName을 읽으면, MyObject의 getName이 호출되고, myName에 이름을 넣으면, setName이 되는 것이다.

main.qml
Rectangle {
  width: 360
  height: 360
  Text {
      text: qsTr("Hello World2")
      anchors.centerIn: parent
  }
  Text {
      x:50; y:50
      text:myObject.myName;
  }
}


그럼, Main.qml에서 사용자가 마우스 클릭으로 이름을 바꾸고, 바꾼 내용이 화면이 표시가 되는지 확인해 보자.

QML에 버튼 비슷한 것을 만들고, click이 되면, 이름을 “Jamie”로 바꿔보자.
// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
  width: 360
  height: 360
  Text {
      text: qsTr("Hello World2")
      anchors.centerIn: parent
  }
  Text {
      x:50; y:50
      text:myObject.myName;
      color:"green"
  }
  Rectangle{
      x:150;y:50
      width:100;
      height:15
      color:"steelBlue"
      Text{
          anchors.fill:parent;
          verticalAlignment: Text.AlignVCenter;
          horizontalAlignment: Text.AlignHCenter;
          text: "Change"
      }
      MouseArea{
          anchors.fill: parent;
          onClicked: {
              myObject.myName = "Jamie";
          }
      }
  }
}

실제 동작하는 화면을 보면, Change를 클릭하면, David Bae라는 이름이 Jamie로 바뀌고, 화면에 자동으로 갱신이 된다.


좀더 자세하게 Q_PROPERTY를 설정할 때 들어가는 내용을 알아봅시다.
(참조 사이트: http://doc.qt.nokia.com/4.7/qobject.html#Q_PROPERTY )
Q_PROPERTY(type name
           READ getFunction
           [WRITE setFunction]
           [RESET resetFunction]
           [NOTIFY notifySignal]
           [DESIGNABLE bool]
           [SCRIPTABLE bool]
           [STORED bool]
           [USER bool]
           [CONSTANT]
           [FINAL])

선언
- 일반적인 변수와 동일하게 동작함.
- 추가적으로 Meta-Object System을 통해서 접근이 가능한 Property가 됨.
- READ : reading the property value
- WRITE: setting the property value
- RESET: default value로 돌아올 때
- NOTIFY: 변경을 알리는 Signal을 명시
- DESIGNABLE: GUI design tool에서 보이도록
- SCRIPTABLE: script engine에서 접근 가능, 디폴트로 true임
STORED: property가 자기것으로 가지고 있거나, 혹은 다른 Property의 Value에 따라 변하는지를 표시한다. 일반적으로 True, minimumWidth()의 경우, minimumSize()의 값이 되므로 자기것을 가지고 있을 필요 없다는 것임.
- USER: 사용자가 보고, 변경할 수 있는 것인지를 표시하는 것. (??)
- CONSTANT: const이므로 READ함수가 같은 값을 return한다.
- FINAL: 상속받은 class에서 overridden을 하지 못한다는 의미.

[QML/Qt] Lecture 01. Qt QML 설명을 위한 테스트 Application을 만들자

먼저 Test를 위한 프로그램을 만듭니다.

1. QtCreator에서 File > New File or Project 를 선택합니다.

2. Qt Quick Application을 선택해서,  Name을 만들고, Built-In elements only로 만듭니다.

3. Target은 Desktop을 선택해서, 윈도우에서 테스트를 합니다.

4. QmlApplicationViewer는 삭제해 버립니다.

5. Main에서 QApplication과 View를 만들고, QML 파일을 setSource해서 화면에 보여주도록 합니다.

main.cpp

#include <QApplication>
#include <QDeclarativeContext>
#include <QDeclarativeView>
Q_DECL_EXPORT int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  QDeclarativeView view;
  view.setSource(QUrl("../QLecture/qml/QLecture/main.qml"));
  view.show();
  return app.exec();
}


main.qml
import QtQuick 1.1
Rectangle {
  width: 360
  height: 360
  Text {
      text: qsTr("Hello World")
      anchors.centerIn: parent
  }
}


QLecture.pro
QT += declarative core gui opengl

SOURCES += main.cpp

OTHER_FILES += \
  qml/QLecture/main.qml

2012/06/07

[QML/Qt] Windows에서 Qt Creator용 Debugging 설정하기.


먼저 Qt Creater를 설치하고 디버깅을 해보면, CDB와 GDB가 설정이 되어 있지 않는다고 한다.
이건 Visual Studio를 설치하는 것과 별개로 윈도우에 Win SDK가 있느냐 없느냐 의 차이이다.
그러므로 Visual Studio를 설치하더라도, 다시 Win SDK를 설치해야 되는 것이다.

이 설명은 Qt Creator 웹사이트에 나와 있다.

그리고 거기에 Installing Native Debuggers 부분에 보면, Debugging tools for Windows에 링크가 있다.
하지만 링크에 접속해 보면 웹사이트가 바뀌었다고 한다.
    The contents of this page have been removed or relocated. You should be automatically redirected to the New Destination in 5 seconds.
새로운 위치로 가고,
거기에서























위 항목에 들어가면 Microsoft Windows SDK for Windows 7 and .Net Frame4를 얻을 수 있다.
이것을 받아서 설치하고, Rebooting 한 후, Qt Creator에서 해당 Project를 디버깅 실행하면, 심볼위치를 설정하라고 하고, 적당한 곳을  설정하면, 디버깅이 가능하게 된다.

단, 프로젝트의 실행 환경을 Release가 아닌 Debug로 설정을 하고, F5으로 디버거를 실행시켜야 된다.