How to change font of a QMessageBox in Qt? - qt

I was trying to build a simple application with a QComboBox and a QPushButton. The idea is to populate the QComboBox with a list of all available fonts in the system. When the user selects a font and presses the QPushButton then a QMessageBox appears with the font selected. Now how to do it?

The solution is using the setFont() method of the QMessageBox
QMessageBox *msg = new QMessageBox(QMessageBox::Information, "Message with font",
"This message is in font: " + ui->comboBox->currentText(),
QMessageBox::Ok | QMessageBox::Cancel, this);
QFont font = QFont(ui->comboBox->currentText());
msg->setFont(font);
msg->exec();
Where combobox is QComboBox used.

You can use basic HTML markups when setting the text to your message box label. The markup supported by QLabel includes <font>.This method also allows more versatile formatting.

As before suggested you could use styles in your Html blocks (in my example add style to the paragraphs):
QMessageBox.about(
self,
"About",
"<font>"
"<p style='font-family: Terminal'>An simple app.</p>"
"<p style='font-family: Georgia, 'Times New Roman'>- PyQt</p>"
"<p>- Qt Designer</p>"
"<p>- Python3</p>",
)
Results in:
QMessageBox

Related

How to customize QToolButtons from QToolBar in Qt?

I am having QToolBar with various tool buttons on it. I want to customize those buttons with some simple effects like, it should be seen that button is pressed, after pressing it should change its icon color or background color etc.
I tried but I could not succeed.
_toolbar = new QToolBar;
_toolbar->setIconSize(QSize(35,35));
_toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
void createIcons()
{
_zoomInIcon = QIcon::fromTheme("zoom-in");
_zoomIn = new QAction(_zoomInIcon, "Zoom in", this);
// code for other icons
_toolbar->addAction(_zoomIn);
}
void myClass::ZoomIn()
{
_zoomIn->setCheckable(true);
//QToolButton:_zoomInIcon {background-color: red; }
//setStyleSheet('background-color: red;');
// other logic
}
Moreover I am using Qt's default icons from this default-icons
But some of the icons are not looking good specially save in and save in as.
So does any one knows more default icons apart from above link in Qt ?
Can anyone help me ?
Try something like below (not tested)
//Get the tool button using the action
QToolButton* zoomInButton = mytoolbar->widgetForAction(_zoomIn);
//Set the style you want.
zoomInButton->setStyleSheet("QToolButton:pressed"
"{"
"background-color : red;"
"}"
);
And you can use all QPushButton styles, if your tool button don't have a menu.
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton
The QToolButton has no menu. In this case, the QToolButton is styled
exactly like QPushButton.

Clickable hyperlink in QTextEdit

