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

时间:2012-03-20 22:09:56

标签: qt pyqt focus border

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

有问题的边界:

Dotted Focus? Border

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

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

这是另一个例子:

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

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

5 个答案:

答案 0 :(得分:40)

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

QTableView
{
    outline: 0;
}

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

答案 1 :(得分:5)

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

答案 2 :(得分: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。

答案 3 :(得分:1)

虚线边框实际上也惹恼了我。我用Google搜寻了很多遍,尝试解决了上百遍,但是收效甚微。现在,我想总结一下您可能已经知道的三种典型方式,但是让我们更清楚地了解您的真正需求。

第一个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())

这种方法可以帮助我摆脱虚线的边界之谜,希望对您也有帮助。

答案 4 :(得分:0)

您可以使用PyQt5执行此操作:

mu