QTableWidget: How can I get tighter lines with less vertical spacing padding? - qt

The QTableWdiget is fabulous for simple grid displays. Changing colors, fonts, etc is straightforward.
However, I did not manage to give the grid a 'tighter' look with less vertical whitespace. I see that the Qt documentation talks (eg here) about
margin
border
padding
around widgets, but when I set these I only get changes around the entire grid widget rather than inside.
How can I set this (with a style sheet, or hard-coded options) directly to make the QTableWidget display tighter?

The code getting 'h' might be unsound. It was just an example. Copy & paste the following rather rudimentary code. Change the value in "setDefaultSectionSize()", recompile, and run. You should see the difference. Setting this to 10 or 50 yields visible results. In the code above, it is possible QFontMetrics or QFont is messing something up.
You can use whatever you want to get the height, but font size makes the most sense.
#include <QtGui>
int main( int argc, char* argv[] )
{
QApplication app( argc, argv );
QDialog* my_dialog = new QDialog();
QHBoxLayout* layout = new QHBoxLayout();
QTableWidget* my_table_widget = new QTableWidget( my_dialog );
my_table_widget->setRowCount( 10 );
my_table_widget->setColumnCount( 10 );
my_table_widget->verticalHeader()->setDefaultSectionSize( 15 );
layout->addWidget( my_table_widget );
my_dialog->setLayout( layout );
my_dialog->resize( 500, 200 );
my_dialog->show();
return app.exec();
}
EDIT: I don't know how to format a block of code here... forgive me. :)
Edit 2: I fixed that, and the following simple tighterTable.pro file
helps along.
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
SOURCES += tighterTable.cpp # if that is the filename
Thanks a big fat bunch for this. BTW: Editing as code is just indenting by four spaces, and/or hitting the button with the little '101010' in the formatting row.

What you're looking for has a very silly solution IMHO, but it works. You need to set the headers' defaultSectionSize() members. Accessed via verticalHeader() & horizontalHeader(). I never really set the column width's w/ this b/c most of my projects involve me adding rows, not columns, and I just call resizeColumnsToContents or do a manual resizing. However, the rows is irksome. I generally get the height of the font using QFontMetrics, and add 2. Any subsequent row added should have this height, and viola: tighter look.
Hope that helps.
EDIT:
Untested code:
QFontMetrics fm( my_font );
int h = fm.height() + 2;
my_table->verticalHeader()->setDefaultSectionSize( h );

QTableWidget is a convenience model and view. Typically, QAbstractItemModel's data() method provides a SizeHintRole that is used to tell the view what size each cell should be.
Since you're using QTableWidget, I don't think there's anything that you can do to change the size hint being returned by its internal model. Even the Qt style sheet documentation mentions nothing in that area.

QTableWidget -> verticalHeader -> setMinimumSectionSize() is the right way, and it can be set in ui.

I tried all the answers here without success. What worked for me though was setting both the following.
table->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents)
table->verticalHeader()->setMaximumSectionSize(10)

Related

Adjust QTableView Height to its content (few lines)

