Удаление пунктирной рамки без установки NoFocus в Windows PyQt - программирование
Подтвердить что ты не робот

Удаление пунктирной рамки без установки NoFocus в Windows PyQt

Есть несколько вопросов по поводу этого, все из которых, похоже, говорят, что единственный способ удалить пунктирную границу - чтобы установить focusPolicy на виджет/элемент, о котором идет речь, NoFocus. Хотя это работает как временное исправление, это препятствует дальнейшему взаимодействию с указанным виджетами/элементами в области других необходимых фокусов.

Указанная граница:

Dotted Focus? Border

Вот пример того, почему это не работает.

  • У меня есть всплывающее окно немодального виджета, подумайте о лайтбоксе для изображения.
  • Я хочу обнаружить mousePressEvent за пределами виджета и закрыть виджет в результате. Чтобы сделать это, я должен поймать focusOutEvent.
  • Однако, если подавляющее большинство виджетов в моей программе настроено как NoFocus (чтобы удалить проблему с границей), тогда я не могу поймать focusOutEvent, потому что, как вы догадались, у них нет политики фокуса.

Вот еще один пример:

  • У меня есть QTreeWidget, который является подклассом, поэтому я могу поймать keyPressEvents по разным причинам.
  • QTreeWidget также установлен как NoFocus для предотвращения границы. Из-за этого, однако, виджет никогда не имеет фокуса, и поэтому никакие keyPressEvents не могут быть пойманы.
  • Обходной путь для этого (kludgy, imo) заключается в использовании класса widget grabKeyboard, что опасно, если я забуду освободитьKeyboard позже. Это не оптимально.

Итак, вопрос в том, есть ли способ удалить эту странную (в основном просто уродливую) пунктирную рамку, не отключая фокус для всего, что есть в моем приложении? Спасибо заранее!

4b9b3361

Ответ 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())