I solved my first problem. Every time I create a QFontComboBox, I get "Monospace" listed but selecting it gives me another font. Fine - I have removed all fonts that are not in the QFontDatabase. That removes the "Monospace" entry.
But when I use setCurrentFont with a courier font, it will add that option back in to the pull down.
This is on Linux with QT 5.15 (I just tried 6.6.1 and that does the same).
I have attempted to do my own font matching so that I am setting a font that it certainly should know about but that has not helped. Here is my latest test code -
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupUi(this);
QFontDatabase db;
QStringList fontFamilies = db.families();
QStringList filteredFonts;
QFont defaultFont("Courier");
bool foundDefault = false;
for (const QString& family : fontFamilies)
{
if (family.startsWith("Courier"))
{
defaultFont = QFont(family);
foundDefault = true;
}
if (QFont(family).exactMatch())
{
filteredFonts.append(family);
}
}
fontComboBox->clear();
fontComboBox->addItems(filteredFonts);
if (foundDefault)
{
fontComboBox->setCurrentFont(defaultFont);
}
connect(fontComboBox, &QFontComboBox::currentFontChanged, this, &MainWindow::fontUpdate);
}
void MainWindow::fontUpdate(const QFont& font)
{
}
On my system, it's finding "Courier 10 Pitch" and using that as the default. Is there anything I can do to stop that bogus entry popping up?
The user problem is that they pick "Monospace" but end up getting "DejaVu Sans Mono" when they go back in again.
Thanks
Peter
Whenever setCurrentFont()
is called, QFontComboBox always updates its internal list of family names.
The solution is to never call that function directly and use the basic setCurrentIndex()
of QComboBox, which is internally connected to a function that checks the current font and eventually updates it.
Unfortunately I cannot write in C++, but the following Python example based on your original code should be clear enough.
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.fontComboBox = QFontComboBox()
self.preview = QLabel('Hello world!')
layout = QVBoxLayout(self)
layout.addWidget(self.fontComboBox)
layout.addWidget(self.preview)
fontFamilies = QFontDatabase().families()
filteredFonts = []
defaultFont = QFont('Courier')
if QFontInfo(defaultFont).family() == defaultFont.family():
defaultFamily = defaultFont.family()
else:
defaultFamily = ''
for family in fontFamilies:
font = QFont(family)
if QFontInfo(font).family() == family:
if family.startswith('Courier') and not defaultFamily:
defaultFamily = family
filteredFonts.append(family)
self.fontComboBox.model().setStringList(filteredFonts)
self.fontComboBox.currentFontChanged.connect(self.preview.setFont)
if defaultFamily:
defaultIndex = self.fontComboBox.findText(defaultFamily)
if defaultIndex >= 0:
self.fontComboBox.setCurrentIndex(defaultIndex)
The last block also shows a possible alternative to setCurrentFont()
, in case you need a similar function, which could be implemented with something like this:
def setCurrentFont(self, font):
fi = QFontInfo(font)
index = self.fontComboBox.findText(fi.family())
if index < 0 and ' [' in fi.family():
# strip *foundry* names
family = fi.family()[:fi.family().index(' [')]
index = self.fontComboBox.findText(family, Qt.MatchStartsWith)
if index >= 0:
self.fontComboBox.setCurrentIndex(index)