Qt text alignment in QCheckBox - qt

I am looking for a way to align text in a QCheckBox to both the right and left side. I cannot seems to find any ways to modify just the alignment of the text and not the checkbox itself.

I don't know if you can access the label associated with the checkbox or not, but if you cannot, a hack would be to set the checkbox label with an empty string and use another QLabel where you can use setAlignment(Qt::AlignJustify) to adjust your text to both the right and left side.
But then I don't know if you consider this modify the checkbox itself and not just the alignement.

I solved it using a trick.
Create a QCheckBox without putting any text in it.
And create a QLable so that you can center the text and click it.
Then it's possible.
Below is the example code.
You can refer to it.
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class MyApp(QWidget):
###### Define StyleSheet ######
DEFAULT_COLOR = {
'border': '#000000',
'hover': '#29adff'
}
CP_DEFAULT_STYLE = '''
QCheckBox::indicator:hover {{
border: 1px solid {hover};
background: white;
}}
QCheckBox::indicator {{
border: 1px solid {border};
background: white;
}}
'''
CP_DEFAULT_STYLE_SET_VALUE = CP_DEFAULT_STYLE.format(**DEFAULT_COLOR)
################################
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.cb = QCheckBox(self)
cp_label = QLabel('Click\nHere Me!!', self)
self.cb.setStyleSheet(self.CP_DEFAULT_STYLE_SET_VALUE)
cp_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
cp_label.setGeometry(75+30, 50+15, 60, 30)
self.cb.move(75+90, 50+20)
self.cb.clicked.connect(self.cpClick)
cp_label.mousePressEvent = self.cpLabelClick
cp_label.leaveEvent = self.cpLabelLeave
cp_label.enterEvent = self.cpLabelEnter
self.setWindowTitle('QCheckBox')
self.setGeometry(300, 300, 300, 200)
self.show()
def cpClick(self):
if not self.cb.isChecked():
self.cb.setStyleSheet(
self.CP_DEFAULT_STYLE_SET_VALUE
)
else:
self.cb.setStyleSheet('')
def cpLabelClick(self, _):
self.cb.setStyleSheet('')
self.cb.setChecked(
not self.cb.isChecked()
)
def cpLabelLeave(self, _):
self.cb.setStyleSheet('')
def cpLabelEnter(self, _):
if not self.cb.isChecked():
setColer = self.DEFAULT_COLOR.copy()
setColer['border'] = self.DEFAULT_COLOR['hover']
self.cb.setStyleSheet(
self.CP_DEFAULT_STYLE.format(**setColer)
)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
or
If you use Qt Designer,
After creating one Qwidget, make QCheckBox and QLabel inside
Bring the QLabel to the front and make the QCheckBox deselected.
And if you write it like the code below, it works perfectly!
import os
import sys
from PyQt5.uic import loadUi
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
def resource_path(*relative_Path_AND_File):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = getattr(sys, '_MEIPASS', os.path.dirname(
os.path.abspath(__file__)))
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, '/'.join(relative_Path_AND_File))
class MyApp_Define:
cb: QCheckBox
cb_label: QLabel
class MyApp(QMainWindow, MyApp_Define):
###### Define StyleSheet ######
DEFAULT_COLOR = {
'border': '#000000',
'hover': '#29adff'
}
CP_DEFAULT_STYLE = '''
QCheckBox::indicator:hover {{
border: 1px solid {hover};
background: white;
}}
QCheckBox::indicator {{
border: 1px solid {border};
background: white;
}}
'''
CP_DEFAULT_STYLE_SET_VALUE = CP_DEFAULT_STYLE.format(**DEFAULT_COLOR)
################################
def __init__(self):
super().__init__()
loadUi(resource_path("TEST.ui"), self)
self.cb_label.installEventFilter(self)
self.cb_label.leaveEvent = self.cbLabelLeave
self.cb_label.mousePressEvent = self.cbLabelClick
def eventFilter(self, source: QObject, event: QEvent):
# 자동 종료 체크박스 안에 들어갈시
if (
source is self.cb_label and
event.type() == QEvent.Type.MouseMove and
not self.cb.isChecked()
):
self.cbLabelEnter()
return super().eventFilter(source, event)
def cbLabelClick(self, _):
self.cb.setStyleSheet('')
self.cb.setChecked(
not self.cb.isChecked()
)
if not self.cb.isChecked():
self.cbLabelEnter()
def cbLabelLeave(self, _):
self.cb.setStyleSheet('')
def cbLabelEnter(self, _=None):
if not self.cb.isChecked():
setColer = self.DEFAULT_COLOR.copy()
setColer['border'] = self.DEFAULT_COLOR['hover']
self.cb.setStyleSheet(
self.CP_DEFAULT_STYLE.format(**setColer)
)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
ex.show()
sys.exit(app.exec_())
The image below is an example of QtDesigner.

