I would like to create my own Balloon window for tips in Qt. I'm starting by creating a window with round corners.
I'm using a class inherited from QFrame. The class's constructor contains:
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
Pal.setColor(QPalette::Background, Qt::yellow);
this->setAutoFillBackground(true);
this->setPalette(Pal);
this->setStyleSheet("QFrame {border-style: solid; border-width: 10px;"
"border-radius: 100px;"
"min-width: 10em; background-clip: padding; background-origin: content;}");
But this is not creating round corners when showing using the show() member function. I'm getting this:
How can I get rid of those rectangular edges and have them transpararent colored?
If you require any additional information, please ask.
If my guess is correct you are looking for something like setMask !
Basically what you need to do is draw a rectangle with your desired radius and then convert it to QRegion to use it with setMask. See below one way:
QPainterPath path;
path.addRoundedRect(rect(), 100, 100);
QRegion region = QRegion(path.toFillPolygon().toPolygon());
setMask(region);
And that will be the result:
Hope that helps!
auto frame = new QWidget(parent, Qt::Popup);
frame->setStyleSheet("background-color: red; border: 1px solid green; border-radius: 6px;");
QPainterPath path;
path.addRoundedRect(frame->rect(), 6, 6);
frame->setMask(path.toFillPolygon().toPolygon());
frame->show();
Related
How i could create a QTextEdit with a space for a caption like seen on gmail:
The result I got with the code below:
I figured a way to calculate where the top border should end (Before Email) and start again (after phone), but I not figured how to clear the border in the area where 'caption' is drawn.
Example:
// textedit.h
class TextEdit : public QTextEdit
{
Q_OBJECT
public:
QLabel* caption;
TextEdit(QWidget* parent = 0) : QTextEdit(parent)
{
caption = new QLabel(this);
caption->setText("Email or phone");
caption->setStyleSheet(R"(
font: 14px;
font-weight: 900;
color: #3762ab;
border-radius: 4px;
background-color: rgba(0, 0, 0, 30);
margin-left: 32px;
)");
caption->adjustSize();
auto caption_rect = caption->contentsRect();
int caption_x = caption_rect.x();
int caption_width = caption_rect.x() + caption_rect.width();
qDebug() << "Position where the left border should end:\n"
<< caption_x << "\n";
qDebug() << "Position where the border start after the caption:\n"
<< caption_width << "\n";
}
};
#include "textedit.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QTextEdit* textEdit = new TextEdit(this);
ui.centralWidget->setStyleSheet("#centralWidget { background-color: #121212; }");
textEdit->setStyleSheet(R"(
QTextEdit
{
border-radius: 4px;
border: 3px solid #3762ab;
background-color: transparent;
margin-top: 10px;
}
)");
textEdit->setGeometry(100, 50, 300, 70);
}
I think to achieve this I would need to draw the borders in the paintEvent, so i tried:
void paintEvent(QPaintEvent* event)
{
QTextEdit::paintEvent(event);
QPainter painter(viewport());
int borderWidth = 4;
QPen pen;
pen.setWidth(borderWidth);
//pen.setBrush(radialGrad);
painter.setRenderHint(QPainter::Antialiasing, true);
QPoint center = viewport()->rect().center();
auto r = this->contentsRect();
QPainterPath path;
//path.lineTo(0, 0);
//path.moveTo(r.width(), 4);
//painter.setClipPath(path);
// Top border
pen.setColor(Qt::red);
painter.setPen(pen);
// Line before the caption
painter.drawLine(QLine(0, 0, caption_x, borderWidth));
// Line after the caption
painter.drawLine(QLine(caption_width, 0, r.width(), borderWidth));
// Left border
pen.setColor(Qt::white);
painter.setPen(pen);
painter.drawLine(QLine(0, 0, borderWidth, r.height()));
// Bottom border
pen.setColor(Qt::green);
painter.setPen(pen);
painter.drawLine(QLine(0, r.height() - borderWidth, r.width(), r.height()));
// Right border
pen.setColor(Qt::blue);
painter.setPen(pen);
painter.drawLine(QLine(r.width() - borderWidth, 0, r.width(), r.height()));
}
Result:
I use different colors just to figure if each border was being drawn correctly...
Btw, the borders looks weird, looks like they are being drawn with a different thickness, and i'm not sure how to draw the lines curved.
I really recommand you to use QGroupBox and style sheets to adjust all you want.
Here is an example (In QtDesigner, I just put a QLineEdit in a QGroupBox and made the layout of the groupBox horizontal).
ui->groupBox->layout()->setContentsMargins(2,2,2,2);
ui->centralwidget->setStyleSheet("QWidget{"\
"background-color:black;}");
ui->groupBox->setStyleSheet("QGroupBox{"\
"color:blue;"\
"background-color:black;"\
"border: 1px solid;"\
"border-color: blue;"\
"border-radius: 5px;"\
"margin-top: 20px;}"\
"QGroupBox::title{"\
"subcontrol-origin: margin;"\
"left: 20px;"\
"padding: 10px 0px 0px 0px;}");
ui->lineEdit->setStyleSheet("QLineEdit{"\
"color:white;"\
"background-color:black;"\
"border: none;}");
Here is what I've got :
I have a question and it seems that it has been asked before by someone else but with no answers since 2008.
http://www.qtcentre.org/threads/17227-QTabBar-scrollbar-separation
Is it possible to separate the scrollbar from QTabBar like this?
"<-" tab1 | tab2 | tab3 | tab4 "->"
The scrollbars consists of two seperate QToolButton. I don't think they can be re-styled by subclassing QTabBar and overriding paintEvent. You will have to create your own function (with the help of paintEvent) that moves invisible tabs to the viewport. This is also the same way how Qt has implemented it see makeVisible and connect seperate buttons to it which moves the tabs.
There is also another easy way to connect your own buttons to QTabBar. At first you have to call
setUsesScrollButtons(bool useButtons)
and set this value to true. Then you re-style the scrollbar with an alpha channel, so it becomes invisible.
QTabBar QToolButton {
background-color: rgba(255, 255, 255, 0);
border:0;
}
QTabBar QToolButton::right-arrow:enabled {
background-color: rgba(255, 255, 255, 0);
border:0;
}
QTabBar QToolButton::right-arrow:disabled {
background-color: rgba(255, 255, 255, 0);
border:0;
}
QTabBar QToolButton::left-arrow:enabled {
background-color: rgba(255, 255, 255, 0);
border:0;
}
QTabBar QToolButton::left-arrow:disabled {
background-color: rgba(255, 255, 255, 0);
border:0;
}
Then you can create two QPushButton or QToolButton with < and >.
void MainWindow::on_pushButton_2_clicked()
{
ui->tabWidget->setCurrentIndex(ui->tabWidget->currentIndex()+1);
}
void MainWindow::on_pushButton_clicked()
{
ui->tabWidget->setCurrentIndex(ui->tabWidget->currentIndex()-1);
}
Sample screen
Maybe that's enough for your use and you don't need to re-implement all the stuff, which will take a couple of days probably.
If you want to have the QPushButton or QToolButton inside QTabBar you can archieve this by subclassing paintEvent. To do so, set the QPushButton or QToolButton to the QTabBar parent and add to the x-coordinate the size of the QPushButton, so they don't overlap. (screenshot has the buttons not as parent.)
I want to make QLineEdit looks like QLabel with bold text if it's inactive and like QLineEdit with normal weight if active. In my understanding "active" = when text cursor shown and user can enter a text.
I tried to apply this css:
QLineEdit {
font-weight: normal;
border: 1px solid black;
}
QLineEdit:!focus {
font-weight: bold;
border: none;
}
Border works as expected, but font-weight is always bold.
I was thinking of creating my class to handle activation event, but can't found anything related with it.
I will be very thankful if somebody can help me.
You need to get your custom slot for the focusChanged event. There you can change the font like this:
QFont font = ui->lineEdit_search->font();
font.setWeight(QFont::Bold); // or
font.setWeight(QFont::Normal);
ui->lineEdit_search->setFont(font);
An example where I handled a LineEdit search box is here, but you have to customize it with the bold text.
void MainWindow::focusChanged(QWidget* old, QWidget* now)
{
if(now != NULL &&
now->objectName() == "lineEdit_search")
{
if(ui->lineEdit_search->text() == tr("Search..."))
{
ui->lineEdit_search->clear();
QPalette *palette = new QPalette();
palette->setColor(QPalette::Text,Qt::black);
ui->lineEdit_search->setPalette(*palette);
delete palette;
}
}
else if(old != NULL &&
old->objectName() == "lineEdit_search")
{
if(ui->lineEdit_search->text().isEmpty())
{
ui->lineEdit_search->setText(tr("Search..."));
QPalette *palette = new QPalette();
palette->setColor(QPalette::Text,Qt::gray);
ui->lineEdit_search->setPalette(*palette);
delete palette;
}
}
}
When you turn your line edit to inactive,
//Set your line edit to read only
yourLineEdit->setReadOnly(true);
//Get your widget background color
const QColor clr = this->palette().color(QWidget::backgroundRole());
//Set the widget background color to both the line edit background and its border
QString backGroundstyle = "background-color: rgb(%1, %2, %3);";
QString borderStyle = "border: 1px solid rgb(%1, %2, %3);";
yourLineEdit->setStyleSheet(backGroundstyle.arg(clr.red()).arg(clr.green()).arg(clr.blue()) + borderStyle.arg(clr.red()).arg(clr.green()).arg(clr.blue()));
When you turn line edit to active
//Make your line edit read-write
yourLineEdit->setReadOnly(false);
//Bring back your styles.
QString backGroundstyle_active = "background-color: white;";
QString borderStyle_active = "border: 1px solid black;";
yourLineEdit->setStyleSheet(backGroundstyle_active + borderStyle_active);
Been trying to do this for quite a while and took advice from every forum post i could find but i still cant solve it. This is my current code and I would really like to change the color of the chunk on the progress bar. Every other setting is working, except the colors.
In my workspace object that fills up one subview on the MainWindow.
Workspace::Workspace( QWidget* parent) : QWidget( parent )
{
QTableView* tableView = new QTableView();
// ...
tableView->setItemDelegate(new ProgressBarDelegate);
}
The delegate.cpp looks like this:
ProgressBarDelegate::ProgressBarDelegate( QObject* parent )
: QStyledItemDelegate(parent)
{
}
void ProgressBarDelegate::paint( QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (index.column() == 2)
{
int progressPercentage = index.model()->data(index, Qt::DisplayRole).toInt();
QStyleOptionProgressBarV2 progressBarOption;
progressBarOption.rect = QRect(option.rect.x(), option.rect.y() + 5 , option.rect.width(), option.rect.height() / 1.5);
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progressPercentage;
QPalette pal = progressBarOption.palette;
QColor col = QColor(35, 35,25);
pal.setColor(QPalette::Highlight, col); // or QPalette::Window doesnt matter
progressBarOption.palette = pal;
if(option.state & QStyle::State_Selected)
{
}
QApplication::style()->drawControl( QStyle::CE_ProgressBar,
&progressBarOption,
painter);
}
else
{
QStyledItemDelegate::paint(painter, option, index);
}
}
Currently, no matter what I do the color doesnt change from OSX standard light-gray.
Running OSX 10.6.7 and Qt 4.8.1 if that matters. thank you!
Edit:
I was able to do the following:
app.setStyleSheet("QScrollBar:horizontal { border: 2px solid green;background: cyan;height: 15px;margin: 0px 20px 0 20px;}");
But when I do this:
app.setStyleSheet("QProgressBar:horizontal { border: 1px solid gray; border-radius: 3px; background: white; padding: 1px; }");
NOTHING changes on the progressbar. I am in theory not creating any progressbar objects, im just settings a style how I'm viewing my data in my delegate. But surely, I cant be the first person who would want to do this right?
Also, if this doesnt work, how can I do this (having a styled progressbar) in a tableview?
You should use Qt Style Sheet, which allows us to customize UI of many controls to give unique look and feel across platforms. Check this.
Create a new simple Qt Gui project, open UI Form editor and add a Progress Bar control from under 'Display Widgets' in tool window. Now write following code in constructor of MainWindow..
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Customize progress-bar's style..
QString style = "QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center;}";
style += "QProgressBar::chunk {background-color: #CD96CD; width: 10px; margin: 0.5px;}";
// Assuming objectName is 'progressBar'..
ui->progressBar->setStyleSheet(style);
}
Compile and run.
If you just want to change that single QProgressBar control, then above method is sufficient, but if you want to apply styles at application level (say all QProgressBar controls and some other controls), then proper way is to create a *.css file, write styles using Qt Style Sheet Reference and then read that file in Qt and call
QApplication::setStyleSheet(QString style).
Besides, style sheet uses the same syntax as CSS and also supports various selectors.
Edit:
I agree that above method works only with controls and not delegates. I found something for delegates also. Try following paint function.
void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.column() == 2)
{
QProgressBar renderer;
int progressPercentage = index.model()->data(index, Qt::DisplayRole).toInt();
// Customize style using style-sheet..
QString style = "QProgressBar { border: 2px solid grey; border-radius: 5px; }";
style += "QProgressBar::chunk { background-color: #05B8CC; width: 20px; }";
renderer.resize(option.rect.size());
renderer.setMinimum(0);
renderer.setMaximum(100);
renderer.setValue(progressPercentage);
renderer.setStyleSheet(style);
painter->save();
painter->translate(option.rect.topLeft());
renderer.render(painter);
painter->restore();
}
else
QStyledItemDelegate::paint(painter, option, index);
}
So here the point is that instead of using QStyleOption, we can use directly the control itself as a renderer. Hope this helps..
Instead of pal.setColor(QPalette::Window, col);
Use pal.setColor(QPalette::Highlight, col);
This should work.
I used the code in Paintevent
void Dialog::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(ShowPrintDialog()));
QStyleOptionProgressBarV2 progressBarOption;
progressBarOption.rect = QRect(20,20,30,30);
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = 75;
QPalette pal = progressBarOption.palette;
QColor col = QColor(0,255,0);
pal.setColor(QPalette::Highlight, col);
progressBarOption.palette = pal;
QApplication::style()->drawControl(QStyle::CE_ProgressBar,&progressBarOption, &painter);
}
How/Can I change color of a frame in QLineEdit? What I've tried is this:
lineEdit->setStyleSheet("border: red");
and
lineEdit->setStyleSheet("border-color: red");
but it doesn't work.
lineEdit->setStyleSheet("border: 1px solid red");