前書き
自分用の備忘録で、実装の小ネタ集です。
実装環境
OS: Windows 10(20H2)
Visual Studio: Professional 2019(Version 16.10.3)
Qt: 5.15.2
Qt Visual Studio Tools: 2.7.1.18
ダイアログ
アプリケーション終了時に確認ダイアログを表示させる
closeEventイベントをオーバーライドする。
void QtWidgetsApplication1::closeEvent(QCloseEvent* event)
{
int res = QMessageBox::question(this, tr("quit"), tr("application quit ok?"));
if (res == QMessageBox::No) {
event->ignore();
}
}
アプリケーションのバージョン表示
void QtWidgetsApplication1::on_action_About_triggered()
{
QMessageBox::about(this, tr("version information"), QString("%1 Version: %2").arg(QApplication::applicationName()).arg(QApplication::applicationVersion()));
}
QApplication::applicationVersion()では、リソースの「VS_VERSION_INFO」からバージョンが取得できる。
Qtについての情報表示
void QtWidgetsApplication1::on_action_AboutQt_triggered()
{
QMessageBox::aboutQt(this, tr("About Qt"));
}
コンボボックス
指定アイテムを選択不可にする
QStringList list = {"aaa", "bbb", "ccc" };
list.prepend(tr("Not set"));
ui.comboBox->addItems(list);
QStandardItemModel* model = qobject_cast<QStandardItemModel*>(ui.comboBox->model());
QModelIndex firstIndex = model->index(0, ui.comboBox->modelColumn(), ui.comboBox->rootModelIndex());
QStandardItem* firstItem = model->itemFromIndex(firstIndex);
firstItem->setEnabled(false); // "Not set"を選択不可にする
firstItem->setEnabled(false) の代わりにfirstItem->setSelectable(false) を使用した場合、マウスでは選択できないが、カーソルキーでは選択できてしまう。
スタイルシート
スタイルシートの設定を子ウィジェットに引き継がないようにする
親側のスタイルシート設定で、
#オブジェクト名 {
background-color:white;
}
「#~」でobjectNameを指定し、スタイルシートの適用範囲を限定する。
SQLite関連
日時の扱い
SQLiteでCURRENT_TIMESTAMPなどを使用した場合に取得される現在時刻はUTC。
こちらの記事を参考にさせていただきました。
データベースに格納された日時を取得する際、
QSqlDatabase db = QSqlDatabase::database(connectionName);
QSqlQuery query(db);
query.prepare("select id, date, time from hogehoge where user_id=:id");
query.bindValue(":id", user_id);
query.exec();
QDateTime datetime = QDateTime::fromString(query.value(1).toString() + QString(" ") + query.value(2).toString(), "yyyy-MM-dd HH:mm:ss");
qDebug() << datetime.toLocalTime().toString("yyyy/MM/dd hh:mm:ss");
この場合ローカルタイムではなく、UTCで表示されてしまう。
QDateTime datetime = QDateTime::fromString(query.value(1).toString() + QString(" ") + query.value(2).toString(), "yyyy-MM-dd HH:mm:ss");
datetime.setTimeSpec(Qt::UTC);
qDebug() << datetime.toLocalTime().toString("yyyy/MM/dd hh:mm:ss");
こうすると、ローカルタイムで表示される。
Json
Json形式のファイルを読み込む
QFile jsonFile("hogehoge.json");
if (jsonFile.open(QIODevice::ReadOnly)) {
QJsonObject data(QJsonDocument::fromJson(jsonFile.readAll()).object());
}
Jsonファイルを指定して読み込む。
指定したJsonファイルが、
{
"foo": 10,
"bar": "aaa"
}
というものであった場合、
data["foo"].toInt()
と指定することでint型の数値を取り出すことができる。
Json形式のファイルとして書き出す
QFile jsonFile("hogehoge.json");
if (jsonFile.open(QIODevice::WriteOnly)) {
QJsonDocument saveDoc(data);
jsonFile.write(saveDoc.toJson());
jsonFile.close();
}
デバッグログ
デバッグログをファイル出力する
qInstallMessageHandlerを使用する。
void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
OutputDebugStringW(QString(msg + "\n").toStdWString().c_str()); // VisualStudioの出力ウィンドウにも表示する
QFile file("log.txt");
if (!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
return;
}
QTextStream ts(&file);
ts.setCodec(QTextCodec::codecForName("UTF-8"));
ts << msg << endl;
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput);
QApplication app(argc, argv);
...
return app.exec();
}
共通言語ランタイムサポートについて
OleInitialize() failedへの対応
プロジェクトのプロパティで「共通言語ランタイムサポート(/clr)」を有効にした際、
プログラム実行時に、
QWindowsContext: OleInitialize() failed: "COM error 0xffffffff80010106 RPC_E_CHANGED_MODE (Unknown error 0x080010106)"
このようなエラーが発生してしまう(プログラムの実行自体はされる)。
main.cppのmain関数の直前に、
#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>
#using <system.dll>
[System::STAThread]
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtWidgetsApplication1 w;
w.show();
return a.exec();
}
**[System::STAThread]**行を追加することで回避できた。
これらの記事を参考にさせていただいた。