Related

Change highlight color for a specific item (QAction type) on a QMenuBar

I want to mimic the behavior of the window top-right corner actions when hovering over the minimize-maximize-close buttons.
So I have created a QMenuBar that contains 3 QActions.
class WindowMenuActions(QMenuBar):
def __init__(self):
super(WindowMenuActions, self).__init__()
minimize_action = QAction(self)
minimize_action.setIcon(_MINIMIZE_ICON)
maximize_action = QAction(self)
maximize_action.setIcon(_MAXIMIZE_ICON)
exit_action = QAction(self)
exit_action.setIcon(_CLOSE_ICON)
self.addAction(minimize_action)
self.addAction(maximize_action)
self.addAction(exit_action)
And set the background color when hovering with stylesheet (it is applied to the entire QApplication):
I want the close button to have a different highlight color, so I tried setting a boolean property on the exit_action to change the color only for that specific item, but it does not do any effect (in fact, if I add the property in the stylesheet it doesn't even consider the stylesheet values)
Any idea of how to achieve this?
To extend the question, I would not only use this for the minimize-maximize-close actions, but also to understand how to apply different hover/selected colors on QActions in the QMenuBar (not in the QMenu, which I already found a solution for that).
This is an running example:
from PySide2.QtWidgets import QMenuBar, QAction, QStyle, QApplication, QMainWindow
from PySide2.QtCore import Qt
class WindowMenuActions(QMenuBar):
def __init__(self):
super(WindowMenuActions, self).__init__()
minimize_action = QAction(self)
_MINIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMinButton)
_MAXIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMaxButton)
_EXIT_ICON = self.style().standardIcon(QStyle.SP_TitleBarCloseButton)
minimize_action.setIcon(_MINIMIZE_ICON)
minimize_action.setProperty('exit_action', False)
maximize_action = QAction(self)
maximize_action.setProperty('exit_action', False)
maximize_action.setIcon(_MAXIMIZE_ICON)
exit_action = QAction(self)
exit_action.setProperty('exit_action', True)
exit_action.setIcon(_EXIT_ICON)
self.addAction(minimize_action)
self.addAction(maximize_action)
self.addAction(exit_action)
self.setStyleSheet(
'QMenuBar::item:selected {'
'background-color: grey;'
'}'
'QMenuBar::item[exit_action=true]:selected {'
' background-color: red;'
'}')
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
main = QMainWindow()
main.setMenuBar(WindowMenuActions())
main.show()
sys.exit(app.exec_())
To anyone interested, I sorted by inheriting from a regular QWidget instead of a QMenuBar and using QToolButton instead of QAction.
Working example:
from PySide2.QtWidgets import QMenuBar, QStyle, QApplication, QMainWindow, QWidget, QHBoxLayout, QToolButton, QMenu
from PySide2.QtCore import Qt
class MenuBar(QMenuBar):
def __init__(self):
super(MenuBar, self).__init__()
self.addMenu(QMenu('File'))
self.addMenu(QMenu('Help'))
self.setCornerWidget(WindowMenuActions(self))
class WindowMenuActions(QWidget):
def __init__(self, parent=None):
super(WindowMenuActions, self).__init__(parent)
_MINIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMinButton)
_MAXIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMaxButton)
_EXIT_ICON = self.style().standardIcon(QStyle.SP_TitleBarCloseButton)
minimize = QToolButton(self)
minimize.setIcon(_MINIMIZE_ICON)
maximize = QToolButton(self)
maximize.setIcon(_MAXIMIZE_ICON)
exit_action = QToolButton(self)
exit_action.setProperty('exit_button', True)
exit_action.setIcon(_EXIT_ICON)
layout = QHBoxLayout()
layout.addWidget(minimize)
layout.addWidget(maximize)
layout.addWidget(exit_action)
self.setLayout(layout)
self.setStyleSheet(
'QToolButton:hover {'
' background: grey;'
'}'
'QToolButton[exit_button=true]:hover {'
' background: red;'
'}'
)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
main = QMainWindow()
main.setWindowFlags(Qt.FramelessWindowHint)
main.setMenuBar(MenuBar())
main.show()
sys.exit(app.exec_())

