外字について



  • 皆様はじめまして。
    尾崎@名古屋です。
    Qt名古屋勉強会 #4でも質問させていただいた内容なのですが
    未だ解決できないためご協力をお願いいたします。

    問題点
    Qt上で外字が文字化けして表示できません。
    QtCreatorも例外ではないです。
    Windows環境で確認しています。

    再現方法
    1.外字を作ります。
    外字エディタを起動します。
    Xpなら
    [プログラム]-[アクセサリ]-[ユーザー補助]-外字エディタ
    Vista以降は
    [プログラム]-[アクセサリ]-[システムツール]-外字エディタ
    開いたらコード「F040」を選択(デフォルトだと思います)してOKクリック
    他の文字と区別が付くように適当にお絵かきをしていただいて
    編集メニューから同じコードで保存(Ctrl+s)

    2.正しく登録されたどうか確認します。
    フォント等が変更できるアプリケーション(例えばWord)を起動します。
    カーソルを入力したい場所に入れた状態でIMEパッドから文字一覧を表示します。
    文字カテゴリでシフトJISを選択して0xF40を選択すると外字文字の入力が出来たと思います。
    あとはフォントサイズや種類を変更して変化することを確認してください。
    この文字を上記手順やコピペすればChromeやEclipseでも表示されるはずです。

    3.Qtで確認します。
    QtCreatorを起動して外字を貼り付けます。
    「・」か「□」のような文字に文字化けしたと思います。

    試したこと
    1.文字コードのマッピング?
    QTextCodec::setCodecForCStrings
    QTextCodec::setCodecForTr
    putenv("UNICODEMAP_JP=XXX")
    辺りをいろいろ組み合わせましたが解決に至りませんでした。
    試しに外字を含んだテキストを読み込んでからアウトプットしてみたところ
    文字コードが正しく保持されているため文字コード自体が
    壊れているわけではないことが判りました。

    2.QFontにの設定?
    QFontにSystemかFixedSysを設定すると文字化けしなくなることが判りました。
    QtCreatorでもオプションメニューからテキストエディタ-フォント&色タブのフォントを
    SystemかFixedSysに変更すればエディタでは文字化けしなくなります。(UI周りは変わりません)
    ただ、Systemフォントでは制約が非常に大きいため解決とは言えませんでした。

    3.フォントの上書き
    以下のサンプルコードを使って検証します。
    15行目のボタンテキストに外字を入力してみます。
    @#include <QtGui>

    int main(int argc, char *argv[])
    {
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());

     QApplication app(argc, argv);
     QApplication::setFont(QFont("System"));
    
     QWidget window;
     window.resize(320, 240);
     window.show();
     QPushButton *button = new QPushButton(
         QApplication::translate("childwidget", "日本語←0xF40"), &window);
     button->move(100, 100);
    
     int fontsize = 11;
     //int fontsize = 9;
     //int fontsize = 16;
     //int fontsize = 24;
     button->setFont(QFont("MS UI Gothic", fontsize));
     button->show();
     return app.exec();
    

    }@

    一旦Systemフォントに設定すればフォントを上書きしても文字化けしないことは確認できました。
    ただし、外字だけはSystemフォントのまま表示されてしまいます。
    私も詳しくは知らないのですが、Systemフォントは特定のフォントサイズにしか対応しておらず
    最小が11ptとなっているようです。
    fontsizeを設定している部分を変更してみて頂ければ確認できます。

    なんとか外字の文字化けは回避できたと思いますが、
    可能であればフォント指定が有効になるようにしたいと考えております。
    何かお気づきの点があれば教えて頂けると助かります。

    よろしくお願いいたします。



  • うーん,分からない。。。
    日本語全体がsystemフォント固定になってるみたいですね。

    一応自分の確認コード
    (コンパイルエラーが出たらqmakeして下さい)

    @
    #include <QtGui>

    class MainWindow : public QDialog
    {
    Q_OBJECT
    public:
    MainWindow()
    {
    qApp->setFont(QFont("System"));
    QFontComboBox *f = new QFontComboBox;
    QSpinBox *s = new QSpinBox;
    setLayout(new QVBoxLayout);
    layout()->addWidget(new QLineEdit("\ue000 <- 外字"));
    layout()->addWidget(f);
    layout()->addWidget(s);
    s->setValue(11);

        connect(f, SIGNAL(currentFontChanged(QFont)), SLOT(fontSelected(QFont)));
        connect(s, SIGNAL(valueChanged(int)), SLOT(sizeSelected(int)));
    }
    

    public slots:
    void fontSelected(const QFont &f)
    {
    QFont ff(f);
    ff.setPointSize(font().pointSize());
    setFont(ff);
    }
    void sizeSelected(int size)
    {
    QFont f = font();
    f.setPointSize(size);
    setFont(f);
    }
    };

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
    MainWindow w;
    w.show();
    return a.exec();
    }

    #include "main.moc"

    @



  • 違う。。。

    選択したフォントで文字が見つからなければ
    qAppのフォント(System)で表示してるんですかね。。。



  • 選択したフォントで文字が見つからないと
    parentを辿って表示できるフォントが有れば使用する,というロジックらしい。

    根本的な解決になりませんが
    "System" の代わりに "Terminal" を使うと
    "System" よりは細かくサイズ指定できそうです。



  • ご回答ありがとうございます。

    確かにSystemよりもサイズ指定できることを確認できました!
    Systemが11,24...
    Terminalは6,11,17...

    残念なことに6ptだとかなり小さくなりますね。
    Terminalだと横長のフォントになってしまうのも痛いです。

    parentを辿って表示できるフォントが有れば使用する,というロジックらしい。
    具体的にソースコードの場所を教えて頂けると大変助かります。
    よろしくお願いします。



  • ごめんなさい,ソースコードを追ったわけではなくて
    実際の動作とドキュメントからです(;´∀`)

    QApplicationに"System",
    MainWindowに"MS UI Gothic",
    QLineEditに日本語非対応フォント
    みたいな事をしてみました。

    QFont::NoFontMerging のドキュメントに
    ちょっと説明らしきものが有りました。



  • 情報ありがとうございます。

    昨日の頂いた情報で、何処かの判定が間違っていて
    Systemに戻されてしまうのであれば強制的にフラグを書き替えたら
    直るのではないかと妄想しておりました。
    まさにQFont::NoFontMergingがそのスイッチにあたりますね。

    ドキュメントを読ませていただき
    QFont::NoFontMerging指定をしてみましたが
    指定したフォントで正しく文字化けに戻るだけですね(当たり前ですが)

    ギギギ…



  • 新たな問題が発覚しました。
    SystemやFixedSys、-Terminal-フォントに指定すると
    全角の数字「1」が文字化けし始めます。

    上記の私が書いたサンプルソースで
    15行目のテキストを"全角1"とし
    22行目のsetFontをコメントすると文字化けすることが確認できます。

    Qtのソースも見てみたのですがお手上げです
    恐らくこのあたりだと思うのですが…
    /src/gui/text/qfontengine_win.cpp
    /src/gui/text/qfontdatabase_win.cpp

    2012/04/24 20:17 追記です

    これで文字化けするのはXp端末で、
    Vistaや7では文字化けしませんでした。

    2012/04/25 18:39 追記です

    記載に誤りがありました。
    Terminalでは化けませんでした。


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.