Why css style don't work on GtkButton? - python

Please excuse my english.
I'm trying to change the background color of a GtkButton using a css file but I can't.
I tried a few examples I found on the web, but none work.
I post two examples. One in Python 3.2.3 and the other in C
I'm using Gtk+ 3.6 and Kubuntu 12.10.
This is the code of one of them:
from gi.repository import Gtk, Gdk
class MainWindow(Gtk.Window):
def __init__(self):
super().__init__()
vbox = Gtk.Box(spacing=10,orientation=Gtk.Orientation.VERTICAL)
self.add(vbox)
self.entries = [ Gtk.Entry() for i in range(3) ]
for e in self.entries:
vbox.pack_start(e, True, True, 0)
e.connect("changed", self.on_entry_changed)
e.set_text('123')
button=Gtk.Button(label='ok')
vbox.pack_end(button,True,True,0)
def on_entry_changed(self,entry):
ctx = entry.get_style_context()
if not entry.get_text().isnumeric():
ctx.add_class('invalid')
else:
ctx.remove_class('invalid')
cssProvider = Gtk.CssProvider()
cssProvider.load_from_path('style.css')
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider,
Gtk.STYLE_PROVIDER_PRIORITY_USER) # With the others GTK_STYLE_PROVIDER_PRIORITY values get the same result.
window = MainWindow()
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()
and the style.css
GtkEntry.invalid {
background-color: #ffaaaa;
background: #ffaaaa;
}
GtkButton {
engine: oxygen-gtk; /*tried also with 'none' and without setting engine*/
background-color: green;
background: green;
}
The entries works well... the bg color change. But the Button no, and theres no error messages.
EDIT3: (Deleted previews edits and change some tags)
Summarizing... I tried to change the button color with all the Python, C, and C++ codes I found in the web unsuccessfully. I read all the tutorials I found and the GTK+ 3 reference manual.
All that I know after that is that the problem is about Kubuntu themes: If I change the GTK theme from 'oxygen-gtk' to 'default' (in GTK Configuration), is the only way I found that the code works well, but this is not the idea and the button looks horrible.
So, the questions are:
Why I can't change the background color of the button?
Why I having this problem only with buttons? (Works well with other widgets)
I get answers here and in GTK forums saying that is not a good practice to change button colors, but... What if I want a menu like the one in this image (link) (see red box buttons)? Wich is the best practis for that?
Thanks and greetings!

I know this is quite old, but popped up in the first few google results, so I thought I'd share my experience.
Gtk.Button has an inline Gtk.Label for the button text, that doesn't inherit from the button by default, so you have to explicitly tell it to (or just specify the colour in it):
GtkButton GtkLabel {
color: #fff; /* This changes the text color in the button */
}
As far as the answer from #sciamp, the GTK theme sets an image for the background and the borders as well, so you have to manually remove that with background-image: none; border-image: none; Hope this saves someone the struggle.

