如何使用Qt中的QFont获取字体文件路径?

13

我想要获取包括文件扩展名在内的字体文件路径(例如"arial.ttf")。

QFont::rawname()方法总是返回"unknown"。

是否还有其他方法可以获取字体的名称和扩展名?

这是我们使用的代码:

    bool ok = true;
    QFont font = QFontDialog::getFont(&ok, this);
    if(ok)
    {
    QString fontpath = "/Library/Fonts/" + font.family()+".ttf";//Using font file path in the application
    }

你使用的是哪个操作系统? - UmNyobe
我使用的是Mac OSX 10.7.5。 - Julien Ravit
1
您可以使用QDesktopServices返回用户字体的路径。我认为系统字体路径有点棘手,因为它们在不同的系统之间变化很大。 - David Elliman
在大多数情况下,您并不一定需要绝对路径来设置字体。 - UmNyobe
“_stripView->setFont(fontpath)” 的结果是什么?它会抛出错误信息吗? - Thomas Ayoub
setFont(fontpath)没有问题。我已经从帖子中删除了它,但它仍然存在于代码中。 - Julien Ravit
3个回答

5

QFont 是对字体的请求,而不是匹配实际字体的描述;后者是 QFontInfo。请参见我其他回答。不幸的是,QFontInfo 不提供 rawName() 方法。如果有可能获取它,有一种绕弯路可以获取,但不能保证在所有平台上都有效。

QFont myFont;
QFontInfo info(myFont);
QFont realFont(info.family());
QString rawName = realFont.rawName(); 

如果你正在寻找标准位置,比如字体等东西的位置,在Qt 5中,你可以使用QStandardPaths::standardLocationsFontsLocation。在Qt 4中,你需要使用QDesktopServices::storageLocation


谢谢您的回答,但不幸的是第一个解决方案对我无效。当我显示_rawName_时它仍然返回_unknown_。我将尝试使用QStandardPaths来解决问题。 - Julien Ravit
没有保证它会工作。从实际目的来看,这基本上是一个不受支持的API。你到底需要字体路径做什么? - Kuba hasn't forgotten Monica
我使用一个 setFont(QString fontpath) 方法,需要字体路径。 - Julien Ravit
是的,这不是Qt方法。它使用_SDL_ttf_,需要.ttf文件来加载字体。 - Julien Ravit
明白了。看起来你需要使用特定于平台的方法,或者将文本渲染成 QImage 并将其传递到 SDL 中。SDL 的许多功能与 Qt 重叠。 - Kuba hasn't forgotten Monica

2
我需要做同样的事情,但我在使用Python。我使用PyQt界面选择字体,但使用PIL绘制文本,而PIL需要字体文件的路径(或者至少是文件名)才能使用它。到目前为止,我只有一个普遍的部分答案 - 希望我的回答可以适应您的需求。
您可以首先通过QStandardPaths获取字体所在路径,然后使用QFontDatabase迭代字体路径下的文件,并通过addApplicationFont将其加载到数据库中。如果加载成功,您将获得一个索引;然后将该索引提供给数据库的applicationFontFamilies函数。这只会给你字体族名称,但你可以用这个名称映射到文件路径。
你无法通过这种方法区分精确的字体(C:/Windows/Fonts/HTOWERT.TTF和C:/Windows/Fonts/HTOWERTI.TTF都返回相同的字体名称,但第二个是斜体),因此这不是一对一的映射,我甚至不确定它是否适用于非TrueType字体(.ttf),但至少这是一个开始。
以下是Python中的示例代码:
from PySide2.QtCore import QStandardPaths
from PySide2.QtGui import QFontDatabase
from PySide2.QtWidgets import QApplication
import sys, os

def getFontPaths():
    font_paths = QStandardPaths.standardLocations(QStandardPaths.FontsLocation)

    accounted = []
    unloadable = []
    family_to_path = {}

    db = QFontDatabase()
    for fpath in font_paths:  # go through all font paths
        for filename in os.listdir(fpath):  # go through all files at each path
            path = os.path.join(fpath, filename)

            idx = db.addApplicationFont(path)  # add font path
            
            if idx < 0: unloadable.append(path)  # font wasn't loaded if idx is -1
            else:
                names = db.applicationFontFamilies(idx)  # load back font family name

                for n in names:
                    if n in family_to_path:
                        accounted.append((n, path))
                    else:
                        family_to_path[n] = path
                # this isn't a 1:1 mapping, for example
                # 'C:/Windows/Fonts/HTOWERT.TTF' (regular) and
                # 'C:/Windows/Fonts/HTOWERTI.TTF' (italic) are different
                # but applicationFontFamilies will return 'High Tower Text' for both
    return unloadable, family_to_path, accounted


>>> app = QApplication(sys.argv)
>>> unloadable, family_to_path, accounted = getFontPaths()
>>> family_to_path['Comic Sans MS']
'C:/Windows/Fonts\\comic.ttf'

我觉得有点奇怪,竟然没有一种真正的方法将字体映射到它们的位置上。我的意思是,在某个时候,Qt需要知道字体在哪里,才能使用它,对吧?


0

根据 QFont 对象的字体系列,您可以获取所需的字体文件。

为了实现这一点,您可以使用 matplotlib 库,通过 pip 进行安装:

pip install matplotlib

然后您可以使用库中的font_manager模块,并访问其find_font函数,该函数将字体系列作为字符串输入,如下所示:

Python:

from PyQt6 import QtGui
#QtGui.QFont() should be replaced with your QFont Object

QtGui.QFont().family()

C++(等价)

QFont::family()

接下来,您将从QFont对象中获取字体系列,并将其放入font_manager.find_font()方法中:

from matplotlib import font_manager

x = QtGui.QFont().family()  #this is now a string
font_manager.find_font(x) 
#this method now converted the font family string into the file path of the font

总的来说,代码看起来像这样:

from PyQt6 import QtGui
from matplotlib import font_manager

#QtGui.QFont() should be replaced with your QFont Object

QtGui.QFont().family()

x = QtGui.QFont().family()  #this is now a string
font_manager.find_font(x) 
#this method now converted the font family string into the file path of the font

这是PyQt6中一个真实的例子:

from PyQt6 import QtGui, QtWidgets, QtCore
import os
#import matplotlib.font_manager as font_manager
from matplotlib import font_manager

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.fontComboBox = QtWidgets.QFontComboBox(self.centralwidget)
        self.fontComboBox.setGeometry(QtCore.QRect(210, 220, 338, 32))
        self.fontComboBox.setObjectName("fontComboBox")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 30))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

def your():
    print(font_manager.findfont(ui.fontComboBox.currentFont().family()))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    your()
    sys.exit(app.exec())

我知道你可能不会使用python,因为你正在使用C++,但是你可以研究如何在python中使用open()函数来编写一个包含文件路径的文本文件(或者制作一个jason文件,由你决定)。

希望这能在某种程度上帮助到你,如果有任何问题,请随时问我。即使它似乎很基础,也不要让它让你灰心丧气。无论别人怎么说!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接