How To implementing multi layer frame or widget in Qt?

How can I implement this in Qt, I am using PyQt and Qt Designer but confusing how to use layering like in the following image.
I want to first layer in index 0 to show the image or video,
then the second layer in index 2 is media control which can hide when no move from mouse,
and layer 3 in index 3 when change the volume in example
layer 4 in index 4 for notification etc.
is possible to do this in Qt?
There is a simple way to implement "layers" - you can add child widgets without any layout and resize/move them on resize event of host widget (using event filter). First layer can be organized with any layout as usual.
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt
class Layer(QtCore.QObject):
def __init__(self, host, child, alignment = Qt.AlignLeft, setWidth = False, setHeight = False, parent = None):
super().__init__(parent)
self._host = host
self._child = child
self._alignment = alignment
self._setWidth = setWidth
self._setHeight = setHeight
child.setParent(host)
host.installEventFilter(self)
def eventFilter(self, watched, event):
if watched != self._host or event.type() != QtCore.QEvent.Resize:
return False
hostSize = event.size()
childSize = self._child.sizeHint()
alignment = self._alignment
x = 0
y = 0
dWidth = max(0, hostSize.width() - childSize.width())
dHeight = max(0, hostSize.height() - childSize.height())
if alignment & Qt.AlignRight:
x = dWidth
elif alignment & Qt.AlignHCenter:
x = dWidth / 2
if alignment & Qt.AlignVCenter:
y = dHeight / 2
elif alignment & Qt.AlignBottom:
y = dHeight
width = hostSize.width() if self._setWidth else childSize.width()
height = hostSize.height() if self._setHeight else childSize.height()
self._child.setGeometry(x, y, width, height)
return False
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QWidget()
label1 = QtWidgets.QLabel("right label")
label2 = QtWidgets.QLabel("bottom label")
layer1 = Layer(widget, label1, Qt.AlignRight)
layer2 = Layer(widget, label2, Qt.AlignBottom | Qt.AlignHCenter, True)
widget.show()
sys.exit(app.exec_())
This is one of the very few cases for which using a layout is not suggested, as the visible widgets are "floating" and should be possibly moved around.
The solution is to create a "container" widget that has all those controls as children.
Then, some widgets will need some repositioning and resizing (for instance, the control bar should always be on bottom and occupy the whole width), and that can be implemented in the resizeEvent().
from PyQt5 import QtCore, QtGui, QtWidgets
class ControlBar(QtWidgets.QFrame):
def __init__(self, parent):
super().__init__(parent)
layout = QtWidgets.QVBoxLayout(self)
self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
layout.addWidget(self.slider)
buttons = QtWidgets.QHBoxLayout()
layout.addLayout(buttons)
buttons.addWidget(QtWidgets.QToolButton(text='play'))
buttons.addWidget(QtWidgets.QToolButton(text='stop'))
buttons.addStretch()
class VolumeWidget(QtWidgets.QFrame):
def __init__(self, parent):
super().__init__(parent)
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(2, 2, 2, 0)
layout.setSpacing(1)
handle = QtWidgets.QFrame()
handle.setFixedHeight(12)
handle.setStyleSheet('''
QFrame {
border: 1px solid darkGray;
border-radius: 2px;
background: #aa646464;
}
''')
layout.addWidget(handle)
volumeLayout = QtWidgets.QHBoxLayout()
layout.addLayout(volumeLayout)
for i in range(4):
volumeLayout.addWidget(QtWidgets.QSlider(QtCore.Qt.Vertical))
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.startPos = event.pos()
def mouseMoveEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton:
delta = event.pos() - self.startPos
self.move(self.pos() + delta)
class Notification(QtWidgets.QFrame):
def __init__(self, parent):
super().__init__(parent)
layout = QtWidgets.QHBoxLayout(self)
self.label = QtWidgets.QLabel('Notification', alignment=QtCore.Qt.AlignCenter)
layout.addWidget(self.label)
class PlayerWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.video = QtWidgets.QLabel(self)
self.video.setPixmap(QtGui.QPixmap('movie.png'))
self.video.setScaledContents(True)
self.controlBar = ControlBar(self)
self.notification = Notification(self)
self.volumeWidget = VolumeWidget(self)
self.volumeWidget.move(30, 30)
self.setStyleSheet('''
VolumeWidget, ControlBar {
border: 1px outset darkGray;
border-radius: 4px;
background: #aad3d3d3;
}
VolumeWidget:hover, ControlBar:hover {
background: #d3d3d3;
}
Notification {
border: 1px outset darkGray;
border-radius: 4px;
background: #aa242424;
}
Notification QLabel {
color: white;
}
''')
def sizeHint(self):
if self.video.pixmap() and not self.video.pixmap().isNull():
return self.video.pixmap().size()
return QtCore.QSize(640, 480)
def resizeEvent(self, event):
# set the geometry of the "video"
videoRect = QtCore.QRect(
QtCore.QPoint(),
self.video.sizeHint().scaled(self.size(), QtCore.Qt.KeepAspectRatio))
videoRect.moveCenter(self.rect().center())
self.video.setGeometry(videoRect)
# control panel
controlHeight = self.controlBar.sizeHint().height()
controlRect = QtCore.QRect(0, self.height() - controlHeight,
self.width(), controlHeight)
self.controlBar.setGeometry(controlRect)
# notification
notificationWidth = max(self.notification.sizeHint().width(), self.width() * .6)
notificationRect = QtCore.QRect(
(self.width() - notificationWidth) * .5, 20,
notificationWidth, self.notification.sizeHint().height()
)
self.notification.setGeometry(notificationRect)
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.fillRect(self.rect(), QtCore.Qt.black)
Note that in this simple case I only used an image. If you want to play video, you should use the Qt Multimedia module, and in order to correctly have transparency of controls a QGraphicsView with a QGraphicsVideoItem must be used.
In this case, PlayerWidget can directly be a subclass of QGraphicsView.