I want to use QTextEdit (in read-only mode) to show a clickable hyperlink, I used to do
QTextEdit *textEdit = new QTextEdit;
QTextCursor cursor(textEdit->document());
textEdit->setTextCursor(cursor);
cursor->insertHtml("<a href=\"www.google.com\" >Google</a>");
textEdit->show();
this code will show Google as hyperlink but unable to click.
And if I used
QTextEdit *textEdit = new QTextEdit;
QTextCursor cursor(textEdit->document());
textEdit->setTextCursor(cursor);
QTextCharFormat linkFormat = cursor.charFormat();
linkFormat.setAnchor(true);
linkFormat.setAnchorHref("http://www.google.com");
linkFormat.setAnchorName("Google");
cursor.insertText("Google", linkFormat);
then nothing happen. "Google" is just normal text.
Please help me insert clickable hyperlink to QTextEdit.
Using QTextBrowser is simpler (as suggested by another answer). However, if for some reason you want to use QTextEdit, try to change the text interaction flags using setTextInteractionFlags().
I think you have to enable the Qt::LinksAccessibleByMouse flag.
See Qt::TextInteractionFlag and QTextEdit::textInteractionFlags
To have clickable hyperlink in QTextEdit, you can use
QTextCharFormat::setAnchorHref to set the link for some text
QWidget::mousePressEvent to capture mouse press event
QTextEdit::anchorAt to obtain the link
Here's the minimal working PyQt example,
import sys
from PyQt5.Qt import QDesktopServices, QUrl, QApplication, QColor, Qt
from PyQt5.QtWidgets import QTextEdit
class MyWidget(QTextEdit):
def mousePressEvent(self, e):
self.anchor = self.anchorAt(e.pos())
if self.anchor:
QApplication.setOverrideCursor(Qt.PointingHandCursor)
def mouseReleaseEvent(self, e):
if self.anchor:
QDesktopServices.openUrl(QUrl(self.anchor))
QApplication.setOverrideCursor(Qt.ArrowCursor)
self.anchor = None
app = QApplication(sys.argv)
editor = MyWidget()
cursor = editor.textCursor()
fmt = cursor.charFormat()
fmt.setForeground(QColor('blue'))
address = 'http://example.com'
fmt.setAnchor(True)
fmt.setAnchorHref(address)
fmt.setToolTip(address)
cursor.insertText("Hello world again", fmt)
editor.show()
app.exec_()
As far as I've tried, when using QTextEdit + Qt::LinksAccessibleByMouse I'm able to click on links, but no action is taken (i.e., link is not open). The only action possible is to right-click on the link and select Copy Link Location.
As mentioned, one option is using QTextBrowser. In this case you have to set the QTextBrowser::openExternalLinks property too, in order to open the link using the default browser, otherwise it will be open in the text-browser widget.
Another option, given you have a read-only text, is to use a QLabel with rich format, and using the QLabel::linkActivated signal to open the URL
label->setTextFormat(Qt::RichText);
QObject::connect(label, &QLabel::linkActivated, [](const QString & link) {
QDesktopServices::openUrl(link);
});
You can use QTextBrowser instead of QTextEdit if it read only text.
In order for setTextInteractionFlags() to work the openExternalLinks property needs to be set. Since this property is not available on QTextEdit, here is a little hack to enable it.
auto &clist = edit->children();
for each (QObject *pObj in clist)
{
QString cname = pObj->metaObject()->className();
if (cname == "QWidgetTextControl")
pObj->setProperty("openExternalLinks", true);
}
This does not address the mouse cursor, so you will still need to override mouseMoveEvent.

How to change the font of a QGroupBox's title only?

I want to change the QGroupBox's title to be bold and others keep unchanged. How to change the font of a QGroupBox's title only?
Font properties are inherited from parent to child, if not explicitly set. You can change the font of the QGroupBox through its setFont() method, but you then need to break the inheritance by explicitly resetting the font on its children. If you do not want to set this on each individual child (e.g. on each QRadioButton) separately, you can add an intermediate widget, e.g. something like
QGroupBox *groupBox = new QGroupBox("Bold title", parent);
// set new title font
QFont font;
font.setBold(true);
groupBox->setFont(font);
// intermediate widget to break font inheritance
QVBoxLayout* verticalLayout = new QVBoxLayout(groupBox);
QWidget* widget = new QWidget(groupBox);
QFont oldFont;
oldFont.setBold(false);
widget->setFont(oldFont);
// add the child components to the intermediate widget, using the original font
QVBoxLayout* verticalLayout_2 = new QVBoxLayout(widget);
QRadioButton *radioButton = new QRadioButton("Radio 1", widget);
verticalLayout_2->addWidget(radioButton);
QRadioButton *radioButton_2 = new QRadioButton("Radio 2", widget);
verticalLayout_2->addWidget(radioButton_2);
verticalLayout->addWidget(widget);
Note also, when assigning a new font to a widget, "the properties from this font are combined with the widget's default font to form the widget's final font".
An even easier approach is to use style sheets - unlike with CSS, and unlike the normal font and color inheritance, properties from style sheets are not inherited:
groupBox->setStyleSheet("QGroupBox { font-weight: bold; } ");
The answer above is correct.
Here are a couple extra details which may be helpful:
1) I learned in
Set QGroupBox title font size with style sheets
that the QGroupBox::title doesn't support font properties, so you CAN'T set the title font that way. You need to do it as above.
2) I find the setStyleSheet() method to be a bit more "streamlined" than using QFont. That is, you can also do the following:
groupBox->setStyleSheet("font-weight: bold;");
widget->setStyleSheet("font-weight: normal;");
I searched for this question coming from PyQt5 not Qt directly, so here is my answer in python hoping that it will help others in the same situation as me.
# Set the QGroupBox's font to bold. Unfortunately it transfers to children widgets.
font = group_box.font()
font.setBold(True)
group_box.setFont(font)
# Restore the font of each children to regular.
font.setBold(False)
for child in group_box.children():
child.setFont(font)
At least with Qt 4.8, setting the font to 'bold' with style sheets didn't work for me.
A somewhat simpler version to set all children widgets to normal font which works also when you are using the Qt designer (ui files):
QFont fntBold = font();
fntBold.setBold( true );
ui->m_pGroup1->setFont( fntBold );
auto lstWidgets = ui->m_pGroup1->findChildren< QWidget* >();
for( QWidget* pWidget : lstWidgets )
pWidget->setFont( font() );

