Удаление пунктирной рамки без настройки NoFocus в Windows PyQt - PullRequest
17 голосов
/ 21 марта 2012

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

Сказанная граница в вопросе:

Dotted Focus? Border

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

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

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

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

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

Ответы [ 5 ]

40 голосов
/ 17 августа 2012

Установите outline: 0 желаемого объекта. См. Следующий пример, который устанавливает его для QTableView.

QTableView
{
    outline: 0;
}

Работает для QAbstractItemView унаследованных классов. (QTreeWidget, QTableWidget и т. Д.). Удивительно, но это свойство CSS не упоминается в документации QT. См. Справочная документация таблицы стилей QT.

5 голосов
/ 21 марта 2012

На OSX вы можете сделать QWidget.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False).Не уверен насчет Win или Linux.Возможно, вам придется сделать это через таблицы стилей.

1 голос
/ 20 марта 2019

Пунктирная граница на самом деле меня тоже раздражает.Я много раз гуглю, пытаюсь решить сто раз, но с меньшим успехом.Теперь я хочу обобщить три типичных способа, может быть, вы уже знаете это, но давайте сделаем это более ясным, чтобы вы могли понять, что вам действительно нужно.

Первый QSS
Qss был заявлен как самый простой способрешить проблему.
На самом деле он работает хорошо без полномочий root, но под root он сломался.

table.setStyleSheet("QTableView:{outline: 0;}")

non root privilege
non root privilege

root privilege
root privilege

Так что, если вашему приложению для запуска требуется привилегия root, возможно, QSS вам не подходит.

Во-вторых, FrameSheet/FrameShape
Выглядит будет эффективно, но он будет хорошо работать без привилегий root, как описано выше.

table.setStyleSheet("QTableView:{outline: 0}")
table.setFrameShape(QtWidgets.QFrame.NoFrame)

Третье NoFocusDelegate наследование.
Это отличный метод, он решает проблему привилегия не имеет значения

class NoFocusDelegate(QtWidgets.QStyledItemDelegate):
    def paint(self, QPainter, QStyleOptionViewItem, QModelIndex):
        if QStyleOptionViewItem.state & QtWidgets.QStyle.State_HasFocus:
            QStyleOptionViewItem.state = QStyleOptionViewItem.state ^ QtWidgets.QStyle.State_HasFocus
        super().paint(QPainter, QStyleOptionViewItem, QModelIndex)

table.setItemDelegate(NoFocusDelegate())

Этот метод поможет мне избавиться от тайны пунктирной границы, надеюсь, она вам тоже пригодится.

1 голос
/ 05 апреля 2012

Большинство стилей делегируют отрисовку индикатора фокуса функции 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 для некоторых виджетов (кнопок, выпадающих списков), поэтому он также может не работать для Windows или Mac.

0 голосов
/ 06 июня 2016

Вы можете сделать это с 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())
...