wrap text in the tabBar of QTabWidget - qt

Im changing text of QTabWidget dynamically and also changing its font family. so the text in the tabBar header is exceeding the actual width. how i can control the text to wrap inside the tabBar width like
"Text.."
im setting the font family using stylesheet
QString menuBarStyle = QString("QTabBar::tab {font-family: %1;font-style: %2;font-size: 11pt;font-weight: %3;width: 130px}").arg(m_currentFont.family()).arg(fontStyle).arg(fontWeight);
TabWidget->setStyleSheet(menuBarStyle);

Qt stylesheet technique may or may not let to solve it that but I once resolved similar problem like that:
QString elidedText(const QFont& someFont, int width)
{
QFontMetrics metrix( someFont );
return metrix.elidedText(text, Qt::ElideRight, width);
}
So, in addition to font object you have to have the width to fit the text in. Also frequently applying changes via the stylesheet for the widget can hardly be optimal solution, it does a bit too much to get the small change.

Related

How to change QPushButton icon/text spacing with stylesheets?

I'm fairly new to Qt's method of stylesheets and I am looking to adjust the spacing between the icon and text on a QPushButton.
This is the gap I'm referring to: http://imageshack.us/scaled/thumb/593/4kem.png (stackoverflow won't let me post pics yet)
QPushButton {
qproperty-icon: theme_url("/button_action/add");
qproperty-iconSize: 14px;
}
Is there a parameter I can use to adjust this space? I've tried margin, padding, spacing? Perhaps there is a different selector that I can use to just grab the icon?
Actually with QPushButton you are out of luck. You can find a complete list of working options for styling push buttons in the qt documentation ( I am assuming you use qt5, but it is available for other versions as well).
What is often recommended if you want more control over the icon is to exchange your QPushButtons with QToolButtons wich are exactly the same except that they have extra features to make them compatible with toolbars -and- they have more options for icon placement. But this might not work for you because as you can see they are styled the exact same way as QPushButtons. But do look into the "toolButtonStyle" parameter which allows you to move the icon around.
Next on the list comes changing the artwork. If all you want is more space then just add the extra empty pixels to the artwork. This really hurts the perfectionist's mind but is effective.
Next on the list comes subclassing QPushButton and overriding the paint yourself. Sounds more daunting than it is. Subclassing in Qt has become a habit already and it works great. Here is a tutorial i googled in a jiffie (for 4.8 but should be about the same for 5) on the matter of subclassing. It even covers overriding the paint event.
Hope this was helpful.
At least with Qt5.5 (this may change in the future, I hope), besides overriding the paint event, which is complex and in my opinion messy for just a simple thing, there's no inherent Qt way to move that icon a few pixels here or there (small adjustments). If you remove the icon and use a stylesheet to set the background to your icon in your resource URL, you can use background-position property in the stylesheet, but unfortunately it only accepts words like center, left, etc., not pixel adjustments.
Here's how I resolved this problem. I created transparent PNGs that were slightly larger than I needed, where I had like a 4px margin around the icon itself inside the PNG. Then, I just moved the icon inside that canvas and reloaded it into the project resources file, and then mapped it again with the icon property in the designer for the QPushButton, and that worked. I now have icons that line up properly on the left with the text beside it. I can even widen the gap between icon and text.
As of Qt5.7 I don't know of any built-in functionality for the icon/text spacing.
What I usually do is give the image some more space to the right and set the icon size of the button accordingly.
Solution:
Resize your icon file to 32*16 px but leave its content as is.
Call setIconSize(QSize(32, 16)) on your button.
Result: Now there's 16 pixel empty space between its icon and text. 32 pixel is just my example, you can of course set the additional size to something that suites your style.
If you want to apply that on all your button elements simply create a tiny subclass that does it automatically in the constructor. There's really no need to override the paintEvent method for this.
Here is a workaround way to achieve that 'space between text and image':
QPushButton{
border:0px;
image: /*your url*/;
padding-top:16px;
image-position:top;
text-align:bottom;
padding-bottom:10px;
}
since qss doesn't support relative size, you need to implement resize() to change stylesheet when size changing to get a fixed space between text and image.
Here's an opportunistic approach to customize the spacing between text and icon. There's currently no regular way to change the width, so we need to add a transparent area to the right of the icon which is applied to paint device.
Firstly, add a new member variable "m_spacing"(double) and initialize it to 0.0 in constructor, as a factor of expanding the width.
Then, override the "paintEvent", "sizeHint" and "minimumSizeHint".
class CPushButton : public QPushButton {
Q_OBJECT
public:
double spaceRatio() const;
void setSpaceRatio(double ratio);
protected:
double m_spacing;
void paintEvent(QPaintEvent *event) override;
......
QSize CPushButton::sizeHint() const {
QSize sz = QPushButton::sizeHint();
int offset = iconSize().width() * m_spacing;
return QSize(sz.width() + offset, sz.height());
}
QSize CPushButton::minimumSizeHint() const {
QSize sz = QPushButton::minimumSizeHint();
int offset = iconSize().width() * m_spacing;
return QSize(sz.width() + offset, sz.height());
}
void CPushButton::paintEvent(QPaintEvent *event) {
QSize sz = iconSize();
QPixmap tmp = icon().pixmap(sz); // Get the pixmap to apply with right size
sz.rwidth() *= 1 + m_spacing; // Multiply width
QPixmap exp(sz); // Expended
exp.fill(Qt::transparent);
QPainter painter(&exp);
painter.drawPixmap(QRect(QPoint(), tmp.size()), tmp);
QStylePainter p(this); // From Qt source
QStyleOptionButton option; // From Qt source
initStyleOption(&option); // From Qt source
option.icon = QIcon(exp); // Change to real icon
option.iconSize = sz; // Change to real size
p.drawControl(QStyle::CE_PushButton, option); // From Qt source
Q_UNUSED(event)
}
Now you can create a CPushButton instance and set the spacingRatio to 0.1 or other positive real. Visually, it does increase the spacing between text and icon.
The simplest way to go for it is to create your own class inheriting from the QPushButton and override the PaintEvent and then manually place the pixmap of the icon where ever you want.
Best way to solve this problem is adding some blank space in the beginning of QPushButton text. it works well for me!
See here

Determine CSS-styled Text size in JavaFX / force styling?

I have a problem determining the width of a rendered text node in JavaFX 2. When using the standard style, everything works fine:
Text testText = new Text("test");
double width = testText.getLayoutBounds().getWidth();
But if I apply custom CSS styling which sets a different font size like this
.text-class {
-fx-font: 20px "Tahoma Bold";
}
and apply the CSS class to my example above:
Text testText = new Text("test");
testText.getStyleClass().add("text-class");
double width = testText.getLayoutBounds().getWidth();
I will get the same result as in the first case, so obviously styling is delayed to some later point in time.
How do I determine the width of a CSS-styled text in JavaFX 2? Is it possible to somehow force immediate CSS styling?
CSS application is not done immidiately, so, the way to solve the issue, is do your actions, when size of text actually changes.
testText.layoutBoundsProperty()
Is the property, which responds to bounds, and it stores an immutable object. There are also other properties, telling you about size and position. What you can do - is to attach a change listener on this property, and apply changes, when a modification is done.
CSS-Styles are applied on the next so called pulse beside that the layoutBounds are influence by the parent container your put it into.

QTextEdit display width vs text width

I'm creating a 'scrolling-text' class in Qt, using a QTextEdit (read-only, no scrollbars, moveCursor) and a QTimer - simple and working.
My problem is when the text sent to the class is shorter (narrower) than the QTextEdit-box.
Silly, I agree, but, being new to Qt, I didn't find an easy way to compare the width of the given text (depending on the font) and the actual width that can be displayed inside the QTextEdit (after calculating the FrameStyle, etc.). I presume I need to calculate the pixels.
Any ideas?
Thanks
You can get the width of a text using QFontMetrics:
int textWidth = myTextEdit->fontMetrics().width(myTextEdit->text());

Hiding text with QSyntaxHighlighter

Problem: I want to implement a text editing widget for text with additional tags.
I'd like some tags to be invisible in some cases so that they do not distract the user.
Environment: I'm using PyQt and prefer to use QPlainTextWidget and QSyntaxHighlighter.
Approach: With QSyntaxHighlighter I can set QTextCharFormat for the strings which match my requirement. QTextCharFormat has gives me all font properties like size, colors, etc. but: I haven't found a option to hide the text or reduce its size to zero.
I don't want to remove or replace the tags, as this will introduce a lot more code (copying should contain tags and without I can't use QSyntaxHighlighter for formating the remaining text according to the tags).
Update: So far I found a ugly hack. By setting the QTextFormat::FontLetterSpacing to a small value, the text will consume less and less space. In combination with a transparent color the text is something like invisible.
Problem: In my test this worked only for letter spacings down to 0.016 %. Below the spacing is reseted to 100 %.
You can use the underlying QTextDocument for this. It consists of blocks whose visibility can be turned on and off using setVisible. Use a QTextCursor to insert the text and new blocks and switch visibility. As a bonus the copy function copies the content of non-visible blocks anyway.
Notes: See the documentation of QTextCursor for more information. In another question here is was reported that setting the visibility is not working on QTextEdits.
Example:
from PyQt5 import QtWidgets, QtGui
app = QtWidgets.QApplication([])
w = QtWidgets.QPlainTextEdit()
w.show()
t = QtGui.QTextCursor(w.document())
t.insertText('plain text')
t.insertBlock()
t.insertText('tags, tags, tags')
t.block().setVisible(False)
print(w.document().toPlainText())
app.exec_()