PyQt5 QGroupBox - how to display title in line with the top outside line for the QGroupBox?

This example:
# test1.py
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout, QVBoxLayout, QPushButton, QRadioButton, \
QGroupBox, QButtonGroup
from PyQt5.Qt import Qt
def main():
app = QApplication([])
mainForm = MainForm()
mainForm.show()
app.exec()
# end function
class MainForm(QWidget):
def __init__(self):
super().__init__()
self.rdoRed = QRadioButton('Red')
self.rdoGreen = QRadioButton('Green')
self.rdoBlue = QRadioButton('Blue')
self.vblColor = QVBoxLayout()
self.vblColor.addWidget(self.rdoRed)
self.vblColor.addWidget(self.rdoGreen)
self.vblColor.addWidget(self.rdoBlue)
self.gbColor = QGroupBox('Choose Color')
self.gbColor.setStyleSheet('QGroupBox:title {'
'subcontrol-origin: padding; }')
self.gbColor.setLayout(self.vblColor)
self.vboxLayout = QVBoxLayout()
self.vboxLayout.addWidget(self.gbColor)
self.setLayout(self.vboxLayout)
# end function
# end class
if __name__ == '__main__':
main()
Renders like this on Ubuntu 18.04:
I'd like the Choose Color text currently just above the top of the QGroupBox boundary line to instead be in line with the top of the QGroupBox boundary, like the Qt docs show:
Notice how Package selection is in line with the top boundary line of the QGroupBox, I'd like to do the same with the Choose Color title in the example I have above.
Is this an operating system limitation and what I'm asking isn't possible? I'm using Ubuntu 18.04.
Or is there a setStyleSheet parameter I can pass in to achieve this? As you can see in the example above I attempted to set some style sheet properties to achieve this but I was unable to find such a property. Or is there some other means with which this can be achieved?
Try it:
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout, QVBoxLayout, QPushButton, QRadioButton, \
QGroupBox, QButtonGroup
from PyQt5.Qt import *
class MainForm(QWidget):
def __init__(self):
super().__init__()
self.rdoRed = QRadioButton('Red')
self.rdoGreen = QRadioButton('Green')
self.rdoBlue = QRadioButton('Blue')
self.vblColor = QVBoxLayout()
self.vblColor.addWidget(self.rdoRed)
self.vblColor.addWidget(self.rdoGreen)
self.vblColor.addWidget(self.rdoBlue)
self.gbColor = QGroupBox('Choose Color')
self.gbColor.setStyleSheet('''
QGroupBox {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #E0E0E0, stop: 1 #FFFFFF);
border: 2px solid #999999;
border-radius: 5px;
margin-top: 2ex; /*leave space at the top for the title */
font-size: 13px;
color: black;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center; /* position at the top center */
padding: 0 3px;
font-size: 13px;
color: black;
}
''')
self.gbColor.setLayout(self.vblColor)
self.vboxLayout = QVBoxLayout()
self.vboxLayout.addWidget(self.gbColor)
self.setLayout(self.vboxLayout)
def main():
app = QApplication([])
mainForm = MainForm()
mainForm.show()
app.exec()
if __name__ == '__main__':
main()

