I am trying to get the built in StandardPixmaps
to display on my layout.
So far I have managed to access a standard pixmap (PyQt4.QtGui.QStyle.SP_MessageBoxWarning), but seem unable to actually add this to my layout. I have tried adding it to a QLabel using the setPixmap method, but this requires a pixmap, not a standardPixmap.
I have found this answer on SO, which led me to the standardPixmaps, but I have been unable to make any more progress from here.
PyQt4.QtGui.QStyle.SP_MessageBoxWarning is an enumeration value not a pixmap.
In order to get a pixmap from it, you could give it to the standardPixmap method of the current used style.
Example:
from PyQt4 import QtGui
if __name__ == '__main__':
app = QtGui.QApplication([])
label = QtGui.QLabel()
label.setPixmap(app.style().standardPixmap(QtGui.QStyle.SP_MessageBoxWarning))
label.show()
app.exec_()
Unfortunately, the standardPixmap method is considered obsolete now. The Qt doc advises to use the standardIcon method which returns a QIcon.
If you still want to use a QLabel to display your icon, you have to build a QPixmap from the QIcon you get. You can use one of its pixmap methods for this:
from PyQt4 import QtGui
if __name__ == '__main__':
app = QtGui.QApplication([])
label = QtGui.QLabel()
icon = app.style().standardIcon(QtGui.QStyle.SP_MessageBoxWarning)
label.setPixmap(icon.pixmap(32))
label.show()
app.exec_()
Related
I am learning how to use PyQt5 and I came across this issue where "my first label" does not complete display on my screen.
Display after running the code:
Code:
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) #enable highdpi scaling
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) #use highdpi icons
def window():
app = QApplication(sys.argv)
win = QMainWindow()
win = QMainWindow()
win.setGeometry(200, 200, 400, 400)
win.setWindowTitle("Tech with Aeijan")
label = QtWidgets.QLabel(win)
label.setText("my first label!")
label.move(50,50)
win.show()
sys.exit(app.exec_())
window()
QLabel adapts its contents based on the (possible) parent layout manager, but you didn't use any, so it doesn't know how to correctly display itself or adapt its size to do that.
The simplest solution is to call label.adjustSize(), which will cause the label to resize itself so that it will be able to display its contents.
That wouldn't be a very good idea, though: you are trying to use a fixed position for a widget (which is normally considered a bad thing to do, for plenty of reasons); the result will be that if the label text is too big and the user resizes the window, the text won't be completely visible as it should be, nor the label would know how to resize or eventually wrap its contents to do ensure that all its text is shown.
The better approach is to use a layout manager, but that is a solution reserved for simpler widgets (like a QWidget or a QDialog); a QMainWindow doesn't work like that, and it requires a central widget to be set to ensure that its contents are correctly displayed and managed.
In your case, you could simply use self.setCentralWidget(label), but that would prevent you to add any other widget to your window.
A "container" widget should be used instead, and that widget would be set as the central one for the main window; then you can set a layout for that widget and add the label to it:
def window():
app = QApplication(sys.argv)
win = QMainWindow()
central = QWidget()
win.setCentralWidget(central)
layout = QVBoxLayout()
central.setLayout(layout)
# alternatively, the above is the same as this:
# layout = QVBoxLayout(central)
label = QtWidgets.QLabel(win)
label.setText("my first label!")
layout.addWidget(label)
# ...
I am trying to develop a small gui using PySide and the QT Creator.
As the base implementation, I have choosen a QMainWindow.
The problem is that adding any elements to that MainWindow inside the Editor results in an empty window when I run the code.
The initially generated python code looks like this:
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.load_ui()
def load_ui(self):
loader = QUiLoader()
path = os.path.join(os.path.dirname(__file__), "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self)
ui_file.close()
if __name__ == "__main__":
app = QApplication([])
widget = MainWindow()
widget.show()
sys.exit(app.exec_())
I know that loader.load(ui_file, self) returns a widget. My solution was:
def load_ui(self):
loader = QUiLoader()
path = os.path.join(os.path.dirname(__file__), "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
self.window = loader.load(ui_file, self)
self.window.show()
ui_file.close()
if __name__ == "__main__":
app = QApplication([])
widget = MainWindow()
#widget.show() <<<<<<--- removing this
sys.exit(app.exec_())
This works for me but this clearly cannot be the way this is supposed to work.
I am confused on why QT Creator gives me this non-working templaet.
Furthermore I am curious on how custom functions should be implemented.
When clicking on the clicked() slot for a button, it tells me
No ui_form.h found! (translated)
I ended up writing the functions into my MainWindow class like this:
self.window.menuopen_button.clicked.connect(lambda x: self.menu_animation(x))
self.window.minimise_button.clicked.connect(lambda x: self.menu_buttons('minimise'))
Your initial code only loads the UI file into the QUiLoader object - you don't do anything else with it. When you call widget.show(), you're calling the QMainWindow's show method which is a default window (and, hence, empty) since you haven't added the loaded widget to it.
Your solution similarly loads the UI but displays it via the widget object's show method. However, you're not amending it to your main window, so you're basically tossing your main window and just using the widget.
There are a couple ways to correctly accomplish what you want:
One way would be to, as #musicamante suggested, add the loaded UI widget to your MainWindow object (and by the way, this is supported by PySide2: https://doc.qt.io/archives/qtforpython-5.12/PySide2/QtUiTools/QUiLoader.html - the example in the detailed description shows exactly how to do this).
Or the other way, which I prefer, would be to use the uic utility, PySide2-uic, in the build process to generate a UI Python class based on the UI file.
The Qt documentation has tutorials showing both methods. The linked documentation shows PySide6 as support for PySide2 has been discontinued with the release of Qt6. The API for PySide2, PySide6, and PyQt5 are all very similar, so if you're migrating from either PySide2 or PyQt then the change should be relatively painless. I recommend using PySide6 as this is the Python binding officially supported by Qt.
I am learning how to use PyQt5 and I came across this issue where "my first label" does not complete display on my screen.
Display after running the code:
Code:
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) #enable highdpi scaling
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) #use highdpi icons
def window():
app = QApplication(sys.argv)
win = QMainWindow()
win = QMainWindow()
win.setGeometry(200, 200, 400, 400)
win.setWindowTitle("Tech with Aeijan")
label = QtWidgets.QLabel(win)
label.setText("my first label!")
label.move(50,50)
win.show()
sys.exit(app.exec_())
window()
QLabel adapts its contents based on the (possible) parent layout manager, but you didn't use any, so it doesn't know how to correctly display itself or adapt its size to do that.
The simplest solution is to call label.adjustSize(), which will cause the label to resize itself so that it will be able to display its contents.
That wouldn't be a very good idea, though: you are trying to use a fixed position for a widget (which is normally considered a bad thing to do, for plenty of reasons); the result will be that if the label text is too big and the user resizes the window, the text won't be completely visible as it should be, nor the label would know how to resize or eventually wrap its contents to do ensure that all its text is shown.
The better approach is to use a layout manager, but that is a solution reserved for simpler widgets (like a QWidget or a QDialog); a QMainWindow doesn't work like that, and it requires a central widget to be set to ensure that its contents are correctly displayed and managed.
In your case, you could simply use self.setCentralWidget(label), but that would prevent you to add any other widget to your window.
A "container" widget should be used instead, and that widget would be set as the central one for the main window; then you can set a layout for that widget and add the label to it:
def window():
app = QApplication(sys.argv)
win = QMainWindow()
central = QWidget()
win.setCentralWidget(central)
layout = QVBoxLayout()
central.setLayout(layout)
# alternatively, the above is the same as this:
# layout = QVBoxLayout(central)
label = QtWidgets.QLabel(win)
label.setText("my first label!")
layout.addWidget(label)
# ...
I'm trying to change the current color group fora QPalette, but it seems that the setCurrentColorGroup method of QPalette simply does not work.
I'm running this code:
app = QtGui.QApplication(sys.argv)
button = QPushButton()
svgWidget = QSvgWidget(resources_paths.getPathToIconFile("_playableLabels/42-labelPlay-disabled-c.svg"))
button.setLayout(QHBoxLayout())
button.layout().addWidget(svgWidget)
button.setFixedSize(QSize(300, 300))
print button.palette().currentColorGroup()
button.setEnabled(False)
print button.palette().currentColorGroup()
button.palette().setCurrentColorGroup(QPalette.ColorGroup.Normal)
print button.palette().currentColorGroup()
button.show()
print button.palette().currentColorGroup()
app.exec_()
This is the output I get:
PySide.QtGui.QPalette.ColorGroup.Normal
PySide.QtGui.QPalette.ColorGroup.Disabled
PySide.QtGui.QPalette.ColorGroup.Disabled
PySide.QtGui.QPalette.ColorGroup.Disabled
Process finished with exit code -1
So... It seems that setCurrentColorGroup does exactly nothing. Any ideas on how could I change the current color group?
Thanks in advance!
(BTW, I'm running PySide 1.2.4 with Qt 4.8 on a Windows 7 system)
It seems that you are trying to change the way icons are rendered, rather than the way widgets are painted, so the palette is not the right API to use. Instead, you should use a QIcon, which allows different images to be used for various modes and states.
To use the same image for both Normal and Disabled modes, you would use code like this:
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap('image.svg'), QtGui.QIcon.Normal)
icon.addPixmap(QtGui.QPixmap('image.svg'), QtGui.QIcon.Disabled)
button = QtGui.QPushButton()
button.setIcon(icon)
However, you should take careful note of this warning from the Qt docs:
Custom icon engines are free to ignore additionally added pixmaps.
So there is no guarantee that this will work with all widget styles on all platforms.
UPDATE:
If the above method doesn't work, it probably means the widget style is controlling how disabled icons are rendered. The relevant QStyle API is generatedIconPixmap, which returns a copy of the pixmap modified according to the icon mode and style options. It seems that this method may sometimes also take the palette into account (somewhat contrary to what I stated above) - but when I tested this, it did not have any affect. I reset the palette like this:
palette = self.button.palette()
palette.setCurrentColorGroup(QtGui.QPalette.Normal)
palette.setColorGroup(QtGui.QPalette.Disabled,
palette.windowText(), palette.button(),
palette.light(), palette.dark(), palette.mid(),
palette.text(), palette.brightText(),
palette.base(), palette.window(),
)
button.setPalette(palette)
which made the colours look normal when the button was disabled - but the icon was still greyed out. Still, you might want to try it in case things work differently on your platform (don't be surprised if they don't).
It seems that the correct way to control the disabling of icons is to create a QProxyStyle and override the generatedIconPixmap method. Unfortunately, this class is not available in PyQt4, but I have tested it in PyQt5, and it works. So the only working solution I have at the moment is to upgrade to PyQt5, and use QProxyStyle. Here is a demo script that shows how to implement it:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class ProxyStyle(QtWidgets.QProxyStyle):
def generatedIconPixmap(self, mode, pixmap, option):
if mode == QtGui.QIcon.Disabled:
mode = QtGui.QIcon.Normal
return super(ProxyStyle, self).generatedIconPixmap(
mode, pixmap, option)
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.button = QtWidgets.QPushButton(self)
self.button.setIcon(QtGui.QIcon('image.svg'))
self.button2 = QtWidgets.QPushButton('Test', self)
self.button2.setCheckable(True)
self.button2.clicked.connect(self.button.setDisabled)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
layout.addWidget(self.button2)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyle(ProxyStyle())
window = Window()
window.setGeometry(600, 100, 300, 200)
window.show()
sys.exit(app.exec_())
This is on PyQt4, Linux and Python 2.5
Can I make PyQt set my window "always on top" over other applications?
For example, in GTK i use the property: Modal.
Now, in PyQt I am using a QWidget, but, I can't find a way to do that.
Any ideas??
Pass the QMainWindow the WindowStaysOnTopHint window flag (or use setWindowFlags).
As in the name, this is a hint to the windowing manager (not a hard guarantee).
Simplest possible example:
import sys
from PyQt4 import QtGui, QtCore
class mymainwindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self, None, QtCore.Qt.WindowStaysOnTopHint)
app = QtGui.QApplication(sys.argv)
mywindow = mymainwindow()
mywindow.show()
app.exec_()
setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
setwindowaFlags is a method that can call it from form object and just take one parameter is a constant QtCore.Qt.WindowStaysOnTopHint that refer to make your form Stays On Top