Below a screenshot of my application. I want to get rid of the white spaces after the last tables lines marked by red rectangles :
The horizontal size policy is expanding and the vertical one is minimum and for other tables it is both set to expanding.
I'm using this method I found in another SO question but as you can see the result is not flawless.
void verticalResizeTableViewToContents(QTableView* tableView)
{
tableView->resizeRowsToContents();
// does it work ?
tableView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
int rowTotalHeight = 0;
// Rows height
int count = tableView->verticalHeader()->count();
for (int i = 0; i < count; ++i) {
// 2018-03 edit: only account for row if it is visible
if (!tableView->verticalHeader()->isSectionHidden(i)) {
rowTotalHeight += tableView->verticalHeader()->sectionSize(i);
}
}
// Check for scrollbar visibility
if (!tableView->horizontalScrollBar()->isHidden())
{
rowTotalHeight += tableView->horizontalScrollBar()->height();
}
// Check for header visibility
if (!tableView->horizontalHeader()->isHidden())
{
rowTotalHeight += tableView->horizontalHeader()->height();
}
tableView->setMaximumHeight(rowTotalHeight);
}
Somewhere, I'm using this code to setup one of the tables :
m_Internals->Ui.Measures->setModel(mm->getPh66MeasuresModel());
m_Internals->Ui.Measures->horizontalHeader()->setSectionsMovable(true);
m_Internals->Ui.Measures->horizontalHeader()->setHighlightSections(false);
m_Internals->Ui.Measures->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
m_Internals->Ui.Measures->horizontalHeader()->setStretchLastSection(true);
m_Internals->Ui.Measures->verticalHeader()->hide();
m_Internals->Ui.Measures->setSelectionBehavior(QAbstractItemView::SelectRows);
verticalResizeTableViewToContents(m_Internals->Ui.Measures);
I'm using Qt ModelView pattern to populate/update the tables.
Update : I made a small example to reproduce this issue with QTableView : https://github.com/embeddedmz/QTableViewAdjustPolicyNotWorkingProperly
Using the latest Qt version (from Qt official installer), there's no issue. However, using the Qt library provided by vcpkg (outdated for sure) the issue is there.
With Qt provided by vcpkg :
With the latest Qt provided by the Qt Company (update not the latest, it's 5.12.11) :
If you have something fully buildable on Ubuntu 20.04 LTS, post a link to the complete project (strip it down to just this part) and I will take an actual stab at it.
My gut, having worked with Qt for years, is telling me you are being burned by Margins.
https://doc.qt.io/qt-5/qwidget.html#contentsMargins
You probably need to set a bottom margin of Zero.
https://doc.qt.io/qt-5/qmargins.html#setBottom
If you retrieve the margins for those widgets you will probably find they are non-zero.
you can also fix your problem with one trick, this problem happens for you because your data is lower than the table size. I clone your project and change sizepolicy
Under Qt 5.12.11, the bug does not exist. So I took a look at the QAbstractScrollArea::sizeHint code of this version and compared it with the implementation used in recent versions of Qt and found that setting verticalScrollBarPolicy to "ScrollBarAlwaysOff" the "AdjustToContents" adjustment policy works. The default value was "ScrollBarAsNeeded", in fact we can see that this value is not handled but since in Qt 5.12.11 we only compare the vertical|horizontal]scrollBarPolicy to Qt::ScrollBarAlwaysOn it prevents this bug from appearing.

Highlight a text Qt [duplicate]

I'm a student programmer currently developing an application for work using Qt4. I am building an equation editor and I'm having issues attempting to highlight a string within my QTextEdit field. I have a function that parses through the QTextEdit string and returns an a start and end integer of where an error is located. My original strategy was to use HTML tags at these two points to highlight the error. Unfortunately there appears to be an issue with html tagging and the equation syntax.
What I think I need is a strategy that relies on Qt's library to set a background color between these two indices. I began looking a QSyntaxHighlighter; however I think that this is more for highlighting using a predefined set of laws and not for just grabbing up anything between a & b and setting the background color. If I can use syntax highlighter please provide me with and example or reference as I have already read through the documentation and didn't find anything.
Thanks for any help in advance!
P.S. Just to emphasize on the html compatibility issues; html becomes problematic due to multiple < and > signs used.
You can use QTextCursor and QTextCharFormat for it:
QTextEdit *edit = new QTextEdit;
...
int begin = ...
int end = ...
...
QTextCharFormat fmt;
fmt.setBackground(Qt::yellow);
QTextCursor cursor(edit->document());
cursor.setPosition(begin, QTextCursor::MoveAnchor);
cursor.setPosition(end, QTextCursor::KeepAnchor);
cursor.setCharFormat(fmt);

How to use QStyle::standardIcon/standardPixmap with QStyle::StandardPixmap?