How to build a flat groupbox in PyQt5?

I found the flat property of the QGroupbox Class in the Qt-docs, where it says:
A group box usually consists of a surrounding frame with a title at the top. If this property is enabled, only the top part of the frame is drawn in most styles; otherwise, the whole frame is drawn.
I'm trying to build such a flat QGroupBox, but it doesn't seem to work, as you can see in this picture. In the docs it also says:
Note: In some styles, flat and non-flat group boxes have similar representations and may not be as distinguishable as they are in other styles.
That leads me to the QStyle Class, which overstrains me a little, as I have no idea how to change the Style of the QGroupBox. I'm not even sure, if this is the real problem here. As you can see in my code below, I don't assign a specific style to the QGroupBox. So, it should use some sort of standard style, i guess...
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox,
QVBoxLayout, QLabel
class WidgetWithFlatGroupBox(QWidget):
def __init__(self):
QWidget.__init__(self, flags=Qt.Widget)
self.init_ui()
def init_ui(self):
self.setGeometry(300, 300, 300, 100)
self.setWindowTitle('PyQt5 Window')
layout = QVBoxLayout()
layout.addWidget(self.create_groupbox(), alignment=Qt.AlignCenter)
self.setLayout(layout)
def create_groupbox(self):
groupbox = QGroupBox('Flat Groupbox')
layout = QVBoxLayout()
label = QLabel('This Groupbox should be flat.')
layout.addWidget(label, alignment=Qt.AlignCenter)
groupbox.setLayout(layout)
groupbox.setFlat(True)
return groupbox
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = WidgetWithFlatGroupBox()
ex.show()
sys.exit(app.exec_())
I had a look at the internet, also here at stackoverflow of course, but were not able to find something useful. Is there anyone who knows how to use the flat property of the QGroupBox Class properly?
Sorry, but I do not understand how you need to do:
border: None;
border: 1px solid #76797C;
Try it:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QWidget, QGroupBox,
QVBoxLayout, QLabel, QPushButton)
class WidgetWithFlatGroupBox(QWidget):
def __init__(self):
QWidget.__init__(self, flags=Qt.Widget)
self.init_ui()
def init_ui(self):
self.setGeometry(300, 300, 300, 100)
self.setWindowTitle('PyQt5 Window')
layout = QVBoxLayout()
layout.addWidget(self.create_groupbox(), alignment=Qt.AlignCenter)
self.setLayout(layout)
def create_groupbox(self):
groupbox = QGroupBox('Flat Groupbox')
layout = QVBoxLayout()
label = QLabel('This Groupbox should be flat.')
button = QPushButton("This Button !!!")
button.setFlat(True)
layout.addWidget(label, alignment=Qt.AlignCenter)
layout.addWidget(button, alignment=Qt.AlignCenter)
groupbox.setLayout(layout)
# groupbox.setFlat(True)
return groupbox
style = '''
QGroupBox {
border: None; /*<----- None */
/* border: 1px solid #76797C; <----- 1px solid #76797C */
border-radius: 2px;
margin-top: 20px;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
}
'''
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(style)
ex = WidgetWithFlatGroupBox()
ex.show()
sys.exit(app.exec_())
self.groupBox_33.setFlat(True)

