QT: Complex Layout and seamless window background image - qt

With some help from you QT sages, I was able to implement this window, with the desired layout and resizeability behavior. Now I have another interesting problem.
I want my entire window to have a "repeat-xy" seamless pattern. If I apply it to a simple window without layout and internal widgets, it works perfectly. I do however, now have a "tree" of widgets within widgets, and I can't set the stylesheet to draw my seamless background image to each and every one, cause it looks unnatural. The image must be underlying to all the widget topology I have. The problem is, it's invisible when i apply it to the bottom all-window-covering widget because it has widgets on top of it.
Is there a solution? maybe "transparent widgets" that can contain visible widgets?

I made the following using only CSS, there's a QPlainTextEdit, two QPushButton and a QLineEdit. In the image i added a red border to the QPlainTextEdit only so it can be seen, the rules are the following
QWidget#Form{
background-image: url(:/img/elephant_pattern.gif);
}
QPlainTextEdit{
background:transparent;
border:1px solid red;
}
As you can see all i had to was setting background transparent in the widgets i wanted.

Write your own widget that inherits QWidget. Reimplement the paintEvent and leave it empty. The widget itself won't be drawn, but its children will be.
my_widget::my_widget( QWidget* parent ) : QWidget( parent )
{
}
void my_widget::paintEvent( QPaintEvent* p_event )
{
// left empty to let my_widget be invisible
}
test_mw::test_mw( QWidget *parent ) : QMainWindow( parent )
{
test_widget = new my_widget( this );
QHBoxLayout* layout = new QHBoxLayout();
QPushButton* button0 = new QPushButton( "Button 0", 0 );
QPushButton* button1 = new QPushButton( "Button 1", 0 );
layout->addWidget( button0 );
layout->addWidget( widget );
test_widget->setLayout( layout );
setCentralWidget( test_widget );
}
Although the paintEvent of my_widget is empty, both QPushButtons are drawn. :-)

There was a QWidget::setBackgroundOrigin() method in earlier versions of Qt.
It's all done with styles now. See the examples http://doc.qt.nokia.com/latest/widgets-styles.html

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.

How to make a free space around a Frameless QWidget?

