Skip to content

Instantly share code, notes, and snippets.

@yossi-tahara
Last active Sep 6, 2020
Embed
What would you like to do?
第6回 Qtの重要な仕組みSignalとSlot
#!/bin/bash
export PATH=~/Qt/5.15.0/gcc_64/bin:$PATH
cd ../linuxdeployqt
qmake
make
©2020 Theoride Technology (http://theolizer.com/) All Rights Reserved.
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
#include <QGuiApplication>
#include "MainWindow.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
try
{
QGuiApplication app(argc, argv);
MainWindow aMainWindow;
aMainWindow.show();
return app.exec();
}
catch (MyException& e)
{
qDebug() << "MyException :" << e.what();
}
return EXIT_FAILURE;
}
#include <QCoreApplication>
#include "MainWindow.h"
// ***************************************************************************
// コンストラクタ
// ***************************************************************************
MainWindow::MainWindow() :
WindowBase("qrc:/MainWindow.qml")
{
// 文字列型connect
connect(mQmlWindow, SIGNAL(startButtonSignal()),
this, SLOT(startButtonSlot()));
// 関数ポインタ型connect
connect(&mSubModule, &SubModule::signal0, this, &MainWindow::signal0Slot);
// 関数オブジェクト型connect
connect(&mSubModule, &SubModule::signal1,
[this]()
{
setLabelTimeout("signal1");
});
}
// ***************************************************************************
// デストラクタ
// ***************************************************************************
MainWindow::~MainWindow()
{
}
// ***************************************************************************
// startButtonの処理スロット
// ***************************************************************************
void MainWindow::startButtonSlot()
{
qDebug() << "startButtonSlot()";
mSubModule.startTimer();
setLabelTimeout("waitting");
}
// ***************************************************************************
// mSubModule.signal0()の処理スロット
// ***************************************************************************
void MainWindow::signal0Slot()
{
setLabelTimeout("signal0");
}
// ***************************************************************************
// LabelTimeout設定
// ***************************************************************************
void MainWindow::setLabelTimeout(QString const iText)
{
bool ret = QMetaObject::invokeMethod
(
mQmlWindow, "setLabelTimeout",
Qt::DirectConnection,
Q_ARG(QVariant, iText)
);
qDebug() << "setLabelTimeout():" << iText << ret;
}
#ifndef MAIN_WINDOW_H
#define MAIN_WINDOW_H
#include <QTimer>
#include "WindowBase.h"
#include "SubModule.h"
class MainWindow : public WindowBase
{
Q_OBJECT
Q_DISABLE_COPY(MainWindow)
public:
explicit MainWindow();
~MainWindow();
signals:
void dummySignal();
private slots:
void startButtonSlot();
void signal0Slot();
private:
SubModule mSubModule;
void setLabelTimeout(QString const iText);
};
#endif // MAIN_WINDOW_H
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ApplicationWindow
{
objectName: "root"
visible: false
width: 640
height: 480
title: qsTr("Signal/Slot Sample-01")
// C++ I/F
signal startButtonSignal();
function setLabelTimeout(iText)
{
console.log("setLabelTimeout():", labelTimeout.text, " -> ", iText)
labelTimeout.text=iText
}
// コンテンツ
ColumnLayout
{
Button
{
id: startButton
objectName: "startButton"
text: "Timer Start"
font
{
pixelSize: 20
bold: true
}
onClicked:
{
console.log("startButtonSignal()")
startButtonSignal()
}
}
Text
{
id: labelTimeout
objectName: "labelTimeout"
text: ""
font
{
pixelSize: 20
bold: true
}
}
}
}
/****************************************************************************
** Meta object code from reading C++ file 'SubModule.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include <memory>
#include "../../05.signal-slot-01/SubModule.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'SubModule.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.15.0. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
QT_BEGIN_MOC_NAMESPACE
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
struct qt_meta_stringdata_SubModule_t {
QByteArrayData data[3];
char stringdata0[19];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_SubModule_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_SubModule_t qt_meta_stringdata_SubModule = {
{
QT_MOC_LITERAL(0, 0, 9), // "SubModule"
QT_MOC_LITERAL(1, 10, 7), // "signal0"
QT_MOC_LITERAL(2, 18, 0) // ""
},
"SubModule\0signal0\0"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_SubModule[] = {
// content:
8, // revision
0, // classname
0, 0, // classinfo
1, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
1, // signalCount
// signals: name, argc, parameters, tag, flags
1, 0, 19, 2, 0x06 /* Public */,
// signals: parameters
QMetaType::Void,
0 // eod
};
void SubModule::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
auto *_t = static_cast<SubModule *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: _t->signal0(); break;
default: ;
}
} else if (_c == QMetaObject::IndexOfMethod) {
int *result = reinterpret_cast<int *>(_a[0]);
{
using _t = void (SubModule::*)();
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SubModule::signal0)) {
*result = 0;
return;
}
}
}
Q_UNUSED(_a);
}
QT_INIT_METAOBJECT const QMetaObject SubModule::staticMetaObject = { {
QMetaObject::SuperData::link<QObject::staticMetaObject>(),
qt_meta_stringdata_SubModule.data,
qt_meta_data_SubModule,
qt_static_metacall,
nullptr,
nullptr
} };
const QMetaObject *SubModule::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *SubModule::qt_metacast(const char *_clname)
{
if (!_clname) return nullptr;
if (!strcmp(_clname, qt_meta_stringdata_SubModule.stringdata0))
return static_cast<void*>(this);
return QObject::qt_metacast(_clname);
}
int SubModule::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 1)
qt_static_metacall(this, _c, _id, _a);
_id -= 1;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 1)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 1;
}
return _id;
}
// SIGNAL 0
void SubModule::signal0()
{
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
}
QT_WARNING_POP
QT_END_MOC_NAMESPACE
<RCC>
<qresource prefix="/">
<file>MainWindow.qml</file>
</qresource>
</RCC>
QT += quick
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
WindowBase.cpp \
MainWindow.cpp \
SubModule.cpp
HEADERS += \
WindowBase.h \
MainWindow.h \
SubModule.h
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# 抽出先フォルダ
CONFIG(debug,debug|release){
BUILD_TYPE=debug
}else{
BUILD_TYPE=release
}
DESTDIR = $$OUT_PWD/deploy/$$BUILD_TYPE
# ターゲット・バイナリのパス
win32 {
TARGET_NAME = $${TARGET}.exe
}
else: macx {
TARGET_NAME = $${TARGET}.app
}
else: linux {
TARGET_NAME = $${TARGET}
}
TARGET_PATH = $$DESTDIR/$${TARGET_NAME}
# リンク後処理の登録
win32 {
QMAKE_POST_LINK = $$dirname(QMAKE_QMAKE)/windeployqt $${TARGET_PATH} -qmldir=$$PWD --no-translations$$escape_expand(\n\t)
QMAKE_POST_LINK += cd$$escape_expand(\n\t)
}
else: macx {
QMAKE_POST_LINK = $$dirname(QMAKE_QMAKE)/macdeployqt $${TARGET_PATH} -qmldir=$$PWD$$escape_expand(\n\t)
QMAKE_POST_LINK += pwd$$escape_expand(\n\t)
}
else: linux {
QMAKE_POST_LINK = ~/Qt/linuxdeployqt-7-x86_64.AppImage $${TARGET_PATH} -qmldir=$$PWD$$escape_expand -unsupported-allow-new-glibc$$escape_expand(\n\t)
QMAKE_POST_LINK += pwd$$escape_expand(\n\t)
}
message("DESTDIR =$$DESTDIR")
message("TARGET =$$TARGET")
message("TARGET_PATH =$$TARGET_PATH")
message("QMAKE_POST_LINK=$$QMAKE_POST_LINK")
#include "SubModule.h"
// ***************************************************************************
// コンストラクタ
// ***************************************************************************
SubModule::SubModule()
{
// Timer0設定
mTimer0.setSingleShot(true); // 1回だけ計測
mTimer0.setInterval(1000); // 1秒タイマ
connect(&mTimer0, &QTimer::timeout,
[this]()
{
emit signal0();
});
// Timer1設定
mTimer1.setSingleShot(true);
mTimer1.setInterval(2000);
connect(&mTimer1, &QTimer::timeout,
[this]()
{
emit signal1();
});
}
// ***************************************************************************
// デストラクタ
// ***************************************************************************
SubModule::~SubModule()
{
}
// ***************************************************************************
// タイマ・スタート
// ***************************************************************************
void SubModule::startTimer()
{
mTimer0.start();
mTimer1.start();
}
#ifndef SUB_MODULE_H
#define SUB_MODULE_H
#include <QObject>
#include <QTimer>
class SubModule : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(SubModule)
public:
explicit SubModule();
~SubModule();
void startTimer();
signals:
void signal0();
void signal1();
private:
QTimer mTimer0;
QTimer mTimer1;
};
#endif // SUB_MODULE_H
#include <QCoreApplication>
#include <QDebug>
#include "WindowBase.h"
// ***************************************************************************
// コンストラクタ
// ***************************************************************************
WindowBase::WindowBase(QString const iQmlFile) :
QObject(nullptr),
mQmlWindow(nullptr)
{
// QMLのロード
const QUrl url(iQmlFile);
connect(&mQmlEngine, &QQmlApplicationEngine::objectCreated, this,
[url](QObject *obj, const QUrl &objUrl)
{
if (!obj && url == objUrl)
{
throw MyException("Failed to load qml : " + url.toString());
}
}, Qt::QueuedConnection);
mQmlEngine.load(url);
for (QObject const* obj : mQmlEngine.rootObjects())
{
enumeration(obj);
}
// Windowポインタ獲得
mQmlWindow = dynamic_cast<QQuickWindow*>(mQmlEngine.rootObjects().first());
if (!mQmlWindow)
{
throw MyException("Not found QQuickWindow : " + url.toString());
}
}
// ***************************************************************************
// デストラクタ
// ***************************************************************************
WindowBase::~WindowBase()
{
}
// ***************************************************************************
// デバッグ用
// ***************************************************************************
void WindowBase::enumeration(QObject const* iObject, int iLevel)
{
QMetaObject const* aMetaObject = iObject->metaObject();
qDebug() << QByteArray(iLevel*4, ' ').data() << aMetaObject->className() << " :" << iObject->objectName();
QObjectList const aObjList = iObject->children();
if (aObjList.size() == 0)
return;
for (QObject const* obj : aObjList)
{
enumeration(obj, iLevel+1);
}
}
#ifndef WINDOW_BASE_H
#define WINDOW_BASE_H
#include <QObject>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QException>
// ***************************************************************************
// QML用ウインドウ・ベース
// ***************************************************************************
//----------------------------------------------------------------------------
// エラー通知用
//----------------------------------------------------------------------------
class MyException : public QException
{
public:
MyException(QString const& iReason) : mReason(iReason.toUtf8()) { }
void raise() const override { throw *this; }
MyException *clone() const override { return new MyException(*this); }
char const* what() const noexcept override { return mReason.data(); }
private:
QByteArray mReason;
};
//----------------------------------------------------------------------------
// 本体
//----------------------------------------------------------------------------
class WindowBase : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(WindowBase)
public:
explicit WindowBase(QString const iQmlFile);
~WindowBase();
// 中継
void show() { mQmlWindow->show(); }
void hide() { mQmlWindow->hide(); }
protected:
QQuickWindow* mQmlWindow;
signals:
private slots:
private:
QQmlApplicationEngine mQmlEngine;
// デバッグ用
void enumeration(QObject const* iObject, int iLevel=0);
};
#endif // WINDOW_BASE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment