Удаление пунктирной рамки без установки NoFocus в Windows PyQt
Есть несколько вопросов по поводу этого, все из которых, похоже, говорят, что единственный способ удалить пунктирную границу - чтобы установить focusPolicy на виджет/элемент, о котором идет речь, NoFocus. Хотя это работает как временное исправление, это препятствует дальнейшему взаимодействию с указанным виджетами/элементами в области других необходимых фокусов.
Указанная граница:
![Dotted Focus? Border]()
Вот пример того, почему это не работает.
- У меня есть всплывающее окно немодального виджета, подумайте о лайтбоксе для изображения.
- Я хочу обнаружить mousePressEvent за пределами виджета и закрыть виджет в результате. Чтобы сделать это, я должен поймать focusOutEvent.
- Однако, если подавляющее большинство виджетов в моей программе настроено как NoFocus (чтобы удалить проблему с границей), тогда я не могу поймать focusOutEvent, потому что, как вы догадались, у них нет политики фокуса.
Вот еще один пример:
- У меня есть QTreeWidget, который является подклассом, поэтому я могу поймать keyPressEvents по разным причинам.
- QTreeWidget также установлен как NoFocus для предотвращения границы. Из-за этого, однако, виджет никогда не имеет фокуса, и поэтому никакие keyPressEvents не могут быть пойманы.
- Обходной путь для этого (kludgy, imo) заключается в использовании класса widget grabKeyboard, что опасно, если я забуду освободитьKeyboard позже. Это не оптимально.
Итак, вопрос в том, есть ли способ удалить эту странную (в основном просто уродливую) пунктирную рамку, не отключая фокус для всего, что есть в моем приложении? Спасибо заранее!
Ответы
Ответ 1
Установите outline: 0
нужного объекта. См. Следующий пример, который устанавливает его для QTableView
.
QTableView
{
outline: 0;
}
Работает для QAbstractItemView
унаследованных классов. (QTreeWidget, QTableWidget
и т.д.). Удивительно, но это свойство CSS не упоминается в документации QT. См. Документация о стиле листа QT.
Ответ 2
В OSX вы можете делать
QWidget.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False)
. Не уверен в Win или Linux. Возможно, вам придется делать это через таблицы стилей.
Ответ 3
Большинство стилей делегируют рисунок индикатора фокусировки функции QStyle::drawPrimitive
с PE_FrameFocusRect
в качестве элемента для рисования.
Таким образом, вы можете отключить глобально со следующим классом стиля, установленным на экземпляре приложения:
class NoFocusProxyStyle : public QProxyStyle {
public:
NoFocusProxyStyle(QStyle *baseStyle = 0) : QProxyStyle(baseStyle) {}
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const {
if(element == QStyle::PE_FrameFocusRect) {
return;
}
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setStyle(new NoFocusProxyStyle);
...
PS: он не работает с QGtkStyle
для некоторых виджетов (кнопок, combobox), поэтому он может не работать и для Windows, и для Mac.
Ответ 4
Вы можете сделать это с помощью PyQt5:
class Style(QProxyStyle):
def drawPrimitive(self, element, option, painter, widget):
if element == QStyle.PE_FrameFocusRect:
return
super().drawPrimitive(element, option, painter, widget)
app.setStyle(Style())