ich nutze ein QTableView und ein Datenmodell abgeleitet von QAbstractTableModel zur Visualisierung von Statusnachrichten. Das Modell hat mehrere Spalten, wobei alle Spalten bis auf die letze eine feste Breite haben, die letzte Spalte hingegen soll stets mindestens so lang sein wie die längste bisher im Datenmodell vorhandene Textnachricht für diese Spalte es erfordert.
D.h. ich möchte nicht die (übliche) Stretch-Funktion für die letze Spalte, so das zu lange Texte mit "..." abgekürzt oder umgebrochen werden, sondern ich möchte, dass die Spalte immer breit genug auch für den längsten vorhandenen Text ist, wenn nötig, dann soll der horizontale Scrollbalken im View erscheinen.
Leider kann ich QTableView::resizeColumnToContents() nicht nutzen, da ich es nach jedem Verändern des Datenmodells erneut aufrufen muss, dann aber lediglich die Zeilen im Modell für die Berechnung verwendet werden, die gerade sichtbar sind. Wenn nach einem langen Text also viele kurze folgen, so dass die Zeile mit dem langen Text aus dem Sichtbereich verschwindet, dann wird die Spaltenbreite wieder verkürzt. Scrollt man dann zurück zur Zeile mit dem langen Text, dann ist dieser mit "..." abgekürzt.
Daher suche ich eine Lösung, die QTableView::resizeColumnToContents() nur dann aufruft, wenn der Text eine noch größere Spaltenbreite erfordert. Die Spaltebreite darf sich also nie verkleinern, sondern höchstens wachsen.
Ich dachte ich könnte dies mit QFontMetrics leicht berechnen, doch leider funktioniert das nicht. Der Code ist nicht vollständig, die Auszüge sollten aber reichen, hoffe ich.
Code: Alles auswählen
// Schrift definieren
QFont tableFont("MS Shell Dlg 2", 8, QFont::Normal);
Code: Alles auswählen
// Schrift für QTableView festlegen
tableView->setFont(tableFont);
Code: Alles auswählen
// Neue Statusnachricht erhalten
dataModel->appendLine(newStatusMessage);
tableView->scrollToBottom();
QFontMetrics fm(tableFont);
if (fm.width(newStatusMessage.toString()) > tableView->columnWidth(<relevante Spaltennummer>))
tableView->resizeColumnToContents(<relevante Spaltennummer>);
Zu Beginn ist die relevante Spalte 100 Pixel breit. Der erste Text der dort dargestellt werden soll ist laut QFontMetrics::width() 170 Pixel breit. Also ist die if-Bedingung wahr (170 > 100) und QTableView::resizeColumnToContents() wird aufgerufen. Danach liefert aber QTableView::columnWidth() nicht 170 sondern 234. Selbst wenn man noch ein paar Pixel für die Zellenränder im QTableView mit berücksichtigt, ist der Wert deutlich daneben. Ich kann aber sehen, dass die Spalte nicht viel zu breit, sondern exakt so breit ist, wie der Text gerade erfordert. Also liefert QFontMetrics::width() einen viel zu kleinen Wert.
Naja, es dauert dann nicht lange, bis Texte ins Modell hinzukommen, bei denen die Ungleichung nicht korrekt aufgeht. QFontMetrics::width() liefert dann einen Wert der noch gerade eben kleiner ist als QTableView::columnWidth() zurückgibt, der Text aber in Wirklichkeit zu lang ist und daher mit "..." abgeschnitten wird. Eigentlich wäre ein QTableView::resizeColumnToContents() nötig gewesen.
Plattform ist WinXP 32bit, Visual Studio 2008, Qt4.6.2