Qt Style Sheet - Different styles for same type widgets

I need to assign different styles for the same typed widget instances. Specially for QActions. Following style sheet sets QActions' background images, actualy tool buttons'.
QToolButton
{
background-image: url(bg.png);
}
But I need to assign different backgrounds for tool buttons like this.
QToolButton::actClose
{
background-image: url(close.png);
}
QToolButton::actOpen
{
background-image: url(open.png);
}
Is there any easy way like this or is it not possible?
You can set object name for instances of QToolButton
QToolButton *button = new QToolButton;
button->setObjectName("firstButton");
button = new QToolButton;
button->setObjectName("secondButton");
and next use them in Style Sheet
QToolButton#firstButton
{
background-color: gray
}
QToolButton#secondButton
{
background-color: red
}
It helps if you can post c++ code that creates the QToolButton and associates with QActions.
Cite from QToolBar's reference "Toolbar buttons are added by adding actions, using addAction() or insertAction(). " and "QWidget * QToolBar widgetForAction (QAction *action )const
Returns the widget associated with the specified action."
So if you are creating QToolBar and call QToolBar::addAction(QAction*) to fill it, it is possible to get pointer to the tool buttons. Try QToolBar::widgetForAction(), and call setObjectName("") and Blueman's method can be applied.
while applying Style Sheet to widgets, "#" is used after class name to specify object name, ":" is used after className of objectName indicating the object's status such like "enabled", "::" is used to specify the subcontrols such as "ListView::Item", unfortunately QAction is neither of QToolBar.

Monospaced detailedText in QMessageBox

I've been using a QMessageBox to display the outcome of a statistical test. It's nice, because I can put a summary result in the informative text, then the full result in the detailed text. The trouble is, the full result is a table, so I'd like it to be monospaced so that it looks right, and QMessageBox doesn't use a monospace font in the detailed text area.
So I'm looking at either subclassing QMessageBox, or subclassing QDialog to make something that looks like a QMessageBox but uses a monospace font in the detailed text area. I'm a bit rusty at the moment, and having a hard time figuring out which is the better option. Could I subclass QMessageBox, just add my own QTextEdit and my own "show detailed text" button, and leave the QMessageBox detailed text area and button hidden? Or is there some easier way to do this?
You can use html text in the fields of a QMessageBox, that would be the easiest way. As a hint, try putting
<pre>Test</pre>
in your QString.
Any other customization of the message box will probably imply a subclass, though.
I did not find better than this:
setStyleSheet("QTextEdit { font-family: monospace; }");
It's a bit hacky because (1) it uses stylesheets, which may conflicts with your way of styling your widget and (2) it relies on the fact that the detailed text is in a QTextEdit and is the only such element, which is not officially ensured by the API. But it works. :D
Here is a working example, based on the answer of Lithy:
import sys
from PySide2.QtCore import *
from PySide2.QtWidgets import *
table_text = '\
Name Flower\n\
------ -------\n\
Violet Yes\n\
Robert No\n\
Daisy Yes\n\
Anna No\n\
'
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
warning_text = 'warning_text'
info_text = 'info_text'
pt = 'colour name'
msg = QMessageBox()
msg.setIcon(QMessageBox.Warning)
msg.setText(warning_text)
msg.setInformativeText(info_text)
msg.setDetailedText("{}".format(table_text))
msg.setTextInteractionFlags(Qt.TextSelectableByMouse)
# print all children and their children to find out which widget
# is the one that contains the detailed text
for child in msg.children():
print('child:{}'.format(child))
print(' {}'.format(child.children()))
pname = 'QMessageBox'
cname = 'QTextEdit'
msg.setStyleSheet(
"""{} {} {{ background-color: red; color: black; font-family: Courier; }}""".format(pname, cname))
msg.exec_()
if __name__ == '__main__':
app = QApplication(sys.argv)
Widget()
You can use html text in the detailedText of a QMessageBox using this hack:
QString html_formatted_text;
QMessageBox mb;
mb.setDetailedText(html_formatted_text);
// Find detailed text widget
auto te = mb.findChild<QTextEdit*>();
if (te) {
te->setHtml(mb.detailedText());
}
mb.exec();

Resources