删除虚线边框而不在Windows PyQt中设置NoFocus

问题描述 投票:17回答:5

关于这一点,有几个问题,所有这些似乎都说,删除虚线边框的唯一方法是to set the focusPolicy on widget/item in question to NoFocus。虽然这可以作为临时修复,但这可以防止在其他必要的focusEvents领域与所述小部件/项目进一步交互。

所述边界有问题:

这是为什么这不起作用的一个例子。

  • 我有一个非模态小部件弹出窗口,想象一个图像的灯箱。
  • 我想在窗口小部件外部检测mousePressEvent并因此关闭窗口小部件。要做到这一点,我应该catch the focusOutEvent
  • 但是,如果我的程序中的绝大多数小部件被设置为NoFocus(以消除边界问题),那么我无法捕获focusOutEvent,因为您猜对了,它们没有焦点策略。

这是另一个例子:

  • 我有一个子类的QTreeWidget,所以我可以出于各种原因捕获keyPressEvents。
  • QTreeWidget也设置为NoFocus以防止边框。但是,由于这个原因,小部件永远不会有焦点,因此不能捕获keyPressEvents。
  • 这个(kludgy,imo)的解决方法是use the widget's grabKeyboard class,如果我忘记稍后释放Keyboard,这是危险的。这不是最佳选择。

那么问题是,有没有办法删除这个奇怪的(大多数只是丑陋的)虚线边框而不关闭我的应用程序中的所有内容的焦点?提前致谢!

qt pyqt focus border
5个回答
40
投票

设置所需对象的outline: 0。请参阅以下示例,该示例将其设置为QTableView

QTableView
{
    outline: 0;
}

适用于QAbstractItemView继承的课程。 (QTreeWidget, QTableWidget等)。令人惊讶的是,QT文档中未提及此CSS属性。见QT Style Sheet Reference Documenation.


5
投票

在OSX上你可以做QWidget.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False)。关于Win或Linux不确定。您可能必须通过样式表来完成。


1
投票

大多数样式将焦点指示符的绘图委托给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。


1
投票

虚线边框实际上也让我恼火。我谷歌多次,尝试大约一百次来解决它,但成功率较低。现在我想总结三种典型的方式,也许你已经知道它,但让我们更清楚,这样你才能理解你真正需要的东西。

首先QSS Qss被认为是解决问题最简单的方法。 实际上它在非root权限下工作得很好,但在root下它就破坏了。

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

non 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())

这种方法帮助我摆脱虚线边框的神秘感,我希望它对你也有帮助。


0
投票

你可以用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())
© www.soinside.com 2019 - 2024. All rights reserved.