【Qt入門】QFont::family()でフォント名を操る!基本からトラブルシューティングまで
QtプログラミングにおけるQFont::family()
は、QFont
オブジェクトがどのフォントファミリー名を使用するように設定されているかを返します。
Qtでは、テキストを描画するためにQFont
クラスを使ってフォントを指定します。QFont
オブジェクトを作成する際に、フォントの「ファミリー」(例えば "Arial"、"Times New Roman"、"游ゴシック" など)を指定することができます。
QFont::family()
はこの設定されたフォントファミリー名をQString
として返します。
ここでは、QFont::family()
に関連する一般的なエラーとトラブルシューティングについて説明します。
「指定したフォントが適用されない」「別のフォントで表示される」
これが最も一般的な問題であり、QFont::family()
の挙動と関連しています。
問題点
QFont::family()
は正しく設定した名前を返しているが、見た目が違う。QFont
オブジェクトに特定のフォントファミリー(例: "MyCustomFont")を設定したが、実際に表示されるテキストが意図したフォントではない。
原因
- Webフォント/カスタムフォントのロード失敗
アプリケーションにバンドルされたカスタムフォントをQFontDatabase::addApplicationFont()
などでロードしようとしているが、パスが間違っている、またはロードが成功していない。 - フォントキャッシュの問題
オペレーティングシステムやQtのフォントキャッシュが古くなっている、または破損している場合があります。 - フォントファイルの破損
インストールされているフォントファイル自体が破損している場合、Qtがそれを読み込めないことがあります。 - フォント名が正しくない
スペルミス、大文字小文字の区別(システムによる)、または正式なフォントファミリー名と異なる名前を使用している可能性があります。例えば、"Arial"と"arial"では異なる場合があります。 - フォントがシステムにインストールされていない
これが一番よくある原因です。指定したフォントファミリー名のフォントが、プログラムを実行しているシステムにインストールされていない場合、Qtは代替のフォントを自動的に選択します。
トラブルシューティング
- フォントがインストールされているか確認する
- 該当のシステム(開発環境と配布環境の両方)に、指定したフォントが正しくインストールされているか確認します。
- Windows: コントロールパネルの「フォント」
- macOS: 「Font Book.app」
- Linux: フォント管理ツールや
/usr/share/fonts
、~/.fonts
ディレクトリを確認。
- フォントの正式名称を確認する
- フォント管理ツールでフォントの「完全なフォント名」や「ファミリー名」を確認し、Qtコードで設定している文字列と完全に一致しているかチェックします。
QFontDatabase::families()
を使って、Qtが認識している全てのフォントファミリー名の一覧を取得し、その中に目的のフォントがあるか確認すると良いでしょう。
#include <QFontDatabase> #include <QDebug> // ... QStringList availableFamilies = QFontDatabase::families(); qDebug() << "利用可能なフォントファミリー:"; for (const QString &family : availableFamilies) { qDebug() << " " << family; }
- QFontInfoを使用して実際に使用されているフォントを確認する
QFont::family()
はあくまで「要求された」フォントファミリー名ですが、QFontInfo
を使うと「実際に使用された」フォントファミリー名を確認できます。
QFont requestedFont("MyCustomFont", 12); qDebug() << "要求されたフォントファミリー:" << requestedFont.family(); QLabel label("Hello", nullptr); label.setFont(requestedFont); QFontInfo actualFontInfo(label.font()); qDebug() << "実際に適用されたフォントファミリー:" << actualFontInfo.family();
actualFontInfo.family()
がrequestedFont.family()
と異なる場合、フォントが見つからなかったことを意味します。
- 代替フォントの指定を試す
- 意図したフォントが見つからない場合に備えて、一般的なフォント("Arial", "Helvetica", "Sans-serif"など)を代替として指定することを検討します。
QFont
コンストラクタで複数のフォントファミリーをカンマ区切りで指定できます(優先順位順)。
QFont font("MyCustomFont, Arial, Sans-serif", 12);
- キャッシュのクリア/再構築
- 特にLinuxなどでは、フォントキャッシュを再構築することで問題が解決することがあります。
- 例:
fc-cache -fv
(fontconfigを使用している場合)
- カスタムフォントのロードを確認する
QFontDatabase::addApplicationFont()
が成功したか、返り値のIDが有効か確認します。- アプリケーションがフォントファイルにアクセスできるパスにあるか確認します。リソースファイル (
.qrc
) に含めるのが一般的です。
「QApplication::setFont()が一部のウィジェットに適用されない」
問題点
QApplication::setFont()
でアプリケーション全体のフォントを設定したが、特定のウィジェット(特にカスタムウィジェットや複雑なコンポーネント内)に適用されない。
原因
- ウィジェットの作成タイミング
QApplication::setFont()
を呼び出す前にウィジェットが作成されている場合、そのウィジェットには初期フォントが適用されてしまっている可能性があります。 - 明示的なフォント設定のオーバーライド
- そのウィジェットやその親ウィジェットで、
setFont()
が明示的に呼び出され、アプリケーション全体のフォント設定を上書きしている。 - Qtスタイルシート (
setStyleSheet()
) でフォントが指定されている場合、これが優先されます。
- そのウィジェットやその親ウィジェットで、
トラブルシューティング
- ウィジェットのsetFont()呼び出しを確認
- 該当ウィジェットのコードや、親ウィジェットのコードで、
setFont()
が別途呼び出されていないか確認します。
- 該当ウィジェットのコードや、親ウィジェットのコードで、
- スタイルシートの確認
- ウィジェットやその親ウィジェット、またはアプリケーション全体に適用されているスタイルシートで、フォントが指定されていないか確認します。スタイルシートは非常に強力で、フォント設定を簡単に上書きします。
/* 例: QLabelのフォントを上書き */ QLabel { font-family: "Times New Roman"; font-size: 14pt; }
- QApplication::setFont()の呼び出しタイミング
QApplication::setFont()
は、すべてのウィジェットが作成される前に呼び出すのが最適です。通常、main()
関数内でQApplication
オブジェクトを生成した後、最初に呼び出します。- もし後からフォントを変更したい場合は、各ウィジェットに対して
setFont()
を呼び出すか、スタイルシートを再適用する必要があります。
問題点
- アプリケーション起動時やフォント設定時に、コンソールに以下のような警告が表示される。
qt.qpa.fonts: Populating font family aliases took XXX ms. Replace uses of missing font family "MissingFontName" with one that exists to avoid this cost.
原因
- フォントエイリアスの解決に時間
Qtはフォントのエイリアス(別名)を解決するために時間を費やすことがあり、これがアプリケーションの起動時にパフォーマンスのボトルネックになることがあります。 - 存在しないフォントファミリーの指定
Qtが設定されたフォントファミリー(例: "MissingFontName")をシステムで見つけるのに時間がかかっている、または見つけられなかったことを示します。特にmacOSで「.AppleSystemUIFont」や「Sans」のようなシステム内部名が原因となることがあります。
- 警告で示されているフォント名を確認
- 警告メッセージに具体的なフォント名が記載されている場合は、そのフォントがシステムに存在しないか、名前が誤っている可能性が高いです。上記の「指定したフォントが適用されない」のトラブルシューティングを試します。
- 一般的なフォントファミリーを使用する
- 汎用的なフォントファミリー名("Sans-serif", "Serif", "Monospace")を使用することで、Qtがシステム上で利用可能な代替フォントをより効率的に選択できるようになります。
- 環境変数の設定 (Qt 5.15以降)
- Qt 5.15以降では、
QT_LOGGING_RULES
環境変数を設定することで、特定のロギングメッセージを抑制できます。 - 例:
QT_LOGGING_RULES="qt.qpa.fonts=false"
- ただし、これは問題の根本的な解決ではなく、単に警告を非表示にするだけであることに注意してください。根本的な原因(存在しないフォントの指定)を解決することが望ましいです。
- Qt 5.15以降では、
QFont::family()
は、設定されたフォントファミリー名を取得するメソッドですので、その使い方を中心に、関連する他のフォント操作と合わせて説明します。
例1: 基本的なフォントファミリー名の取得
これは最も基本的な使用例です。QFont
オブジェクトに設定したフォントファミリー名を取得します。
#include <QApplication>
#include <QFont>
#include <QLabel>
#include <QDebug> // デバッグ出力用
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1. QFontオブジェクトを作成し、フォントファミリーを設定
// ここでは"Arial"というフォントファミリーを設定します。
QFont myFont("Arial", 12); // ファミリー名 "Arial", サイズ 12pt
// 2. QFont::family() を使って、設定されたフォントファミリー名を取得
QString fontFamilyName = myFont.family();
// 3. 取得したファミリー名を出力
qDebug() << "設定されたフォントファミリー名:" << fontFamilyName;
// 4. そのフォントをQLabelに適用して表示
QLabel label("Hello, QFont::family()!", nullptr);
label.setFont(myFont);
label.resize(300, 50); // ウィンドウサイズを調整
label.show();
return app.exec();
}
出力例 (コンソール)
設定されたフォントファミリー名: "Arial"
(画面にはArialフォントで "Hello, QFont::family()!" と表示されます。)
例2: 実際に適用されたフォントファミリー名の確認 (QFontInfo の利用)
QFont::family()
が返すのは「設定された」フォントファミリー名です。しかし、システムにそのフォントがインストールされていない場合、Qtは別のフォントを代替として使用します。QFontInfo
を使うと、「実際に使用された」フォントファミリー名を確認できます。
#include <QApplication>
#include <QFont>
#include <QFontInfo> // QFontInfo を使用するため
#include <QLabel>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1. 存在しない可能性のあるフォント名を設定してみる (例: "NonExistentFont123")
QFont myFont("NonExistentFont123", 14);
qDebug() << "要求されたフォントファミリー:" << myFont.family();
// 2. QLabelを作成し、このフォントを適用
QLabel label("このフォントは表示されるかな?", nullptr);
label.setFont(myFont);
label.resize(400, 50);
label.show();
// 3. QLabelに実際に適用されたフォントの QFontInfo を作成
// label.font() で、そのウィジェットに現在適用されている QFont オブジェクトが取得できます。
QFontInfo actualFontInfo(label.font());
// 4. QFontInfo から実際に使用されたフォントファミリー名を取得
QString actualFamilyName = actualFontInfo.family();
qDebug() << "実際に適用されたフォントファミリー:" << actualFamilyName;
// 5. 要求と実際のフォントファミリーが異なるか確認
if (myFont.family() != actualFamilyName) {
qDebug() << "注意: 要求されたフォント (" << myFont.family() << ") は見つからず、代わりに (" << actualFamilyName << ") が使用されました。";
} else {
qDebug() << "要求されたフォントが正常に適用されました。";
}
return app.exec();
}
出力例 (コンソール - "NonExistentFont123" が見つからなかった場合)
要求されたフォントファミリー: "NonExistentFont123"
実際に適用されたフォントファミリー: "Sans-serif" // またはシステムデフォルトの代替フォント
注意: 要求されたフォント ( "NonExistentFont123" ) は見つからず、代わりに ( "Sans-serif" ) が使用されました。
この例は、指定したフォントがシステムに存在しない場合のデバッグに非常に役立ちます。
例3: 利用可能なフォントファミリーの一覧表示
システムにインストールされている、Qtが認識しているすべてのフォントファミリー名を取得して表示する例です。これは、フォント名を正しく指定するための確認に役立ちます。
#include <QApplication>
#include <QFontDatabase> // フォント情報を取得するためのクラス
#include <QDebug>
#include <QStringList>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1. QFontDatabase を使用して、システムが認識しているすべてのフォントファミリー名を取得
QStringList availableFamilies = QFontDatabase::families();
qDebug() << "システムで利用可能なフォントファミリー:";
// 2. 取得したリストをループして表示
for (const QString &family : availableFamilies) {
qDebug() << " - " << family;
}
// (GUI表示はここでは特にありませんが、実行されるコードは必要)
QLabel dummyLabel;
dummyLabel.setText("Check console for font list.");
dummyLabel.show();
return app.exec();
}
出力例 (コンソール - システムによって内容は異なります)
システムで利用可能なフォントファミリー:
- "Arial"
- "Times New Roman"
- "游ゴシック"
- "Meiryo UI"
- "Segoe UI"
- - (その他多数のフォントファミリー名)
このリストから、目的のフォントが正確な名前で存在するかを確認できます。
QFont
コンストラクタは、複数のフォントファミリーをカンマ区切りで指定できます。この場合、Qtはリストの最初のフォントから順に探し、見つかったものを採用します。QFont::family()
は、指定した文字列全体を返します。
#include <QApplication>
#include <QFont>
#include <QLabel>
#include <QDebug>
#include <QFontInfo> // 実際に使用されたフォントを確認するため
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1. 複数のフォントファミリーをカンマ区切りで指定
// "MyNonExistentFont" が見つからなければ "Arial"、それもなければ "Sans-serif"
QFont myFont("MyNonExistentFont, Arial, Sans-serif", 16);
// 2. QFont::family() は、設定された文字列全体を返す
qDebug() << "設定されたフォントファミリーの優先順位リスト:" << myFont.family();
// 3. QLabelに適用して表示
QLabel label("フォント優先順位テスト", nullptr);
label.setFont(myFont);
label.resize(300, 50);
label.show();
// 4. 実際に適用されたフォントファミリーを確認
QFontInfo actualFontInfo(label.font());
qDebug() << "実際に適用されたフォントファミリー:" << actualFontInfo.family();
return app.exec();
}
出力例 (コンソール - "MyNonExistentFont" が見つからず、"Arial" が見つかった場合)
設定されたフォントファミリーの優先順位リスト: "MyNonExistentFont, Arial, Sans-serif"
実際に適用されたフォントファミリー: "Arial"
この例からわかるように、QFont::family()
はあなたが指定した文字列そのものを返します。実際にどれが適用されたかは、QFontInfo
で確認する必要があります。
QFont::setFamilies() と QFont::families() (複数ファミリーの指定と取得)
QFont::family()
は単一のフォントファミリー名を返しますが、QFont
は複数のフォントファミリーを優先順位付きで指定する機能も提供しています。
代替方法:
QFont::families() const
: 設定されたフォントファミリーのリスト(優先順位付き)をQStringList
として返します。QFont::family()
はこのリストの最初の要素を返します。QFont::setFamilies(const QStringList &families)
: フォントを適用する際に、複数のフォントファミリー名をQStringList
で設定します。Qt はこのリストの最初のフォントから順に探し、利用可能なものを使用します。
QFont::family() との違い
QFont::family()
はリストの最初の要素しか返さないため、複数指定されている場合に、設定されたすべての優先順位を確認するには QFont::families()
を使う必要があります。
使用例
#include <QApplication>
#include <QFont>
#include <QLabel>
#include <QDebug>
#include <QStringList>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1. 複数のフォントファミリーをQStringListで指定
QStringList preferredFonts;
preferredFonts << "MySuperCustomFont" // 優先度1 (存在しない可能性あり)
<< "Arial" // 優先度2
<< "Sans-serif"; // 優先度3 (汎用フォント)
QFont myFont;
myFont.setFamilies(preferredFonts);
myFont.setPointSize(16);
// 2. setFamilies() で設定した全てのファミリー名を取得
QStringList configuredFamilies = myFont.families();
qDebug() << "設定されたフォントファミリーリスト:";
for (const QString& family : configuredFamilies) {
qDebug() << " - " << family;
}
// QFont::family() はリストの最初の要素を返す
qDebug() << "QFont::family() の結果:" << myFont.family();
QLabel label("複数のフォント指定のテスト", nullptr);
label.setFont(myFont);
label.resize(400, 50);
label.show();
// 実際に適用されたフォントファミリーを確認 (QFontInfo を使用)
QFontInfo actualFontInfo(label.font());
qDebug() << "実際に適用されたフォントファミリー:" << actualFontInfo.family();
return app.exec();
}
QFont::setStyleHint() と QFont::StyleHint (一般的なフォントタイプによる指定)
特定のフォントファミリー名を直接指定する代わりに、一般的なフォントの「スタイルヒント」を与えることで、Qtに最適なフォントを選択させることができます。これは、特定のフォントがシステムに存在しない場合や、より汎用的なフォント選択を行いたい場合に有効です。
代替方法:
QFont::styleHint() const
: 設定されているスタイルヒントを取得します。
QFont::family() との違い
QFont::family()
は具体的なフォント名を返しますが、setStyleHint()
はフォントの「種類」を指示するものです。Qtはヒントに基づいて適切なフォントファミリーを内部的に選択します。
使用例
#include <QApplication>
#include <QFont>
#include <QLabel>
#include <QDebug>
#include <QFontInfo>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1. スタイルヒントを設定
QFont sansSerifFont;
sansSerifFont.setStyleHint(QFont::SansSerif); // ゴシック体を優先
sansSerifFont.setPointSize(18);
qDebug() << "Sans-serif スタイルヒントのフォントファミリー設定:" << sansSerifFont.family(); // "Sans-serif" とは限らない
// 2. そのフォントをQLabelに適用
QLabel labelSansSerif("これはゴシック体?", nullptr);
labelSansSerif.setFont(sansSerifFont);
labelSansSerif.resize(300, 50);
labelSansSerif.show();
// 3. 実際に適用されたフォントを確認
QFontInfo actualSansSerifInfo(labelSansSerif.font());
qDebug() << "実際に適用されたSans-serif系フォント:" << actualSansSerifInfo.family();
// 別のヒントの例
QFont serifFont;
serifFont.setStyleHint(QFont::Serif); // 明朝体を優先
serifFont.setPointSize(18);
qDebug() << "Serif スタイルヒントのフォントファミリー設定:" << serifFont.family();
QLabel labelSerif("これは明朝体?", nullptr);
labelSerif.setFont(serifFont);
labelSerif.resize(300, 50);
labelSerif.move(0, 60); // 位置をずらす
labelSerif.show();
QFontInfo actualSerifInfo(labelSerif.font());
qDebug() << "実際に適用されたSerif系フォント:" << actualSerifInfo.family();
return app.exec();
}
出力例 (システムによる)
Sans-serif スタイルヒントのフォントファミリー設定: "Sans-serif" // QFont::family()は設定されたヒント名(抽象名)を返すことが多い
実際に適用されたSans-serif系フォント: "Segoe UI" // Windowsの場合
Serif スタイルヒントのフォントファミリー設定: "Serif"
実際に適用されたSerif系フォント: "Times New Roman" // Windowsの場合
QFontDatabase (利用可能なフォント情報の問い合わせとアプリケーション内でのフォント埋め込み)
QFontDatabase
クラスは、システムにインストールされているフォントに関する詳細な情報を提供したり、アプリケーションにカスタムフォントを埋め込んだりするために使用されます。
代替方法/関連する機能:
QFontDatabase::addApplicationFont(const QString &fileName)
/addApplicationFontFromData(const QByteArray &fontData)
: アプリケーション内にフォントファイルを埋め込み、そのフォントをアプリケーション内で利用可能にします。これにより、ユーザーのシステムにフォントがインストールされていなくても、アプリケーションが特定のフォントを使用できます。QFontDatabase::styles(const QString &family)
: 特定のフォントファミリーで利用可能なスタイル名(例: "Regular", "Bold")のリストを取得します。QFontDatabase::font(const QString &family, const QString &style, int pointSize)
: 指定したファミリー、スタイル(例: "Regular", "Bold", "Italic")、ポイントサイズに最も合うQFont
オブジェクトを直接作成して返します。
QFont::family() との違い
QFontDatabase
は、システム全体のフォント環境を「問い合わせる」ためのツールです。QFont::family()
は個々の QFont
オブジェクトが「設定されている」フォント名を取得するもので、役割が異なります。QFontDatabase
を使って利用可能なフォントを調べ、その結果を QFont::family()
に設定する、という連携が考えられます。
使用例 (カスタムフォントの埋め込み)
-
Qt リソースファイル (.qrc) の作成
fonts.qrc
のようなファイルを作成し、プロジェクトにフォントファイル(例:MyCustomFont.ttf
)を追加します。<!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/fonts"> <file>MyCustomFont.ttf</file> </qresource> </RCC>
(プロジェクトファイル
.pro
にRESOURCES += fonts.qrc
を追加することを忘れずに) -
C++ コードでのフォントのロードと使用
#include <QApplication> #include <QFont> #include <QLabel> #include <QFontDatabase> // QFontDatabase を使用するため #include <QDebug> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 1. リソースからカスタムフォントをロード // addApplicationFont は、ロードされたフォントのIDを返します。 // ファイルパスは、リソースファイル内のパスと同じです。 int fontId = QFontDatabase::addApplicationFont(":/fonts/MyCustomFont.ttf"); // 必要に応じてパスを調整 QString fontFamilyName; if (fontId != -1) { // ロードされたフォントのファミリー名を取得 QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId); if (!fontFamilies.isEmpty()) { fontFamilyName = fontFamilies.at(0); // 最初のファミリー名を取得 qDebug() << "カスタムフォントのファミリー名:" << fontFamilyName; } else { qDebug() << "カスタムフォントのファミリー名が見つかりません。"; } } else { qDebug() << "カスタムフォントのロードに失敗しました!"; } // 2. ロードしたカスタムフォントを使用 QFont customFont(fontFamilyName, 24); // ロードしたファミリー名でQFontを作成 QLabel label("埋め込みフォントのテスト", nullptr); label.setFont(customFont); label.resize(500, 100); label.show(); // 3. 実際に適用されたフォントファミリーを確認 QFontInfo actualFontInfo(label.font()); qDebug() << "実際に適用されたフォントファミリー (カスタムフォント):" << actualFontInfo.family(); return app.exec(); }
注意
MyCustomFont.ttf
は実際に存在するフォントファイルに置き換えてください。
Qt スタイルシート (QSS) を使用して、ウィジェットのフォントを宣言的に指定することもできます。これは、CSS の font-family
プロパティに似ています。
代替方法:
QWidget::setStyleSheet(const QString &styleSheet)
: ウィジェットまたはアプリケーション全体にスタイルシートを適用します。
QFont::family() との違い
スタイルシートはテキストベースでフォントを指定します。QFont::family()
は C++ コード内で QFont
オブジェクトから設定を取得するためのものです。スタイルシートで設定されたフォント情報を C++ コードで取得したい場合は、そのウィジェットの font()
メソッドで QFont
を取得し、それに対して family()
や QFontInfo
を使用することになります。
使用例
#include <QApplication>
#include <QLabel>
#include <QDebug>
#include <QFontInfo>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel label("スタイルシートでフォントを設定", nullptr);
label.resize(400, 50);
// 1. スタイルシートでフォントファミリーとサイズを指定
// ここでは "Comic Sans MS" と "Arial" を試します。
label.setStyleSheet("QLabel { font-family: 'Comic Sans MS', Arial; font-size: 20pt; color: blue; }");
label.show();
// 2. スタイルシートで設定されたフォント情報をコードから取得
// 注意: スタイルシートで適用されたQFontのfamily()は、
// スタイルシートに記述した文字列そのままを返すことが多いです。
// 実際に適用されたフォントはQFontInfoで確認します。
QFont labelFont = label.font();
qDebug() << "QLabelのQFont::family() (スタイルシートから):" << labelFont.family();
QFontInfo actualFontInfo(labelFont);
qDebug() << "実際に適用されたフォントファミリー (スタイルシートから):" << actualFontInfo.family();
return app.exec();
}
出力例 (Windowsで "Comic Sans MS" がインストールされている場合)
QLabelのQFont::family() (スタイルシートから): "Comic Sans MS, Arial"
実際に適用されたフォントファミリー (スタイルシートから): "Comic Sans MS"