I'm little confusing meaning of widgets instance creation in PyQt.
Seems QWidget(self) can create a widget.
But what's the meaning of QWidget(instance name)?
For exmaple,
grid_layout = QGridLayout(self)
test_label = QWidget(grid_layout)
I know test_label created inherited from gridlayout.
But what's the meaning during program meaning?
Is that meaning test_label widget is under grid_layout?
For many of the widgets when the signature is just a single parameter like in both of your examples, the argument given sets the created widget/layouts parent.
So in your first example, using self as the argument means that the parent of the QGridLayout and the widget that the layout will be applied to is whatever widget self is.
In the second example you are setting the parent of QWidget to be the widget represented by it's argument. A QWidget with no parent becomes a new window, when set with a parent then the widget becomes a child window within the parent widget.
Neither one are inheriting anything. Inheritance only occurs during Subclassing.
Related
I wanted to ask if we could just animate the fontsize of the QLabel in PyQt5 with QPropertyAnimation.
I tried by adding QPropertyAnimation(self.label , b"fontSize") but It was not working and I got the warning
I want you increase the text of the QLabel and then again switch to normal size
From the QPropertyAnimation description:
QPropertyAnimation interpolates over Qt properties. As property values are stored in QVariants, the class inherits QVariantAnimation, and supports animation of the same meta types as its super class.
A class declaring properties must be a QObject. To make it possible to animate a property, it must provide a setter (so that QPropertyAnimation can set the property's value).
All classes that inherit from QObject (including widgets) support Qt properties, and in fact most of them have "builtin" properties, but, obviously, not all properties support animations: they must be based on numeric values. You can animate a numeric change (eg: from 0 to 100), not a text (eg. from 'ABC' to 'PYZ').
For instance, all QWidget have a pos property, and since such property (which is a QPoint) is based on numbers, you can create an animation. You can see the list of supported variant types for animations in the QVariantAnimation docs. Consider that all documentation pages regarding QObject subclasses contain a property section (see the QWidget properties for example), and that properties obviously are inherited from their super classes.
There is no property for the font size, though, so there are two possibilities:
create a custom property (by using the pyqtProperty decorator in PyQt);
use a QVariantAnimation, which is not bound to any property;
Depending on the situation, one might prefer one approach or the other, but for this specific case it doesn't change that much; the QVariantAnimation is certainly simpler, the Qt property approach is more "compliant".
Here you can see how the property is created using the pyqtProperty decorator. Since the animation writes the property, having a setter is mandatory.
class AnimationTest(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.startButton = QtWidgets.QPushButton('Start')
self.label = QtWidgets.QLabel('Hello!')
self.labelFont = self.font()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.startButton)
layout.addWidget(self.label)
self.ani = QtCore.QPropertyAnimation(self, b'labelFontSize')
self.ani.setStartValue(10)
self.ani.setEndValue(80)
self.ani.setDuration(1500)
self.startButton.clicked.connect(self.ani.start)
#QtCore.pyqtProperty(int)
def labelFontSize(self):
return self.labelFont.pointSize()
#labelFontSize.setter
def labelFontSize(self, size):
self.labelFont.setPointSize(size)
self.label.setFont(self.labelFont)
import sys
app = QtWidgets.QApplication(sys.argv)
test = AnimationTest()
test.show()
sys.exit(app.exec_())
The variant animation is certainly shorter:
class AnimationTest(QtWidgets.QWidget):
def __init__(self):
# ...
self.ani = QtCore.QVariantAnimation()
self.ani.setStartValue(10)
self.ani.setEndValue(80)
self.ani.setDuration(1500)
self.ani.valueChanged.connect(self.updateLabelFont)
self.startButton.clicked.connect(self.ani.start)
def updateLabelFont(self, value):
self.labelFont.setPointSize(value)
self.label.setFont(self.labelFont)
Please consider that font size animations are often problematic, as most fonts have slightly different glyphs and spacings depending on the size. In the examples above I used a pretty long animation that will probably show the effect: while the size increases linearly, the change in the font usually is not very smooth.
I understand that QLabel attributes such as frameGeometry, pixmap and text can be recovered using their respective commands. But is it possible to get the value of "frame shadow" around each of these label widgets?
I have 3 Labels placed inside a Frame (inside a Window) using qt-designer. I assigned shadows for each of these labels by calling self.label_1.setFrameShadow(QFrame.Raised) or self.label_1.setFrameShadow(QFrame.Plain) within the QMainWindow class.
Now I wish to update their shadow attributes after checking to see if one of them is Raised or Plain. The error says that: 'QLabel' object has no attribute 'FrameShadow'. But why so if I was able to set it?
QLabel inherits from QFrame and therefore has an accessor frameShadow() for that property.
Unlike in other frameworks, Qt accessors don't start with get...
First, a heads up - I am not too familiar with OOP concepts, so this may just be some form of python functionality that I am not aware of.
In Kivy we can modify the behaviour and appearance of widgets by creating classes child to the widgets whose functions we want to alter, for instance:
class MyWidget(Button):
def __init__(self, **kwargs):
super(MyWidget, self).__init__(**kwargs)
self.size_hint = None
self.size = 200, 100
Then use MyWidget: or <MyWidget> to instantiate the widget in kv. This is good if I wish for my widgets to be parent to the root widget, but there are times when this is not wanted for instance when requiring a temporary Popup.
In which case I would just create a typical class which is instantiated when an event is triggered. Like so:
class Interface():
def __init__(self):
btn = Button()
btn.bind(on_press=self.some_callback)
self.popup = Popup(content=btn)
self.popup.open()
def some_callback(self, instance):
print('woo')
And this, to all appearances, looks fine, but the widget events (on_press here) don't trigger callback functions??? The bind() function will call the callback on the event, since I will be notified if the callback function definition has incorrect syntax, but for some reason the contents of the callback are not executed - only when Interface() inherits from the Widget() class (Interface(Widget): ...).
From the docs:
Widget interaction is built on top of events that occur. If a property changes, the widget can respond to the change in the ‘on_’ callback. If nothing changes, nothing will be done.
btn is the widget, it is instance of Button() which itself is a child of Widget, its method has no connection at all to what may be the parent class of Interface so why then is the callback only fully executed when Widget is the parent class of Interface? What am I missing?
I am trying to display a QGraphicsView inside a QGraphicsWidget, but I can't seem to get it to work.
This is what I want to achieve, where the QGraphicsWidgets are all added to a QGraphicsScene, and each widget has their own QGraphicsScene and QGraphicsView.
The large box represents the main view, and the smaller boxes represent widgets, each with their own view and scenes.
My current implementation doesn't work, due to the following error:
TypeError: QGraphicsLinearLayout.addItem(QGraphicsLayoutItem):
argument 1 has unexpected type 'QGraphicsView'
My implemetation in a subclass of the QGraphicsWidget:
self.scene = QtGui.QGraphicsScene(self)
self.view = QtGui.QGraphicsView(self.scene)
self.view.setRenderHint(QtGui.QPainter.Antialiasing)
self.setLayout(QtGui.QGraphicsLinearLayout(Qt.Vertical))
self.layout().addItem(self.view)
I've tried to implement this with a QGraphicsLayoutItem, but I couldn't find anywhere to stick the QGraphicsView in.
Any help would be appreciated.
The function QGraphicsLinearLayout.addItem expects a QGraphicsWidget parameter and you are passing a normal QWidget (QGraphicsView).
You can use the class QGraphicsProxyWidget which is specially designed for wrapping QWidget into QGraphicsWidget.
I do not have Qt + Python on hands but I think it should look as follows:
proxy = parentView.addWidget(nestedView) # QWidget -> QGraphicsWidget
self.layout().addItem(proxy)
How can I make a childWindow access and/or modify an attribute from his MainWindow?
I have a MainWindow that opens different childWindows, dependeing on the pressed button on the MainWindow.
I would like any of the childWindows to be able to modify some attributes of the MainWindow, but I cannot get the good way to access them.
When defining your widget or window (your window is possibly just a QWidget), specify it's parent in the init-Method (just pass the parent-widget).
After that, you could use the parentWdiget-Method or simply set a "link" to the parent-widget in an attribute of the child-window.
See http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html
You could pass a reference (self) to your childwindow.