QTabBar scrollbar separation - c++

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.)

Related

How to create a QTextEdit with space for a caption in the border?

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 :

QWidget's background applied to all its QWidget children

I chose to use Qt to manage the GUI of a project I am working on.
After finding how to apply a picture at the bottom of my QWidget, I noticed that it has an impact on all the components that are added to it.
Whatever the style applied through the setStyleSheet method or even with a QPixmap, the background of these elements is always the image defined for the QWidget container.
How can I avoid this behavior ?
Here is my code :
MainMenu::MainMenu(QWidget* Parent, const QPoint& Position, const QSize& Size) : QWidget(Parent) {
QString qwidgetStyle = "QWidget {background-image: url(background.jpg); border: 5px solid rgba(3, 5, 28, 1);}";
QString buttonStyle = "color: rgba(73, 123, 176, 1); font-size:30px; background-color: rgba(73, 123, 176, 1);";
move(Position);
resize(Size);
setStyleSheet(qwidgetStyle);
// Menu title
QLabel *title = new QLabel(this);
title->setText("Menu");
title->setStyleSheet(buttonStyle);
title->setAlignment(Qt::AlignCenter);
// Menu buttons
// Play
buttonPlay = new QPushButton("Play");
(*buttonPlay).setEnabled(true);
(*buttonPlay).setStyleSheet(buttonStyle);
connect(buttonPlay, SIGNAL(clicked()), this, SLOT(handleButton()));
// Option
buttonOptions = new QPushButton("Options", this);
(*buttonOptions).setEnabled(true);
(*buttonOptions).setGeometry(250, 175, 100, 50);
(*buttonOptions).setStyleSheet(buttonStyle);
connect(buttonOptions, SIGNAL(clicked()), this, SLOT(handleButton()));
// Quit
buttonQuit = new QPushButton("Quit", this);
(*buttonQuit).setEnabled(true);
(*buttonQuit).setGeometry(250, 275, 100, 50);
(*buttonQuit).setStyleSheet(buttonStyle);
connect(buttonQuit, SIGNAL(clicked()), this, SLOT(handleButton()));
// Layout
QGridLayout *layout = new QGridLayout;
layout->setMargin(50);
layout->addWidget(title, 0, 0, 1, 5);
layout->addWidget(buttonPlay, 3, 1, 2, 3);
layout->addWidget(buttonOptions, 4, 1, 2, 3);
layout->addWidget(buttonQuit, 5, 1, 2, 3);
setLayout(layout);
show();
}
The behavior you encountered is perfectly normal, because of the following lines :
QString qwidgetStyle = "QWidget {background-image: url(background.jpg); border: 5px solid rgba(3, 5, 28, 1);}";
...
setStyleSheet(qwidgetStyle);
Here, you just told Qt to apply qwidgetstyle to every QWidget of your application, with the keyword QWidget. That's why in Qt, you better set a name to your object if you want to apply a style to this particular object.
In your code, QLabel and QPushButton both inherit from QWidget, so they will have the style you defined for a QWidget, unless you name them or you specify the style for each one.
If you want to set style sheet for your MainMenu which inherits directly from QWidget (which is what you are doing in the first place), you have to set a name, and then apply the style :
setObjectName("MainMenu");
QString qwidgetStyle = "QWidget#MainMenu {background-image: url(background.jpg); border: 5px solid rgba(3, 5, 28, 1);}";
setStyleSheet(qwidgetStyle); // here, only your MainMenu will have the style "qwidgetstyle"
Notice that you can, for example, set the same style sheet for every QWidget, and only add a particular color for your MainMenu :
// this is in a CSS, but you can apply it directly from the MainMenu constructor of course
QWidget, QWidget#MainMenu {
background-image: url(background.jpg);
border: 5px solid rgba(3, 5, 28, 1);
} // aplied to all QWidget
QWidget#MainMenu {
color : #9b9b9b; // a nice grey, only applied to MainMenu
}
Again, be specific when using style sheets or you will end up having strange colors/alignments everywhere in your application :). Hope that helps!
NB : you can also thank #PaulRooney who gave a very good link in the comments.

Qt Balloon Window from QFrame

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();

Changing QCheckBox text color