In my code there is a bunch of calls which try to create QIcons from
QStyle standard pixmaps, like:
QIcon groupIcon;
groupIcon.addPixmap( style()->standardPixmap( QStyle::SP_DirClosedIcon ),
QIcon::Normal, QIcon::Off );
groupIcon.addPixmap( style()->standardPixmap( QStyle::SP_DirOpenIcon ),
QIcon::Normal, QIcon::On );
While this works correctly, in that using the icon for a model's
Qt::DecorationRole shows either an open or closed icon based on the item's
expanded state, it has two issues:
It's not hi-dpi friendly, and the icons are tiny
QStyle::standardPixmap is marked as obsolete, with QStyle::standardIcon being described as the preferred approach.
I'm unsure how to translate the above code to QStyle::standardIcon though.
QIcon groupIcon( style()->standardIcon( QStyle::SP_DirClosedIcon ) );
works nicely for closed items, and looks great on hidpi. But I can't see how I would add the SP_DirOpenIcon state. There's no equivalent method like "QIcon::addIcon" like there is QIcon::addPixmap.
What's the correct approach to take here, which is hi-dpi friendly and future proof?
how to translate the above code to QStyle::standardIcon
To be able to use QStyle::standardIcon instead of QStyle::standardPixmap, select the particular pixmap from the icon with QIcon::pixmap.
Here is an example I have prepared for you of how to change your code in order to accomplish that:
QIcon groupIcon;
QSize sz(16, 16);
groupIcon.addPixmap(style()->standardIcon(QStyle::SP_DirClosedIcon).pixmap(sz),
QIcon::Normal, QIcon::Off);
groupIcon.addPixmap(style()->standardIcon(QStyle::SP_DirOpenIcon).pixmap(sz),
QIcon::Normal, QIcon::On);
Here 16 is the requested size. Please note, that:
The pixmap might be smaller than requested, but never larger.
hence adjust this value accordingly.

Qt-Application is killing characters accidentally (drawText produces bug)

I've got a really simple application for adding watermarks to pictures. So you can drop your pictures in a QListWidget which shows you a thumbnail and the path, adjust some things like the text, the transparency, the output format and so on.. and after pressing start it saves the copyrighted picture in a destination of your choice. This works with a QPainter which paints the logo and text on the picture.
Everything is able to work fine. But here's the misterious bug:
The application kills random letters. It's really strange, because I can't reproduce it. With every execution and combination of options it's different. For example:
Sometimes I can't write some letters in the QLineEdit of my interface (like E, 4 and 0 doesnt exist, or he changes the letters so some special signs).
The text of the items in the QListWidget aren't completly displayed, sometimes completley missing. But I can extract the text normally and use the path.
While execution I have a QTextBrowser as a log to display some interesting things like the font size. Although, the font is shown normaly on the resulting picture, it says " 4" or "6" instead of much higher and correct sizes. Betimes strange white blocks appear between some letters
When drawing text on the picture with a QPainter, there also letters missing. Sometimes, all the letters are printed over each other. It seems like this bug appears more often when using small pixelsizes (like 12):
//Text//
int fontSize = (watermarkHeight-(4*frame));
int fontX = 2*frame;
int fontY = (result.height()-(watermarkHeight-2*frame));
int fontWidth = watermarkWidth;
QRect place(fontX,fontY,fontWidth,fontSize);
QFont font("Helvetica Neue", QFont::Light);
font.setPixelSize(fontSize);
emit log(QString::number(fontSize));
pixPaint.setFont(font);
pixPaint.setPen(QColor(255,255,255,textOpacity));
pixPaint.drawText(place,text);
Not all of these bugs appear at once! Sometimes I haven't got any bugs...
Perhaps someone had a similar bug before. Unfortunately I didn't found something like this in the internet. I didn't post a lot of code snippets because I think (and hope) that this is a gerneral problem. If you need something specific to help me, please let me know =)
I've added a example picture:
In the lineEdit I simply wrote ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 (look what he has done with the 7 and 9)
This small square in the lower corner of the picture should be the "ABC..." thing
The "62" looks very strange in the textBrowser
I'm using Qt 5.0.1 on a Windows 7 64Bit computer.
EDIT: Everytime after adding the first picture to the list, he's finding these warnings:
QFontEngine::loadEngine: GetTextMetrics failed ()
QWindowsFontEngine: GetTextMetrics failed ()
But when I change the height (and with it the pointSize of the font) its not emitted anymore, even with the start-parameters.
EDIT 2: Thank you for your help! I corrected my code so that he only uses correct fonts and correct sizes, but it still doesn't work. When I remove the QPainter::drawText() function it works fine (without the text). But as soon as I am adding text everything is bugged. I have something like this now:
//Text//
QList<int> smoothSizes = fontDatabase->smoothSizes("Verdana","Standard");
int fontSize = (watermarkHeight-(4*frame))*0.75;
emit log("Requested: "+QString::number(fontSize));
if(!smoothSizes.contains(fontSize)){
for(int i = 0; i<smoothSizes.length(); i++){
if(smoothSizes.at(i) > fontSize && i>0){
fontSize = smoothSizes.at(i-1);
break;
}
}
}
int fontX = 2*frame;
int fontY = (result.height()-(watermarkHeight/2)+frame);
QFont font = fontDatabase->font("Verdana","Standard",fontSize);
QFontInfo info(font);
emit log("Corrected: "+QString::number(fontSize));
emit log("Okay?: "+QString::number(info.exactMatch()));
pixPaint.setFont(font);
const QFontMetrics fontMetrics = pixPaint.fontMetrics();
if(info.exactMatch()){
pixPaint.setPen(QColor(255,255,255,textOpacity));
pixPaint.drawText(fontX,fontY+(fontMetrics.height()-fontMetrics.ascent()),text);
}
It almost sounds like you are corrupting random memory in your process, or you have a badly broken Windows install. Possibly your font request is matched by a very poorly chosen system font.
Whatever is set on a QFont is merely a request. To obtain the parameters of the actual font that was selected, you must create a QFontInfo, and get your information from there.
Imagine that you request a QFont that doesn't exist on a system, or that can't be scaled to a particular size. At some point the font object would need to morph to reflect what really happened - this would be very confusing. Thus, the QFontInfo provides the information about the font that was actually used. Think of QFontInfo as a response, and QFont as a request.
I finally found a solution: I simply updated Qt from 5.0.1 to 5.2.1, now it works. Perhaps someone has a similar bug and this post helps him. Thank you for your help!

QPlainTextEdit truncate history linewise

I have a GUI application whose main part is a QPlainTextEdit. It is used to display a log of the application, and as such the associated text grows line by line ad infinitum.
As the application is intended to run very long, I need to limit the memory that will be allocated for this log. Therefore I want to have some maxNumLines or maxNumCharacters parameter that will make sure the history will be truncated when reached, i.e. the head lines will be removed as new lines are appended (a.k.a. log rotation).
To achieve this I found the functions
// get the associated text
QString toPlainText () const
// set the associated text
void setPlainText ( const QString & text )
Therefore something like this untested code would probably do the trick:
QString &tmp = pte.toPlainText();
while (tmp.size() > maxNumCharacters) {
// remove lines from the head of the string until the desired size is reached
// removes nothing if "\n" could not be found
tmp.remove(0, tmp.indexOf("\n")+1);
}
pte.setPlainText( tmp );
Is this the way to go to remove the first line(s) from the QPlainTextEdit? Are there probably other Qt Text GUI elements that would better fit to this task (set a maximum number of lines and truncate at the head of the list), e.g. somehow display a QStringList in which I could store the lines (s.t. I could easily erase(0))?
Or does the QPlainTextEdit eventually implement such upper bound for the size of the associated QString after all?
Apparantly the property maximumBlockCount is exactly what I need:
If you want to limit the total number of paragraphs in a QPlainTextEdit, as it is for example useful in a log viewer, then you can use the maximumBlockCount property. The combination of setMaximumBlockCount() and appendPlainText() turns QPlainTextEdit into an efficient viewer for log text.
For reference:
http://doc.qt.io/qt-5/qplaintextedit.html#maximumBlockCount-prop
I had exactly the same problem a months back, and I ended up using a QListView. Although using the model/view/delegate architecture is a bit more fiddly, it scales much better in the long run. For example once the basic architecture is in place, adding a filter that displays only error or warning entries becomes trivial, or creating a delegate so that the background of error entries are painted red is also straightforward.

Resources