change thickness of boarder around QPushbutton when Button is selected with keys - python

I made a Gui and on a normal screen switching with keys between buttons works and the selected button can be easily seen. This gui is designed for an underwater screen which is much smaller than a normal screen. On the underwater screen it becomes very hard to see on which button the "cursor" is.
How is this state of the button called when the button is not yet checked but the cursor is resting on it?
The button is a regular QPushButton.
How can I make the line of this bounding box thicker?
In the image the cursor is on the Exit Button and a small blue line can be seen

You can set the width of the border with Qt StyleSheet:
import sys
from PyQt5 import QtWidgets
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
QSS = """
QPushButton:pressed {
border: 4px solid;
}
QPushButton:selected {
border: 4px solid;
}
"""
app.setStyleSheet(QSS)
button_1 = QtWidgets.QPushButton("Button1")
button_2 = QtWidgets.QPushButton("Button3")
button_3 = QtWidgets.QPushButton("Button3")
w = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(w)
lay.addWidget(button_1)
lay.addWidget(button_2)
lay.addWidget(button_3)
w.show()
sys.exit(app.exec_())

Related

How to implement list of checkable buttons with pyqt

I want to implement list of radiobuttons, but radiobutton shouldn't have a circle and if radiobutton is checked, then the background color is different from the others.
Like in this photo.
(https://i.stack.imgur.com/LsOeE.png)
I think I can use radiobuttons or tabs, but i don't know how to change the styles of this things. Tell me a widget with similar logic or how to change the style of radiobuttons/tabs.
If you don't need the circle of a radio button, then you probably don't need a radio button at all.
Instead, use standard QPushButtons (or QToolButtons) with setCheckable(True) and add them to a QButtonGroup.
win = QWidget()
win.setStyleSheet('''
QPushButton[checkable="true"]::checked {
background: red;
}
''')
layout = QHBoxLayout(win)
group = QButtonGroup()
for title in 'cdefgh':
button = QPushButton(title)
layout.addWidget(button)
button.setCheckable(True)
group.addButton(button)
group.buttons()[0].setChecked(True)
i set css rule:
css = '''
QRadioButton::indicator {
image: none;
}
QRadioButton::checked
{
background-color : red;
}
'''
radioButton.setStyleSheet(css)

Styling the tab bar of QtADS in a PyQt project

I am working on a PyQt project, which makes use of the library QtAds (Qt Advanced Docking System). In order to redesign the software correctly, I'd like to be able to style every widget with QSS, including the ones added by QtAds, which should be able to be styled like any other standard Widget. However, I can't find the proper selector to style the tab bar of the ADS DockWidgets. Here is a MWE :
import sys
from PyQt5.QtWidgets import QPushButton,QApplication
import os
from PyQt5 import uic
from PyQtAds import QtAds
from customWidgets import *
UI_FILE = os.path.join(os.path.dirname(__file__), 'ui/MainWindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)
class MainWindow(MainWindowUI, MainWindowBase):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.dock_manager = QtAds.CDockManager(self)
self.setStyleSheet("""
QToolButton {
background-color: #2c3e50;
border : 1px solid #bdc3c7;
width : 30px;
height : 30px;
}
QToolButton:hover {
background-color: #7f8c8d;
}
QTabWidget::tab {
background : red;
}
""")
scope_settings_dockable = QtAds.CDockWidget("Test")
scope_settings_dockable.setWidget(QPushButton())
# scope_settings_dockable.tabWidget().setStyleSheet("* { background : red; }") # That works
self.menuView.addAction(scope_settings_dockable.toggleViewAction())
self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, scope_settings_dockable)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
Here there is only one dockable widget which contains a QPushButton. The stylesheet defined here is able to change the styles on the buttons controlling the dockable widget, which are plain QToolButton and therefore are easy to edit. However, whenever I try to style the tab themselves, I can't find the right selector. I have tried ads--CDockWidgetTab, which should be the right selector according to the documentation, but it doesn't change the background. Tried with only CDockWidgetTab, and a few other syntaxes, but I can't get it to be styled.
As commented in the example, I found a way to style each tab individually, with dockable.tabWidget.setStylesheet(), but that is obviously not a nice solution since when having multiple widgets, I will have to restyle them individually, and will lead to a lot of redundancy.
Do anyone knows which selectors would allow me to style QtAds widgets ?

PyQt5: Create transparent window with opaque widgets

Is it possible to make mainWindow completely transparent while other widgets remains visible?
For example:
I want to make app transparent and make everything else visible (like, mainFrame, close button, minimize button)
As #Felipe mentioned you can use
window.setAttribute(QtCore.Qt.WA_TranslucentBackground)
here is a little example:
import sys
from PyQt5 import QtWidgets, QtCore
app = QtWidgets.QApplication(sys.argv)
# create invisble widget
window = QtWidgets.QWidget()
window.setAttribute(QtCore.Qt.WA_TranslucentBackground)
window.setWindowFlags(QtCore.Qt.FramelessWindowHint)
window.setFixedSize(800, 600)
# add visible child widget, when this widget is transparent it will also be invisible
visible_child = QtWidgets.QWidget(window)
visible_child.setStyleSheet('QWidget{background-color: white}')
visible_child.setObjectName('vc')
visible_child.setFixedSize(800, 600)
layout = QtWidgets.QGridLayout()
# add a close button
close_button = QtWidgets.QPushButton()
close_button.setText('close window')
close_button.clicked.connect(lambda: app.exit(0))
layout.addWidget(close_button)
# add a button that makes the visible child widget transparent
change_size_button = QtWidgets.QPushButton()
change_size_button.setText('change size')
change_size_button.clicked.connect(lambda: visible_child.setStyleSheet('QWidget#vc{background-color: transparent}'))
layout.addWidget(change_size_button)
visible_child.setLayout(layout)
window.show()
app.exec()

Unexpected padding on wrapped QLabel in custom class

I want to display a border around a QWidget that wraps a QLabel (this is practice for a more complicated widget). I'm using setStyleSheet to create the border. When I did this manually, it worked as expected. However, when I moved the code into its own class (derived from QWidget), the padding is different, and I can't figure out why.
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QMainWindow, QVBoxLayout
class WrappedLabel(QWidget):
def __init__(self, text=''):
super().__init__()
self.text = QLabel(text)
layout = QVBoxLayout()
layout.addWidget(self.text)
self.setLayout(layout)
self.setStyleSheet('padding: 2px; border: 2px solid red;')
class Shell(QMainWindow):
def __init__(self): # constructor
super().__init__() # call the parent's constructor
w = QWidget() # Create the main window content widget
self.setCentralWidget(w)
# First label
unwrapped_label = QLabel('This is a normal QLabel with a border and no padding.')
unwrapped_label.setStyleSheet('border: 2px solid gray; padding: 2px;')
# Second label
wrapped_label = QLabel('This QLabel is manually wrapped in a styled QWidget. ' +
'There is a slight indent compared to the normal QLabel due to padding.')
wrapped_layout = QVBoxLayout()
wrapped_layout.addWidget(wrapped_label)
manual_wrapper = QWidget()
manual_wrapper.setObjectName('wrapper')
manual_wrapper.setLayout(wrapped_layout)
self.setStyleSheet('QWidget#wrapper { border: 2px solid gray; padding: 2px; }')
# Third label
derived_wrapper = WrappedLabel('This class derives from QWidget and wraps a QLabel like above, but is indented even further and the border is in the wrong spot.')
vbox = QVBoxLayout()
vbox.addWidget(unwrapped_label)
vbox.addWidget(manual_wrapper)
vbox.addWidget(derived_wrapper)
vbox.addStretch(1) # Squish them together to better see the spacing
w.setLayout(vbox)
# Setup the rest of the main window appearance
self.setGeometry(300,300,640,180)
self.setWindowTitle('Testing wrapped labels')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
shell = Shell() # create and show the main window
sys.exit(app.exec_())
To begin with, the code in the custom class WrappedLabel is not exactly the same as for the manual widget. For the manual widget you make sure that the stylesheet is only applied to the widget itself, but not to any child widgets via QWidget#wrapper. For you custom class you simply apply the stylesheet to the WrappedLabel instance which will cause it to cascade to all its child widgets (and also to the QLabel instance). This is why your QLabel instance ends up with the padding and the red border.
So why doesn't the same happen for the wrapper? Apparently custom base classes of QWidgets reject all applied style sheets by default (see this answer). You can make this work by adding self.setAttribute(QtCore.Qt.WA_StyledBackground) in WrappedLabel.__init__. Now you'll see that you end up with two borders, one for the wrapper and one for the label. To restrict the stylesheet to the wrapper you need to apply a similar identifier as for the manual widget: self.setStyleSheet('WrappedLabel { padding: 2px; border: 2px solid red; }').
So to make it work you can add this to WrappedLabel.__init__:
self.setAttribute(QtCore.Qt.WA_StyledBackground)
self.setStyleSheet('WrappedLabel { padding: 2px; border: 2px solid red; }')

How to make Icon in QMenu larger (PyQt)?

I did not yet find out how to make the icons in my QMenu larger. I have tried to define a stylesheet in which the icon size is enlarged. But it doesn't work. Here is my code:
menuStyleSheet = ("""
QMenu {
font-size: 18px;
color: black;
border: 2px solid black;
left: 20px;
background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop: 0 #cccccc, stop: 1 #ffffff);
}
QMenu::item {
padding: 2px 20px 2px 30px;
border: 1px solid transparent; /* reserve space for selection border */
spacing: 20px;
height: 60px;
}
QMenu::icon {
padding-left: 20px;
width: 50px; /* <- unfortunately, doesn't work */
height: 50px; /* <- unfortunately, doesn't work */
}
""")
#####################################################
# THE PYQT APPLICATION #
#####################################################
class GMainWindow(QMainWindow):
def __init__(self, title):
super(GMainWindow, self).__init__()
...
def setCustomMenuBar(self):
myMenuBar = self.menuBar()
global menuStyleSheet
myMenuBar.setStyleSheet(menuStyleSheet)
# Now add Menus and QActions to myMenuBar..
The result of this code is as follows:
I know that there is an old StackOverflow question about a similar topic, but it assumes that one is coding the Qt application in C++. So the situation is different. Here is the link: How to make Qt icon (in menu bar and tool bar) larger?
Any help is greatly appreciated :-)
EDIT :
Here are some details about my machine:
OS: Windows 10
Python: v3 (Anaconda package)
Qt: PyQt5
After a long search, I finally found the solution.
Just copy-paste the code below, and paste it in a *.py file. Of course, you should replace the path to the icon with a valid path on your local computer. Just provide a complete path ("C:\..") to be 100% sure that Qt finds the icon drawing.
import sys
import os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
# Create a custom "QProxyStyle" to enlarge the QMenu icons
#-----------------------------------------------------------
class MyProxyStyle(QProxyStyle):
pass
def pixelMetric(self, QStyle_PixelMetric, option=None, widget=None):
if QStyle_PixelMetric == QStyle.PM_SmallIconSize:
return 40
else:
return QProxyStyle.pixelMetric(self, QStyle_PixelMetric, option, widget)
# This is the main window class (with a simple QMenu implemented)
# ------------------------------------------------------------------
class TestWindow(QMainWindow):
def __init__(self):
super(TestWindow, self).__init__()
# 1. Set basic geometry and color.
self.setGeometry(100, 100, 400, 400)
self.setWindowTitle('Hello World')
palette = QPalette()
palette.setColor(QPalette.Window, QColor(200, 200, 200))
self.setPalette(palette)
# 2. Create the central frame.
self.centralFrame = QFrame()
self.centralFrame.setFrameShape(QFrame.NoFrame)
self.setCentralWidget(self.centralFrame)
# 3. Create a menu bar.
myMenuBar = self.menuBar()
fileMenu = myMenuBar.addMenu("&File")
testMenuItem = QAction(QIcon("C:\\my\\path\\myFig.png"), "&Test", self)
testMenuItem.setStatusTip("Test for icon size")
testMenuItem.triggered.connect(lambda: print("Menu item has been clicked!"))
fileMenu.addAction(testMenuItem)
# 4. Show the window.
self.show()
# Start your Qt application based on the new style
#---------------------------------------------------
if __name__== '__main__':
app = QApplication(sys.argv)
myStyle = MyProxyStyle('Fusion') # The proxy style should be based on an existing style,
# like 'Windows', 'Motif', 'Plastique', 'Fusion', ...
app.setStyle(myStyle)
myGUI = TestWindow()
sys.exit(app.exec_())
You will see a window like this, with a huge icon:
So how did I solve it? Well, apparently you cannot increase the icon size of a QMenu item in the usual way - defining the size in the stylesheet. The only way to do it is to provide a new QStyle, preferably derived from an existing QStyle. I found sources on how to do that in C++ (see http://www.qtcentre.org/threads/21187-QMenu-always-displays-icons-aty-16x16-px), but no explanation for PyQt.
After long trials and errors, I got it working :-)
Apparently more people struggle with this situation: http://www.qtcentre.org/threads/61860-QMenu-Icon-Scale-in-PyQt

Categories

Resources