This should work (I mean it's working for me!):
GtkButton {
border-image: none;
background-image: none;
background-color: green;
}

This is complicated, but I don't think it can be done, directly.
I believe the core reason is because the button doesn't render the background. All it does is rendera frame around its area, and then render any children inside. Remember that GtkButton is a container, it typically holds a GtkLabel for a textual label but can hold any widgetry.
I've managed to change the background color of textual labels, but then only the much tigher box around the text itself is affected, which is not what you want.
The indirect solution is to subclass the GtkButton to create a variant which actually does render its background. This is, to be sure, pretty rude towards themes and should be avoided.

Related

How to dissable the focus indication in stylesheet

When my QDoubleSpinBox is focused, it gets a blue outline to it (in "Fusion" style):
How do I turn this off?
Doing this with stylesheets only is doable, but has an important drawback: styling complex widgets like a QSpinBox requires to correctly set all sub control properties.
The basic solution is to set the border for the widget:
QSpinBox {
border: 1px inset palette(mid);
border-radius: 2px;
}
Keep in mind that offering proper visible response of the focus is really important; you might not like the "glow" (and color) the Fusion style offers, but nonetheless it should always be visible when a widget has focus or not, even if it has a blinking text cursor. You can do that by specifying a slightly different color with the :focus selector:
QSpinBox:focus {
border: 1px inset palette(dark);
}
Unfortunately, as explained in the beginning, this has an important drawback: as soon as the stylesheet is applied, the widget painting falls back to the basic primitive methods (the spinbox on the right uses the stylesheet above):
Unfortunately, there's almost no direct way to restore the default painting of the arrows, as using the stylesheet prevents that. So, the only solution is to provide the properties for the controls as explained in the examples about customizing QSpinBox.
There is an alternative, though, using QProxyStyle. The trick is to intercept the control in the drawComplexControl() implementation and remove the State_HasFocus flag of the option before calling the default implementation.
In the following example, I also checked the focus before removing the flag in order to provide sufficient visual feedback, and I also removed the State_MouseOver flag which shows the glowing effect when hovering.
class Proxy(QtWidgets.QProxyStyle):
def drawComplexControl(self, cc, opt, qp, widget=None):
if cc == self.CC_SpinBox:
opt = QtWidgets.QStyleOptionSpinBox(opt)
if opt.state & self.State_HasFocus:
opt.palette.setColor(QtGui.QPalette.Window,
opt.palette.color(QtGui.QPalette.Window).darker(100))
else:
opt.palette.setColor(QtGui.QPalette.Window,
opt.palette.color(QtGui.QPalette.Window).lighter(125))
opt.state &= ~(self.State_HasFocus | self.State_MouseOver)
super().drawComplexControl(cc, opt, qp, widget)
# ...
app = QtWidgets.QApplication(sys.argv)
app.setStyle(Proxy())
# ...
Note that the above "color correction" only works for Fusion style and other styles that use the Window palette role for painting the border. For instance, the Windows style doesn't consider it at all, or you might want to use higher values of darker() or lighter() in order to provide better differentiation.

Python PyQt Hide QToolbutton Menu arrow

I want to hide the Small Down Arrow that appears on the QToolButton if i set a QMenu to it.
I have tried using StyleSheet by setting QToolButton menu-arrow image to none. The following is my Qss code:
QToolButton
{
border:1px solid #B6C4DB;
border-radius:12px;
padding:2px;
margin-left:5px;
}
QToolButton::menu-arrow
{
image:none;
}
QToolButton:pressed
{
border:1px solid #D6BB0B;
}
Is there a way to hide that small arrow on QToolButton with a menu?
QToolButton::menu-indicator { image: none; }
posting my comment as a potential answer (at least for now):
Looks like this is a bug but this page lists a workaround

How to set a style sheet that only affects the parent in PyQT?

I'm trying to customize my UI. I don't know how to make a style sheet entry pertain to anything except the parent and ALL of the children. For example I run this line:
self.lnchTab.setStyleSheet('QWidget { background-color: #1d1d1d ; color: #f8f8f8}')
And I change ALL of the elements beneath self.lnchTab to be darkish grey. I want only the self.lnchTab to be dark grey, and not the text, inputs, and buttons within it.
How do I accomplish this?
Thanks for any help. Google is giving nothing useful or even near what I'm trying to find.
You can give self.lnchTab object some name/id and then you can use id-selector in style-sheet:
self.lnchTab.setObjectName("myParentWidget");
self.lnchTab.setStyleSheet('QWidget#myParentWidget { background-color: #1d1d1d ; color: #f8f8f8}')

How to get the margin between menu items in pyjamas or gwt?

I have implemented a MenuBar using pyjamas as:
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.Composite import Composite
from pyjamas.ui.MenuBar import MenuBar
class Menubar(Composite):
def __init__(self):
Composite.__init__(self)
menubar = MenuBar(vertical=False)
menubar.addItem("Dashboard", "")
menubar.addItem("FileInspect", "")
self.initWidget(menubar)
RootPanel().add(Menubar())
But by all means i have tried, i am unable to get the margin/space between the menuitems "Dashboard" and "FileInspect". Your suggestions are warmly appreciated.
In GWT you can add a MenuItemSeparator between any pair of menu items that you want to separate. The width of the separator determines the separation between items. You can set the style for your separator such that it appears invisible. For example,
private MenuBar myMenuBar=new MenuBar(false); // false for horizontal menu bar
private MenuItemSeparator separator=new MenuItemSeparator();
private MenuItem item1;
private MenuItem item2;
myMenuBar.add(item1);
myMenuBar.add(separator);
myMenuBar.add(item2);
separator.setStyleName("separatorStyle");
In your CSS you define separatorStyle. For example, if you want a 20px separation...
.separatorStyle{
width: 20px;
padding: 0px;
margin: 0px;
border: none;
background: none;
}
OK so first look in the api documentation at http://pyjs.org/api/ and look for menubar (Ctrl+F finds it ok) or if you're lazy then you can see it here: http://pyjs.org/api/pyjamas.ui.MenuBar.MenuBar-class.html
That doesn't help in this case because there's no setSpacing() method or similar but at least it tells us that for sure.
So I guess you have to do it via css. Look in the showcase example:
pyjamas/examples/showcase/src/public/Showcase.css
Now you'll see there's a gwt-MenuBar class right at the top. So you've got two choices; either use the addStyleName() method of the MenuBar widget or just edit the existing style in the css. I'd probably do the latter.
Hope that helps!! Don't forget to accept if it does.

pyqt - how to remove the boder from a widget in the statusbar?

I am using QLabel widgets to display error messages to the user in the status bar. This is working fine with the following code;
self.statusbar = self.statusBar()
label = QtGui.QLabel("this is a test error message")
stylesheet = """
QLabel {
font-weight: bold;
color: #FF0000;
}
"""
label.setStyleSheet(stylesheet)
self.statusbar.addWidget(label)
The only problem is that the widgets have a border around them that I can not get rid of. This is not functionally a problem as the message is still visible but it does look rather ugly and I'd like to get rid of it. I can not work out where it is coming from. Whether it is something I need to set on the statusbar or the widget. I have tried modifying the stylesheet for both the statusbar and label to add "border: 0px" to no avail. I have tried setting the labels frame to label.setFrameShape(QtGui.QFrame.NoFrame) but that doesnt seem to be it either.
Anyone have any ideas how I can get rid of it?
You do this with Style sheets. You probably have a line like this
Application app(argc, argv);
underneath that, add one like this:
app.setStyleSheet("QStatusBar::item { border: 0px solid black }; ");
and those pesky boxes will be gone.
try using self.statusbar.showMessage('this is a test error message'), as the QStatusBar is not designed for showing labels. If you need more frexibility than this you may consider subclassing QStatusBar and changing its paintEvent function to special-case labels. Either of these approaches will be much easier to maintain than setting stylesheets for each label you want to but on there anyway, but as usual, YMMV.
for more info check out the manual page for QStatusBar

Categories

Resources