I found the same question there:
how to change QCheckBox text label color in Qt?
But unfortunately, none of it work for me on a mac.
On Linux and Windows, by default the text of a QWidget (QLabel, QCheckBox, QRadioButton) is white.
On the mac, it's black. Unfortunately this cause issues in my screen as the text is unreadable (I have black background)..
I have derived the QCheckBox class so in the constructor you get:
class MPUBLIC MythCheckBox: public QCheckBox
{
Q_OBJECT
public:
MythCheckBox(QWidget *parent = 0, const char *name = "MythCheckBox")
: QCheckBox(parent)
{
setObjectName(name);
#ifdef Q_OS_MAC
// setStyleSheet("QCheckBox { color : white; }; QCheckBox::indicator { color:black; }");
QPalette p = palette();
p.setColor(QPalette::WindowText, Qt::white);
setPalette(p);
#endif
};
If I use stylesheets like:
setStyleSheet("QCheckBox { color : white; }; QCheckBox::indicator { color:black; }");
then my text is white as I want, but the checkmark itself becomes invisible...
If I use the 2nd method:
QPalette p = palette();
p.setColor(QPalette::WindowText, Qt::white);
setPalette(p);
The checkbox text does become white, and the checkmark itself is still black, it looks like it works.
But if I ever move the focus to the QCheckBox, the text becomes black again, and it will remain black forever.
I tried also:
QPalette p = palette();
p.setColor(QPalette::Active, QPalette::WindowText, Qt::white);
p.setColor(QPalette::Inactive, QPalette::WindowText, Qt::white);
setPalette(p);
Mind you, I only get this weird behavior on the mac; if I try the same code in Linux (with different colors like red), then everything behaves like I want it to.
Any ideas on how to change the color of a QCheckBox's text, and only the text?
For some widgets you have to disable a native look (appearance). For example QPushButton (http://doc.qt.io/qt-4.8/stylesheet-reference.html). So, for checkbox you can try to set borders. So checkbox's style looks like:
QCheckBox {
border: none;
color: white;
}
Works for me.

QPushButton with an alpha level of 0% turns solid when moused over. How to fix Qt with C++ (with stylesheets?)

I have designed two different kinds of QPushButtons in Qt Designer. One is the default, the other I want to be clear.
In QT Designer I set the latter's initial style sheet like such:
background-color: rgba( 35, 35, 35, 0% );
I want the button to have a border and to be clear (the internal color isn't really important; that just happens to match the color scheme). When I mouse over the button I want it to REMAIN clear, however instead it turns to the solid grey that is 35/35/35.
When the button receives a signal press I want it to turn a half transparent green:
background-color: rgba( 0, 255, 0, 50% );
Before I realized the mouse-over would be a problem, I had this coded:
QString MyPanel::FillInvisibleButton(bool activeButton)
{
QString invisibleButton;
if (activeButton) {
invisibleButton = "QPushButton{background-color: rgba(0, 255, 0, 50%);}";
} else {
invisibleButton = "QPushButton{background-color: rgba(35, 35, 35, 0%);}";
}
return invisibleButton;
}
//Signals
void MyPanel::MyButtonPressed()
{
m_ui->myButton->setStyleSheet(FillInvisibleButton(true));
}
void MyPanel::MyButtonReleased()
{
m_ui->myButton->setStyleSheet(FillInvisibleButton(false));
}
That works great as far as making the clear button a transparent green when it's pressed... but it has the big grey opaque block on it when it's moused over which I want to go away!
I've tried this:
QString MyPanel::FillInvisibleButton(bool activeButton)
{
QString invisibleButton;
if (activeButton) {
invisibleButton = "QPushButton{background-color: rgba(0, 255, 0, 50%);} QPushButton:hover{background-color: rgba(35, 35, 35, 0%);}";
} else {
invisibleButton = "QPushButton{background-color: rgba(35, 35, 35, 0%);} QPushButton:hover{background-color: rgba(35, 35, 35, 0%);}";
}
return invisibleButton;
}
And it doesn't work at all. They still mouse-over grey and now they don't turn green at all.
Is my syntax just wrong? Or?? I'm new to Qt and very rusty on C++.
I'm not married to the Stylesheets. If there's a better way to accomplish it that's great. Just keep in mind that I can't do this to ALL of my buttons; just several of them.
Thanks!
ETA: I believe I'm using 4.5.0
You don't need to use signals, stylesheet is enough.
Try this one:
QPushButton {
background-color: rgba( 35, 35, 35, 0% );
border: 1px solid black;
}
QPushButton:pressed {
background-color: rgba( 0, 255, 0, 50% );
}
In your stylesheet you can use 'hover' pseudo state:
button->setStyleSheet("QPushButton:hover { ... }");