I'm trying to set different visual styles for a pressed QToolButton depending on whether it displays a menu or not.
In my code, tool buttons having menu set their popupMode property to QToolButton::InstantPopup (value 2), while buttons without an associated menu keep the default value (QToolButton::DelayedPopup, value 0).
I tried to use such property in different ways as selector, but only the last one (QToolButton[popupMode="2"]) worked:
/* Not working */
QToolButton[popupMode=InstantPopup]:pressed,
QToolButton[popupMode="InstantPopup"]:pressed,
QToolButton[popupMode="QToolButton::InstantPopup"]:pressed,
QToolButton[popupMode="QToolButton--InstantPopup"]:pressed,
QToolButton[qproperty-popupMode=InstantPopup]:pressed,
QToolButton[qproperty-popupMode="InstantPopup"]:pressed,
QToolButton[qproperty-popupMode="QToolButton::InstantPopup"]:pressed,
QToolButton[qproperty-popupMode="QToolButton--InstantPopup"]:pressed,
QToolButton[qproperty-popupMode="2"]:pressed
{
background-color: blue;
}
/* Working */
QToolButton[popupMode="2"]:pressed,
{
background-color: red;
}
(This is a compilation of the options, I've tested them separately).
Documentation mentions that if the enum is declared using Q_ENUM (as ToolButtonPopupMode does), then it should be referenced by name, not by value, but, as it can be seen above, it seems it is not the case for selectors.
Question: Would it be possible to use such enum's name as selector in the stylesheet instead of the enum's value?
Note: I understand that other options such as custom properties with a more expressive, Qt-independant value can make the work too. I'm curious about the possibility of using the enum in the described way.
QToolButton[popupMode=InstantPopup]:pressed is the correct one.
setProperty(<property_name>, QVariant::fromValue(<enum_value>)) for enum class.
setProperty(<property_name>, <enum_value>) for enum.
But you need to reload the style if you want it to change dynamically.
Read about QStyle::unpolish and QStyle::polish.
Related
As a simple example, suppose I have a QPushButton that has some basic styling applied to it using button.setStyleSheet(). Additionally, I want some parts of the style (background color) to change in response to events triggered by the user.
I could simply make calls to button.setStyleSheet() throughout my code, but these will erase pre-existing style attributes. So I would not be able to edit just one styling attribute in response to some signal, rather I would have to specify all style attributes every time the style changes (even if only one or a few style attributes are actually being modified).
I understand this can be done more neatly with the QSS property selector which can apparently be used with "any Qt property that supports QVariant::toString()". This is also described for C++ here: dynamic properties & stylesheets.
So suppose I have a custom widget class, and I want some of its styling to depend (responsively) on a property of my custom class, e.g. a state property. It sounds like I should be able to do something like
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtCore import pyqtProperty
class StatefulWidget(QPushButton):
""" QPushButton colored to reflect its state. """
def __init__(self, state=0):
super().__init__()
self.state = state
self.setStyleSheet('''
StatefulWidget[state=0] {
background-color: red;
}
StatefulWidget[state=1] {
background-color: green;
}
''')
#pyqtProperty(int)
def state(self):
return self._state
#state.setter
def state(self, state):
# Register change of state
self._state = state
# Update displayed style
self.style().polish(self)
but this does not work for me.
Can anyone suggest the proper way to make this work? The intended behavior is that the style should be updated whenever the property changes, but the underlying CSS/QSS should be fixed.
Related:
Update stylesheet without losing original style
The documentation about the QSS property selector says:
You may use this selector to test for any Qt property that supports QVariant::toString()
The QSS parser code is quite complex and somehow cryptic, and I've never been able to completely follow its logic, but I believe that it always tries to convert string values to numbers whenever they contain digits, so the 0 value for the QSS property selector will not match the "0" resulting from toString().
As a general rule, always use quotes around values:
self.setStyleSheet('''
StatefulWidget[state="0"] {
background-color: red;
}
StatefulWidget[state="1"] {
background-color: green;
}
''')
I haven't used ST for some months and I am quite certain that it used to comment/uncomment the entire CSS selector when using ctrl+shift+/ ("toggle block comment") with the cursor inside said selector, but nothing actually selected.
Is anybody aware of what could have caused this behaviour to be replaced with simply adding /* */ around the cursor?
I've tried using SCSS mode(which is what I usually use) and vanilla CSS mode.
Thank you!
There are two bindings for toggling comments, and the one you're using is the one meant for block comments when you probably mean to be using the one for line comments instead. That's not something that's been changed in recent memory.
The keys involved are different depending on platform, but for our purposes here:
Ctrl+/ is bound to toggle_comment with block set to false
Ctrl+Shift+/ is bound to toggle_comment with block set to true
Potentially confusing here is the notion that the /* */ style comments of CSS are actually block comments, which might make you think that you need the second binding.
Actually, the value of the argument controls what gets commented with whatever comment delimiters the support package for the language defines. It's possible for a language (such as C++) to define different comment delimiters for different styles, but that's not required.
When block is set to true, the commented area is the selected text, whereas when it's false it's the line the caret(s) are sitting on.
So, assuming the sample css:
body {
color: red;
}
If the cursor is sitting on the : and you use Ctrl+Shift+/, the result is the following, because the selection is wrapped but the selection is empty (which visually looks like the selection is wrapping the caret).
body {
color/**/: red;
}
On the other hand, with the cursor in the same place and using Ctrl+/ the result is:
body {
/*color: red;*/
}
What I was actually looking for was Emmet's "toggle comment" command which, in the case of CSS, toggles commenting the entire selector. I believe it's with an update to the respective package that the behaviour changed and stopped hooking into ctrl+shift+/, but I could be wrong.
I ended up adding a keyboard shortcut for said command in Preferences > Key Bindings, like so:
{
"keys": ["alt+/"],
"command": "emmet_toggle_comment"
},
I have a website I'm building and I want to have a custom cursors specified for each property like hand, wait, pointer, default, move and so on...
I'm build an operating system website so I want to have custom cursors.
Here is the CSS code.
* {
cursor:url("../.drive/system/visual/cursors/pointer.png"),pointer;
cursor:url("../.drive/system/visual/cursors/hand.cur"),hand;
cursor:url("../.drive/system/visual/cursors/pointer.cur"),default;
cursor:url("../.drive/system/visual/cursors/move.cur"),move;
cursor:url("../.drive/system/visual/cursors/move.cur"),all-scroll;
cursor:url("../.drive/system/visual/cursors/horizontal-resize.cur"),col-resize;
cursor:url("../.drive/system/visual/cursors/horizontal-resize.cur"),e-resize;
cursor:url("../.drive/system/visual/cursors/horizontal-resize.cur"),w-resize;
cursor:url("../.drive/system/visual/cursors/vertical-resize.cur"),row-resize;
cursor:url("../.drive/system/visual/cursors/vertical-resize.cur"),n-resize;
cursor:url("../.drive/system/visual/cursors/vertical-resize.cur"),s-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-1.cur"),se-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-1.cur"),nw-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-2.cur"),sw-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-2.cur"),ne-resize;
cursor:url("../.drive/system/visual/cursors/move.cur"),grab;
cursor:url("../.drive/system/visual/cursors/move.cur"),grabbing;
cursor:url("../.drive/system/visual/cursors/unavailable.cur"),no-drop;
cursor:url("../.drive/system/visual/cursors/unavailable.cur"),not-allowed;
cursor:url("../.drive/system/visual/cursors/text.cur"),vertical-text;
cursor:url("../.drive/system/visual/cursors/text.png"),text;
cursor:url("../.drive/system/visual/cursors/wait.cur"),wait;
cursor:url("../.drive/system/visual/cursors/help.cur"),help;
cursor:url("../.drive/system/visual/cursors/precision-select.cur"),crosshair;
}
The only cursor that happens to load is the one at the bottom (crosshair)
I've also specified some PNG cursors aswell and they did not change the outcome.
I tried putting this into html,body{} and div{} but again nothing worked.
I want something like on Windows93 but without JavaScript
If there is no CSS-only method then I can accept JavaScript ones. But please only vanilla-js.Thanks!
The cursor values are overwriting each other. This means that the last value is the only one that works, as it is the last one to overwrite the cursor value.
The word that follows the URL is a fallback keyword. This means that if the image cannot be found or rendered, the cursor specified by the keyword will be drawn.
For example, with the property cursor: url("../.drive/system/visual/cursors/precision-select.cur"), crosshair;, the browser will attempt to draw the cursor specified in the URL, but if it cannot it will use the default crosshair cursor.
To get the browser to display different cursors you will need to specify the cursor for each element. For your default cursor you would have:
* {
cursor:url("../.drive/system/visual/cursors/pointer.cur"),default;
}
To get a pointer over links you might then do:
a {
cursor:url("../.drive/system/visual/cursors/pointer.png"),pointer;
}
For crosshairs on a particular element you might try:
.target-element {
cursor:url("../.drive/system/visual/cursors/precision-select.cur"),crosshair;
}
You need to specify the cursor property for each element that you wish to have a changed/custom cursor. Using a universal selector for the default cursor ensures that you only specify the property for elements that require it.
My code:
myTextItem = new TextItem();
myTextItem.setHint("Some text");
myTextItem.setShowHintInField(true);
myTextItem.setHintStyle("myTextItemHint");
My css:
.myTextItemHint {
color: gray;
}
My Problem:
My issue is that I can have that setShowHintInField(true) set OR my css getting applied, but not both.
I found more info about this on the link: http://forums.smartclient.com/showthread.php?t=14463 but I cannot come up with a common style / place for it, that would make the trick while the hint is inside the field.
My question:
What kind of css would I need in this case and how I tell the field to use it?
What I have tried:
With that setShowHintInField(true) line and without. Both cases: half of the solution is there. Not both halves.
FormItem has method setCellStyle() to set the style of specific cell.
Use
myTextItem.setCellStyle("myTextItemHint");
your CSS will look like this:
.myTextItemHint, .myTextItemHint input {
color: gray;
}
Override other properties also if needed
.textItem,.textItemFocused,.textItemDisabled,.textItemDisabledHint,.textItemError,.textItemHint
For more information on CSS, Please have a look at skin_styles.css that is already shipped along with standard skins in SmartGWT.
When a drupal form fails validation, it is redrawn with the elements that failed validation surrounded in a red border. Drupal does this by adding the error class to the input elements, and specifing a 2px red border on input.error elements in system.css.
Without modifying this stylesheet, how can I remove the red border on a specific form only, while using the default behavior on the rest of the site?
I believe the solution might require using a custom theme_form_element, but I can't figure out how to customize a single form only.
Note that I would like to do this without having to resort to this jQuery trick (which does work):
$("#edit-name").removeClass('error');
You will need to remove the error class from the form items. This can be done by overwriting the theme functions, in theme_textfield, theme_textarea ... (there is one for each type)
Take a look at $element['#attributes']['class'] which contains the error class.
EDIT
To do it for a specific form element or form you can use the #theme attribute or either form or element you want to change the theming function for.
The easiest way is not to try to modify the markup Drupal is spotting out, but instead to change the styles assocaited with the error class.
You can do that without modifying system.css. Simply add a new stylesheet in your theme (or using an existing one!). Use the Cascading nature of CSS to change the way elements with errors appear. Add something like:
.error {
border: 0;
}
... and you are done.
To target only one specific form, add another selector, like so:
#my-specific-form .error {
border: 0;
}