How to customize button ok in Gtk.MessageDialog with CSS?

My day's question is about apply CSS in default button in Gtk.MessageDialog. I tried a lot things without result.
The deal is to find th good id like buttons, or GTKbutton, or GtkMessageDialog.Button,......
#!/usr/bin/env python
# -*- coding: ISO-8859-1 -*-
#demo_messagedialog_css.py
from gi.repository import Gtk,Gdk
class show_message_dlg:
def __init__(self, message, type_message=Gtk.MessageType.INFO,stock_message=Gtk.STOCK_DIALOG_INFO, decorate=True):
"""
This Function is used to show an message
error dialog when an error occurs.
error_string - The error string that will be displayed on the dialog.
==>type_message=gtk.MESSAGE_ERROR for error message
==>type_message=gtk.MESSAGE_INFO for information message
==>type_message=gtk.MESSAGE_WARNING for warning message
GTK_WIN_POS_NONE
GTK_WIN_POS_CENTER equivalent in python to Gtk.WindowPosition.CENTER
GTK_WIN_POS_MOUSE equivalent in python to Gtk.WindowPosition.MOUSE
GTK_WIN_POS_CENTER_ALWAYS equivalent in python to Gtk.WindowPosition.CENTER_ALWAYS
GTK_WIN_POS_CENTER_ON_PARENT equivalent in python to Gtk.WindowPosition.CENTER_ON_PARENT
"""
self.message = message
self.message_dlg = Gtk.MessageDialog(type = type_message
, buttons = Gtk.ButtonsType.OK)
self.message_dlg.set_decorated(decorate)
self.message_dlg.set_markup(self.message)
self.message_dlg.set_position(Gtk.WindowPosition.CENTER_ON_PARENT )
style_provider = Gtk.CssProvider()
css = """
GtkMessageDialog
{ background:linear-gradient(to bottom, green, rgba(0,255,0,0));}
#Buttons{ background-color: yellow}
"""
style_provider.load_from_data(css)
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
def run(self):
reponse = self.message_dlg.run()
self.message_dlg.destroy()
return reponse
if __name__ == "__main__":
exemple = show_message_dlg(u"message in the box dialog ")
exemple.run()
Gtk.main()
after few white night and 150 black coffe I found a small part of answer
#!/usr/bin/env python
# -*- coding: ISO-8859-1 -*-
#demo_messagedialog_css1.py
from gi.repository import Gtk,Gdk
class MyButtonClass(Gtk.Button):
__gtype_name__ = 'MyButton'
def __init__(self, label):
Gtk.Button.__init__(self, label)
self.connect("clicked", self._clicked1)
def _clicked1(self, button):
print "button ok clicked"
class show_message_dlg:
def __init__(self, message, type_message=Gtk.MessageType.INFO,stock_message=Gtk.STOCK_DIALOG_INFO, decorate=True):
self.message = message
self.message_dlg = Gtk.MessageDialog(type = type_message)
self.message_dlg.set_decorated(decorate)
self.message_dlg.set_markup(self.message)
self.message_dlg.set_position(Gtk.WindowPosition.CENTER_ALWAYS )
button_v = MyButtonClass('Ok button')
self.message_dlg.add_action_widget(button_v, Gtk.ResponseType.OK)
self.message_dlg.set_default_response(Gtk.ResponseType.OK)
# line below necessary if button not defined like Gtk.MessageDialog(type = type_message, buttons = Gtk.ButtonsType.OK)
self.message_dlg.show_all()
style_provider = Gtk.CssProvider()
css = """
GtkMessageDialog
{ background:linear-gradient(to bottom, yellow, rgba(0,255,0,0));}
MyButton {
color: darkgrey;
font: Comic Sans 20;} /* run OK for label font */
MyButton GtkLabel{ background-color: blue} /* run OK for button background label*/
/*MyButton GtkLabel{ background:linear-gradient(to right, yellow, blue,yellow,green,red,orange);}*/ /* run OK for button background label*/
MyButton:active GtkLabel{ background-color: red;} /* do not run if state change */
"""
style_provider.load_from_data(css)
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
def run(self):
reponse = self.message_dlg.run()
self.message_dlg.destroy()
return reponse
if __name__ == "__main__":
exemple = show_message_dlg(u"message in the dialog box ")
response = exemple.run()
if response == Gtk.ResponseType.OK:
print("OK button clicked and end")
else:
print("destroyed")
Gtk.main()
please note special class button with class atribut gtype_name = 'MyButton' and CSS command adressed by MyButton {}
Now I don't understand why part below not OK when I click on button
MyButton:active GtkLabel{ background-color: red;}
ok I found a solution for specific problem button
MyButton:active GtkLabel{ background: red;}
my exemple
#!/usr/bin/env python
# -*- coding: ISO-8859-1 -*-
#demo_messagedialog_css2.py
from gi.repository import Gtk,Gdk
class MyButtonClass(Gtk.Button):
__gtype_name__ = 'MyButton'
def __init__(self, label):
Gtk.Button.__init__(self, label)
self.connect("clicked", self._clicked1)
def _clicked1(self, button):
print "button ok clicked"
class show_message_dlg:
def __init__(self, message, type_message=Gtk.MessageType.INFO,stock_message=Gtk.STOCK_DIALOG_INFO, decorate=True):
self.message = message
self.message_dlg = Gtk.MessageDialog(type = type_message)
self.message_dlg.set_decorated(decorate)
self.message_dlg.set_markup(self.message)
self.message_dlg.set_position(Gtk.WindowPosition.CENTER_ALWAYS )
button_v = MyButtonClass('Ok button')
self.message_dlg.add_action_widget(button_v, Gtk.ResponseType.OK)
self.message_dlg.set_default_response(Gtk.ResponseType.OK)
# line below necessary if button not defined like Gtk.MessageDialog(type = type_message, buttons = Gtk.ButtonsType.OK)
self.message_dlg.show_all()
style_provider = Gtk.CssProvider()
css = """
GtkMessageDialog
{ background:linear-gradient(to bottom, yellow, rgba(0,255,0,0));}
MyButton {
color: darkgrey;
font: Comic Sans 20;}
MyButton:active { background: red;}
MyButton GtkLabel{ background:linear-gradient(to right, yellow, blue,yellow,green,red,orange);}
"""
style_provider.load_from_data(css)
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
def run(self):
reponse = self.message_dlg.run()
self.message_dlg.destroy()
return reponse
if __name__ == "__main__":
exemple = show_message_dlg(u"message in the dialog box ")
response = exemple.run()
if response == Gtk.ResponseType.OK:
print("OK button clicked and end")
else:
print("destroyed")
Gtk.main()

Resources