QLabel: interlinea/linespacing in WordWrap mode

How do I set line height in QLabel when in WordWrap mode?
Use HTML text:
QString template = "<p style=\"line-height:%1%\">%2<p>";
QString targetText = template.arg(myPercentage).arg(myTex);
QLabel *l = new QLabel(targetText, this);
where myPercentage is like 60 - 80.
You will get condensed lines in the WordWrap mode
There is no line spacing property in QLabel. You can change the widget font, which will change the line's height, but I suspect that is not what you want.
Line height is computed from the QFont of the widget and can be obtained by the QFontMetrics associated with the widget. Using this information, you may create your own widget that has a line spacing property (and a text wrap mode), but that represents a lot of low-level work.
You can also edit the HTML of the QLabel directly in Qt Designer.
Select the label in Qt Designer.
In the Property Editor, under the QLabel section, select the text property and press the ... button.
Select the "source" tab and edit the HTML from there.
Here are two examples that control the line spacing of a QLabel using HTML (tested in Qt 5.7). I am sure there are many more (and some better) ways to write the HTML, but this should be a good start.
Example 1
<html><head/><body>
<p style="line-height:120"><span>
This is the first line of the label.<br>
This is the second line.<br>
This is the third and final line.
</span></p>
</body></html>
This example is neater if the line spacing is the same for the whole paragraph.
Example 2
<html><head/><body>
<p style="line-height:20"><span>This is the first line of the label.</span></p>
<p style="line-height:20"><span>This is the second line.</span></p>
<p style="line-height:100"><span>This is the third and final line.</span></p>
</body></html>
This example allows you to control the spacing of each line individually. I had to make the height of the last line 100 to prevent Qt from cutting it in half. I assume it affects how Qt calculates the height of the label as a widget.

Resources