I am coding a GUI in PyQt5, where I need a color picker.
So far, I use the QColorDialog Class, which works fine for selecting a color - but my problem is that there seems to be no way to select "no color" (or "no fill", like its known from PowerPoint or Adobe Illustrator).
How to achieve to select "no color"? (The documentation only mentions a flag for transparency, but this is not helpful for me...)
If you don't mind using a non-native dialog, it is quite easy to customize it.
Below is a very basic implementation that shows how to embed the existing dialog, and add an extra "No Color" button at the bottom. The rest of the implementation is left as an exercise for the reader...
from PyQt5 import QtCore, QtWidgets
class ColorDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent)
widget = QtWidgets.QColorDialog()
widget.setWindowFlags(QtCore.Qt.Widget)
widget.setOptions(
QtWidgets.QColorDialog.DontUseNativeDialog |
QtWidgets.QColorDialog.NoButtons)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(widget)
hbox = QtWidgets.QHBoxLayout()
hbox.addWidget(QtWidgets.QPushButton('No Color'))
hbox.addWidget(QtWidgets.QPushButton('Cancel'))
hbox.addWidget(QtWidgets.QPushButton('Ok'))
layout.addLayout(hbox)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
dialog = ColorDialog()
dialog.show()
sys.exit(app.exec_())
Related
I want a combobox with width adjusted to its (longest) content, so I use AdjustToContents. However, at least with my settings and the Oxygen style, I sometimes get a too short box and the contents are clipped. This seems to happen especially with digits:
Note that the 8 at the end is clipped. If I comment out that item, the length looks ok.
Is it a bug? Is there an easy way to fix it maybe with stylesheets or subclassing?
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
class HelloWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("Test")
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
gridLayout = QHBoxLayout()
centralWidget.setLayout(gridLayout)
label = QLabel("Name")
combobox = QComboBox()
combobox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
combobox.addItem("Short")
combobox.addItem("Longer text")
combobox.addItem("abcdefghijklmnopqr")
combobox.addItem("123456789012345678")
gridLayout.addWidget(label)
gridLayout.addWidget(combobox)
gridLayout.addStretch(1)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = HelloWindow()
mainWin.show()
sys.exit( app.exec_() )
try:
combobox = QComboBox(self)
It seems I found the culprit. I had the "Force fonts DPI" option in KDE fonts settings enabled and set to 96 (while xdpyinfo | grep resolution says 101 dpi). Disabling the option makes it work fine with all styles I have available (Breeze, Oxygen, Windows, Fusion).
Now, is this a KDE bug, a Qt bug or just a limitation?
Disclaimer: New to both python and qt designer
QT Designer 4.8.7
Python 3.4
PyCharm 5.0.3
Question - How do I add controls to the main form or a scroll area widget on the main form (created in QT Designer) programmatically?
I have created a MainWindow in qt designer and added my widgets. The following is the entire test program in PyCharm:
import sys
from PyQt4 import QtGui, QtCore, uic
from PyQt4.QtGui import *
from PyQt4.QtCore import *
qtCreatorFile = "programLauncher.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class MyApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
# Cannot resize or maximize
self.setFixedSize(1045, 770)
# Add button test
self.dateLabel = QtGui.QLabel("Test")
self.pushButton = QtGui.QPushButton('Test button')
# self.scrollArea_programs.addWidget()
grid = QtGui.QGridLayout()
# self.scrollArea_programs.addWidget(self.pushButton)
grid.addWidget(self.dateLabel,0,0)
grid.addWidget(self.pushButton,0,1)
self.setLayout(grid)
self.pushButton_exit.clicked.connect(self.closeEvent)
def closeEvent(self):
QtGui.QApplication.quit()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
As you can see I tried to add controls to a grid but nothing shows up when the program runs - I have also tried to add a control to the scroll area. Can someone help me to just add 1 control to the scroll area at run time - so then I can know the proper way to do it or "a" proper way to do this.
Thanks in advance
Without having access to your programLauncher.ui and making minimal changes to your posted code, you can add your UI elements to the window like so:
from PyQt4 import QtGui
import sys
class MyApp(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Cannot resize or maximize
self.setFixedSize(1045, 770)
widget = QtGui.QWidget(self)
self.setCentralWidget(widget)
# Add button test
self.dateLabel = QtGui.QLabel("Test")
self.pushButton = QtGui.QPushButton('Test button')
grid = QtGui.QGridLayout()
grid.addWidget(self.dateLabel, 0, 0)
grid.addWidget(self.pushButton, 0, 1)
widget.setLayout(grid)
self.pushButton.clicked.connect(self.closeEvent)
def closeEvent(self, event):
QtGui.QApplication.quit()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
This will get the controls on the screen, although the layout leaves a lot to be desired. You may have to make modifications to this based on what's in your .ui file. One thing that you'll want to note in this example is that the QMainWindow needs a central widget (widget in the example above). You then set the layout on that widget.
You can use the designer to create your .ui file
The you can load it in your .py using something like:
from PyQt4 import QtCore, QtGui, uic
class my_win(QtGui.QMainWindow):
def __init__(self):
self.ui = uic.loadUi('my_ui.ui',self)
then you can access all your widgets with something like
self.ui.actionQuit.triggered.connect(QtGui.qApp.quit)
or
self.ui.my_button.triggered.connect(self.do_someting)
Thanks to JCVanHamme (the programLauncher.ui hint) and also outside help I now learned most of what I need to know to access MainWindow at run time. So for anyone interested in this beginner tip:
Take a blank form in QT Designer
Add a control
Run pyuic4 batch file
Take a look at the generated .py file to learn EVERYTHING about how to add controls.
Don't let the power go to your head - cheers
I have a very basic QMainWindow application that contains a menubar and a statusbar. When I hover over the menu the status message disappears. More precisely, the status message is cleared. I have no idea what is causing this behavior but it's resulting in a very difficult workaround for what I hoped to be trivial behavior.
This is problematic for the following reason:
I can make the message permanent by adding a QLabel widget to the QStatusBar, but then I get the awkward border. I don't want the border. The only way I know how to remove the border is via QStatusBar.setStyleSheet(). I am using a palette for my color scheme as opposed to a stylesheet so modifying the stylesheet messes up other colors. I also can't restore the original statusBar QLabel color when I make a modification via the stylesheet. I'm not the best at using stylesheets.
Is there a way to prevent the menu interaction from clearing the status message? If not, is there a way to remove the border from the StatusBar when adding a QLabel widget while preserving my palette (maybe not via stylesheets)?
#!/usr/bin/env python
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class win(QMainWindow):
def __init__(self,parent=None):
super(win,self).__init__(parent)
self.menubar = QMenuBar(self)
self.fileMenu = QMenu("File")
self.exitAction = QAction("Exit",self)
self.fileMenu.addAction(self.exitAction)
self.menubar.addMenu(self.fileMenu)
self.statusBar().showMessage("Hello")
self.connect(self.exitAction,SIGNAL("triggered()"), self.close)
if __name__ == "__main__":
app = QApplication(sys.argv)
GUI = win()
GUI.show()
app.exec_()
I got the same problem, and I found another way which is creating a new QLabel
self.myMessage = QtGui.QLabel()
self.myMessage.setText("Hello")
and add it as an widget to the status bar on the left
self.statusBar.addWidget(self.myMessage)
or on the right
self.statusBar.addPermanentWidget(self.myMessage)
Basically, each widget you hover over sets the status bar text to their statusTip property even when that property is an empty string.
For QMenu, the text is stored in the menuAction action status tip, so, you can have a text instead of just clearing the status bar with something like this:
self.fileMenu.menuAction().setStatusTip("File Menu is hovered")
To prevent anything to change the status bar, you can probably install an eventFilter on the status bar and filter out all QStatusTipEvent.
Just to update Lazywii's answer regarding using a QLabel. That code didn't work exactly as is so maybe there have been some changes since 2016 but what did work in 2020 on PyQt5 is:
self.myMessage = QtWidgets.QLabel()
self.myMessage.setText("My message not affected by tooltips from hovering")
self.statusbar.addWidget(self.myMessage)
One complete example
# Created by BaiJiFeiLong#gmail.com at 2022/2/15 22:27
from PySide2 import QtWidgets, QtCore, QtGui
class StatusTipFilter(QtCore.QObject):
def eventFilter(self, watched: QtCore.QObject, event: QtCore.QEvent) -> bool:
if isinstance(event, QtGui.QStatusTipEvent):
return True
return super().eventFilter(watched, event)
app = QtWidgets.QApplication()
window = QtWidgets.QMainWindow()
window.menuBar().addMenu("File")
window.statusBar().showMessage("Ready")
window.menuBar().installEventFilter(StatusTipFilter(window))
window.show()
app.exec_()
And to answer the portion about removing the border from the statusbar: self.statusbar().setStyleSheet("QStatusBar::item{ border: 0px solid black };") does the trick. It is important to setStyleSheet only on the statusbar object and not the entire application.
This is a Mac OS QT issue,
I have created a QMainWindow and added a toolbar to it.
after setting "setUnifiedTitleAndToolBarOnMac" flag to TRUE my toolbar got unified to my mainwindow.
But when i customize the window buttons such as only close button option,
my window Toolbar got detached from title bar as if it looks like a winodow OS toolbar
not like a Mac native one.
Attached my test code below which is in pyqt.
Hope someone know how to achieve it.
Thanks
from PyQt4 import QtGui
from PyQt4 import QtCore
class Ui_windo(QtGui.QMainWindow):
def __init__(self,parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setObjectName("windo")
self.resize(400, 300)
self.setWindowTitle(QtGui.QApplication.translate("window", "window", None, QtGui.QApplication.UnicodeUTF8))
self.b1 = QtGui.QToolButton()
self.b1.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.b1.setText('Test')
self.b1.setObjectName("b1")
self.b1.setCheckable(True)
_toolBar = self.addToolBar('test')
_toolBar.setMovable(False)
_toolBar.addWidget(self.b1)
self.setUnifiedTitleAndToolBarOnMac(True);
_windowButtons = QtCore.Qt.Window| QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.CustomizeWindowHint
self.setWindowFlags(_windowButtons)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
ui = Ui_windo()
ui.show()
sys.exit(app.exec_())
Seems that the Qt.CustomizeWindowHint flag removes the styling from the toolbar. Not sure if this is expected behavior or a bug. There have been a number of style-related bug reports pertaining to setUnifiedTitleAndToolBarOnMac. You should post it to confirm whether its expected or not.
https://bugreports.qt-project.org/secure/IssueNavigator.jspa
If you set your window flag to use Qt.Tool, that will at least get you close by removing the minimize button.
I'm a beginner in PyQt. I was trying to create a simple app to try some of the toolkit's many features. My question is, how can I hide the app icon from the taskbar?
I don't want the user to be able to see the icon in taskbar and to minimize it using this icon. Is there any window flags that I can use to achieve this?
This should do the trick:
myApp.setWindowFlags(QtCore.Qt.Tool)
This drove me nuts for days. Complete app code to implement below.
Key bits:
override closeEvent(), enabling it to do either of just hiding window
or true exit
create some facility for user to choose either hide or
exit behavior
don't show() main window on instantiation, just exec_() the App
import sys
from PyQt4.QtGui import QAction, QApplication, QFrame, QIcon, \
QMainWindow, QMenu, QSystemTrayIcon
from PyQt4.QtCore import SIGNAL
class MyApp(QMainWindow):
def __init__(self, parent, title):
super(QMainWindow, self).__init__(parent)
self.exitOnClose = False
exit = QAction(QIcon(), "Exit", self)
self.connect(exit, SIGNAL("triggered()"), self.exitEvent)
self.trayIcon = QSystemTrayIcon(QIcon(), self)
menu = QMenu(self)
menu.addAction(exit)
self.trayIcon.setContextMenu(menu)
self.connect(self.trayIcon, \
SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), \
self.trayIconActivated)
self.trayIcon.show()
self.trayIcon.showMessage("MyApp is running!", "Click to open window\nRight click for menu" )
def trayIconActivated(self, reason):
if reason == QSystemTrayIcon.Context:
self.trayIcon.contextMenu().show()
elif reason == QSystemTrayIcon.Trigger:
self.show()
self.raise_()
def closeEvent(self, event):
if self.exitOnClose:
self.trayIcon.hide()
del self.trayIcon
event.accept()
else:
self.hide()
event.setAccepted(True)
event.ignore()
def exitEvent(self):
self.exitOnClose = True
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
myapp = MyApp(None, "My System Tray App")
app.exec_()
Adapted from this thread:
import sys
from PyQt4.QtGui import *
if __name__ == '__main__':
app = QApplication(sys.argv)
widget = QWidget()
mainWindow = QMainWindow(widget)
mainWindow.show()
sys.exit(app.exec_())
I wouldn't recommend trying to hide an application's taskbar presence, especially if the application is visible. If you are only trying to prevent minimizing from the taskbar then you can achieve this by creating your top level widget with the following window flags like this:
QWidget *mainWindow = new QWidget(0, Qt::CustomizeWindowHint
| Qt::WindowTitleHint | Qt::WindowSystemMenuHint
| Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint);
If you don't want a maximize flag, you can leave that one out of the list too.
The various window flags that Qt can use are documented here (Qt::WindowFlags).
If you are on Ubuntu with Unity and want to hide an application's icon from the launcher on the left-hand-side, you will probably need Qt.SplashScreen. This worked for me but I don't remember if I also needed Qt.Tool, which is enough on Windows. For the SplashScreen attempt you may have to reimplement the resize functionality as it disables this feature of a QStatusBar (that has a SizeGrip) for example.
Here is a little example to try out window flags.
Just initialise your main window like this self.setWindowFlags(Qt.ToolTip)