I have made a custom Window in Qt and now facing to resizing problem.
I want a free space around my QWidget (Qt::FramelessWindowHint) so i can process the Mouse Hover+Leave+press+release events in that area and in this events i change the cursor shape and resizing the widget.
(I don't want mouseEvent for widget but for that space)
How could i get such area ?
I suppose your QWidget is added to a QLayout at some point. Then just ask the containing QLayout to reserve some free space around it's content by calling [setContentsMargins].
Example, you had:
QWidget* widget = new QWidget( parent );
parent->layout()->addWidget( widget );
Then, just add:
parent->layout()->setContentsMargins( 100,100,100,100 );
This will guarantee that widget has 100 pixels of empty area around it.
To be more generic, and it case you had no parent, you can create an intermediate QWidget like that:
You had:
QWidget* myWidget = new QWidget( NULL );
widget->show();
Just do:
QWidget* parentWithEmptySpaceBorder = new QWidget( NULL );
parentWithEmptySpaceBorder->setLayout( new QVBoxLayout() );
parentWithEmptySpaceBorder->layout()->setContentsMargins( 100,100,100,100 );
QWidget* myWidget = new QWidget( NULL );
parentWithEmptySpaceBorder->layout()->addWidget( myWidget );
parentWithEmptySpaceBorder->show();

Qt: Resizing QMenuBar corner widget

I put a push button into the top-right corner of my main window menu bar:
QPushButton *pb = new QPushButton("Text");
pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
QMainWindow *mainWindow;
mainWindow->menuBar()->setCornerWidget(pb, Qt::TopRightCorner);
The initial layout is fine. Sometime later, an asynchronous event changes the QPushButton's text to a longer string, but it gets clipped on the right.
I can see that the QPushButton's size changes when the string is updated. The QPushButton is displayed correctly if the window is resized. The problem appears to be getting the QMenuBar to recognize that the widget's size has changed.
This answer How to auto change QPushButton width and QMenuBar corner widget width when change text of button? suggests resetting the corner widget. I would rather avoid that, because my application's structure makes me jump through several ugly and awkward hoops to reset the corner widget after initializing.
The solution is simple. After updating the text of the button call menuBar()->adjustSize(); I have tested it in Qt5.5 and hope it will work for you.
You can use QWidgetAction as a horizontal menu widget:
class TestMenu : public QWidgetAction
{
public:
TestMenu(QObject *parent) :
QWidgetAction (parent)
{
}
virtual QWidget *createWidget(QWidget *parent)
{
QComboBox *combo = new QComboBox(parent);
combo->setFixedWidth(300);
return combo;
}
virtual void deleteWidget(QWidget *widget)
{
delete widget;
}
};
...
QMenu *menu = new QMenu();
menu->addAction(new TestMenu(this));
menuBar()->setCornerWidget(menu);

Find border image of QMainWindow programmatically

I set a border image on my QMainWindow using a style sheet:
QMainWindow
{
border-image: url(:/metal_background);
}
In my program, there are several widgets with transparent background colors that sit on top of the main window. However when I drag and drop them, they look bad because they end up taking the system background color.
What I would like to do is get the brush(?) used to draw the mainwindow background, and use it to paint the child widget while it's being moved. I've tried:
QWidget* widget;
QMainWindow* mainWindow;
QList<QWidget*> widgets = qApp->topLevelWidgets();
foreach(widget, widgets)
{
if(widget->objectName() == "mainWindow") // name is OK
break;
}
mainWindow = static_cast<QMainWindow*>(widget);
qDebug() << mainWindow->objectName();
QPalette palette;
palette.setBrush(this->backgroundRole(),
mainWindow->palette().brush(mainWindow->backgroundRole()));
this->setPalette(palette);
this->repaint();
but it gives the background color/gradient, not the image. Am I doing something wrong, or is there another/better way to get the image?

How to display fix banner between QMenubar and QToolBar in QMainWindow

How can I show fixed banner (with some widget like label and button ) in between
QMenuBar and QToolBar ?
Similarly like QStatusBar but in between QMenuBar and QToolBar.
I tried to implement using QToolBar.
// toolbar Banner with lable inside it.
QLabel * bannerLabel = new QLabel(" bannerToobar with label banner.");
bannerLabel->setAlignment( Qt::AlignVCenter );
ui.bannerToobar->addWidget( bannerLabel );
ui.bannerToobar->setAllowedAreas(Qt::ToolBarArea::TopToolBarArea);
ui.bannerToobar->setMovable( false );
QSize banner_sz = ui.bannerToobar->size();
ui.bannerToobar->setFixedHeight( banner_sz.height() * 2 );
QSizePolicy banner_szPolicy( QSizePolicy::Policy::Maximum, QSizePolicy::Policy::Fixed );
banner_szPolicy.setHorizontalStretch(255);
ui.bannerToobar->setSizePolicy( banner_szPolicy );
but i can't prevent user from draging mainToolbar and droping in the same row as my
bannerToolbar
You can force it to wrap initially using QMainWindow::addToolBarBreak, but I don't know a way to prevent it from being put back there later by the user (except for making the toolbars non-moveable).
If there was a QToolbar::dockLocationChanged signal (which seems to have been requsted and resolved in https://bugreports.qt-project.org/browse/QTBUG-1274, but I still don't see the signal anywhere), I suppose you could use insertToolBarBreak to fix it up whenever things have changed. Maybe there's some hackish way you could get notified when the toolbars move.
Or you could use QMainWindow::setMenuWidget to place a widget containing both your QMenuBar and something else into the menu area of the QMainWindow. This could get tricky if you want to support styles (mac/gnome/etc) where the menubar gets lifted out of your window to the top-of-screen and the toolbar gets unified with the window title decorations. But the idea of a banner between menubar and toolbar just naturally has problems in such cases :-)

Resources