How to override tab width in qt?
Solution 1
If you want to create a source code editor using QTextEdit
, you should first assign a fixed-width (monospace) font. This ensures that all characters have the same width:
QFont font;
font.setFamily("Courier");
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
font.setPointSize(10);
QTextEdit* editor = new QTextEdit();
editor->setFont(font);
If you want to set a tab width to certain amount of spaces, as it is typically done in text editors, use QFontMetrics
to compute the size of one space in pixels:
const int tabStop = 4; // 4 characters
QFontMetrics metrics(font);
editor->setTabStopWidth(tabStop * metrics.width(' '));
Solution 2
The QTextEdit::tabStopWidth
property might solve your problem (see here for Documentation...)
Solution 3
While the question about how to set tab stop width has been answered already; computing the correct tab width in pixels is still (or again?) an open question.
Since Qt 5.10, QTextEdit::tabStopWidth
is marked as obsolete and QTextEdit::tabStopDistance
was introduced. tabStopWidth
was integer, tabStopDistance
is double
.
Why so complicated?
Setting n * QFontMetrics::width(' ')
as tab stop width makes troubles because font_metrics.width
returns an integer. Even if you have a monospace standard font, the width of a single character is actually not an integer, so QFontMetrics::width
returns an inaccurate measure.
If you compare the appearance of the strings ........|
and \t\t\t\t|
(\t = tab, n=2), you will see that the pipes are not aligned properly. It will become worse the more tabs you insert.
Solution
You could do what @Ferdinand Beyer proposed, but it will slightly change the typeface. I also had to adapt his method to make it work. However, there's a much simpler approach which exploits that you can set tabStopDistance
now with double precision:
static constexpr int tab_width_char = 2;
m_text_edit->setFont(QFont("Courier", 12));
const auto font_metrics = m_text_edit->fontMetrics();
static constexpr int big_number = 1000; // arbitrary big number.
const QString test_string(" ");
// compute the size of a char in double-precision
const int single_char_width = font_metrics.width(test_string);
const int many_char_width = font_metrics.width(test_string.repeated(big_number));
const double single_char_width_double = many_char_width / double(big_number);
// set the tab stop with double precision
m_text_edit->setTabStopDistance(tab_width_char * single_char_width_double);
This would be so much simpler if Qt offered a way to get the width of a single character as double
.
Solution 4
While @Ferdinand Beyer's solution will work on some systems, generally fonts are not guaranteed to have integer metrics. e.g 12pt DejaVu Sans Mono
on my Linux setup has character width of 9.625. The best solution I've found is add some letter spacing to get pixel-perfect alignment.
int tabstop = 4;
QFontMetricsF fm (ui->textEdit->font());
auto stopWidth = tabstop * fm.width(' ');
auto letterSpacing = (ceil(stopWidth) - stopWidth) / tabstop;
auto font = ui->textEdit->font();
font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
ui->textEdit->setFont(font);
ui->textEdit->setTabStopWidth(ceil(stopWidth));
Solution 5
Computing a product of a size of one space and num spaces is not always precise (tested under macOS, Monaco font), presumably due to some gaps in between the characters in the real string. A better solution would be to measure the length of the string containing tabStop spaces:
const int tabStop = 4; // 4 characters
QString spaces;
for (int i = 0; i < tabStop; ++i) {
spaces += " ";
}
QFontMetrics metrics(font);
editor->setTabStopWidth(metrics.width(spaces));
Related videos on Youtube
![Barış Akkurt](https://i.stack.imgur.com/1NP25.jpg?s=256&g=1)
Barış Akkurt
Hi! I'm Baris Akkurt. This is my personal SO profile. I also have a personal website. I graduated from Istanbul Technical University with a bachelor's degree in computer engineering. I am now a full time software developer in a private company. I like travelling and reading book.
Updated on June 18, 2022Comments
-
Barış Akkurt about 2 years
I just need to know how to change the tab size in Qt in a QTextEdit. My Google and stackoverflow search returned me null. Thanks in advance.
-
fasked over 11 yearsHow about
tabStopWidth
property? doc.qt.digia.com/qt/qtextedit.html#tabStopWidth-prop -
Al.G. over 5 yearsI rejected the suggested edit by mistake, I think it's valid.
-
-
Barış Akkurt over 11 yearsthanks for your reply, to try it I set TabStopWidth to 40, so this changed my tab size. But this corresponds to 11 space characters and 5 a characters. Why all the charachters have different sizes? I want my editor to behave like source code editors. What i am missing?
-
JonathanK over 9 yearsUse a monospace font like Courier New and all your characters will have the same width.
-
Patrizio Bekerle over 4 yearsSadly setTabStopWidth is obsolete since Qt 5.10, see doc.qt.io/archives/qt-5.10/qtextedit-obsolete.html
-
Ferdinand Beyer over 4 years@PatrizioBekerle - looks like it has just be renamed to
tabStopDistance
? See doc.qt.io/archives/qt-5.10/qtextedit.html#tabStopDistance-prop -
Patrizio Bekerle over 4 yearsYes, @ferdinand-beyer, it looks that way.
-
Shefeto over 3 yearswidth (of a char) is also no longer used, you can use maxWidth() instead no problem because the width is uniform
-
foddex over 2 yearsIn at least Qt 5.15.2, I had to change font_metrics.width to font_metrics.horizontalAdvance, other than that this solution is the only one that worked for me!