0

I had an application that contained a lot of widgets with stylesheet on them, However, I did not add any layout to interface, It neither had central widget included, But the application was running without any problems.

However, whenever i tried to resize the application (scaling it down) the widgets would not scale, of course.

I had an little research (Because i could not find anything else related to my problem) and i found this on Qt Documentation, stylesheet reference:

"The actual image that is drawn is determined using the same algorithm as QIcon (i.e) the image is never scaled up but always scaled down if necessary."

How can i make stylesheet scale down with window? (If stylesheet has background image on)


For example i have button with stylesheet:

btn = QtGui.QPushButton(self)
btn.move(0, 0)
btn.setObjectName('btn)
btn.setStyleSheet("#btn {background-image: url(':/images/somepicture.png'); border: none; }")

How can i make this button scale down with window, Can i achieve this without layouts? If not how can i do it with layouts? (without it limiting too much)

ShellRox
  • 2,532
  • 6
  • 42
  • 90
  • can you include a screenshot of how it currently looks? "It neither had central widget included" makes no sense. Or did you not have a `QMainWindow` at all? – mfitzp May 21 '16 at 22:32
  • It works fine, i even freezed it to executable and worked, i didn't assign central widget my own, Yes it has QMainWindow, i also noticed that whenever i tried to add layout, it gave this warning: Attempting to add QLayout "" to Window "", which already has a layout. @mfitzp – ShellRox May 22 '16 at 05:31

1 Answers1

1

If you add the button as the central widget to a QMainWindow it should automatically adjust it's size to fit the available space. However, to get the button image to scale, you need to set the image as a border-image stylesheet property (a little strange). A working example for PyQt4:

from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        btn = QtGui.QPushButton(self)
        btn.setStyleSheet("border-image: url('somepicture.png');")  # Scaled
        #btn.setStyleSheet("background-image: url('somepicture.png');")  # Not scaled

        self.setCentralWidget(btn)

        self.show()

app = QtGui.QApplication([])
window = MainWindow()

app.exec_()

Note that you don't need to set an id (objectName) to assign the CSS to a specific widget, you can simply pass in the CSS rule via .setStyleSheet().

You cannot set a layout on QMainWindow as it already has a complex layout system to accommodate docking widgets and toolbars. Therefore, if you want to use a layout to add more than one widget to the window, you need to use a container widget to hold it. The following working example demonstrates this:

from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        w = QtGui.QWidget() # container widget
        l = QtGui.QVBoxLayout() # your layout
        w.setLayout(l) # set the layout on your container widget

        btn = QtGui.QPushButton(self)
        btn.setStyleSheet("border-image: url('somepicture.png');")      

        label = QtGui.QLabel('Hello!')

        l.addWidget(btn) # add your widget to the layout
        l.addWidget(label) # add the label to the layout

        self.setCentralWidget(w) # add the container widget to the QMainWindow        

        self.show()

app = QtGui.QApplication([])
window = MainWindow()

app.exec_()

If you want to be able to position widgets absolutely, rather than adding them to a layout (which will control their size/position) you can pass the parent element (relative to which x,y coords are taken) when creating it:

from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        w = QtGui.QWidget() # container widget

        btn = QtGui.QPushButton(w)
        btn.move(100,100)
        btn.setStyleSheet("border-image: url('somepicture.png');")      

        self.setCentralWidget(w) # add the container widget to the QMainWindow        
        self.show()

app = QtGui.QApplication([])
window = MainWindow()

app.exec_()

But positioning a widget absolutely like this loses you the ability to auto-scale it to fit the parent widget. If you just want some padding/spacing around the element in the window, take a look at .setContentsMargins on the QLayouts, e.g. l.setContentsMargins(50,50,50,50) will put a 50px margin around the button.

mfitzp
  • 15,275
  • 7
  • 50
  • 70
  • Thanks a lot @mfitzp Both worked very nice, also i would appreciate answer, Is there any layout so i can freely move widgets horizontally and vertically, as an example, whenever i did `btn.move(200, 200)` it would move without limits, but, here it can't, I've heard of GridLayout, can it work on scaled mode?, Do i need to add rows to them? | | also i am getting this warning when trying second code: `QLayout: Attempting to add QLayout "" to MainWindow "", which already has a layout` – ShellRox May 22 '16 at 15:47
  • 1
    @ShellRox I've updated the second code to a full working example. For absolute positioning you need to create the widget without a layout, but with the parent widget as parent, e.g. `QtGui.QPushButton(w)` see the additional code. – mfitzp May 22 '16 at 16:02
  • Thanks again, i have these final questions: How can i move widgets at all in GridLayout, so i can put multiple widgets on window, So for instance i have two buttons, how can i put one in left border of window and second to the right. Also how can i set max scaling of button to its original size? so it can scale down only. – ShellRox May 22 '16 at 16:53
  • Fixed both ones, sorry for being too annoying @mfitzp, This is final question overall, For example i have a background image (Label with pixmap), How can i make it scalable with layout? – ShellRox May 22 '16 at 17:47
  • 1
    @ShellRox as that is a different thing (Label + Pixmap) it would be better posted as a separate question. But take a look at this http://stackoverflow.com/a/10915341/754456 – mfitzp May 24 '16 at 08:23
  • Sorry for late respond, fixed it by adding border image to layout itself, thanks for help! – ShellRox May 24 '16 at 08:36