2012-03-20 5 views
16

Ci sono alcune domande su SO in merito a ciò, che sembrano dire che l'unico modo per rimuovere il bordo punteggiato è to set the focusPolicy on widget/item in question to NoFocus. Anche se questo funziona come una soluzione temporanea, questo impedisce ulteriori interazioni con il widget/oggetto nel regno di altri focusEvents necessari.Rimozione del bordo punteggiato senza impostazione NoFocus in Windows PyQt

Detto frontiera in questione:

Dotted Focus? Border

Ecco un esempio del perché questo non funziona.

  • Ho un popup di widget non modali, penso a una lightbox per un'immagine.
  • Voglio rilevare un mousePressEvent al di fuori del widget e chiudere il widget come risultato. Per fare questo, dovrei catch the focusOutEvent.
  • Tuttavia, se una vasta maggioranza di widget nel mio programma sono impostati come NoFocus (per rimuovere il problema del bordo), non riesco a prendere il focusOutEvent perché, avete indovinato, non hanno alcuna politica di messa a fuoco.

Ecco un altro esempio:

  • Ho un QTreeWidget che è una sottoclasse in modo da poter prendere keyPressEvents per vari motivi.
  • QTreeWidget viene impostato anche come NoFocus per impedire il bordo. Per questo motivo, tuttavia, il widget non ha mai il focus e quindi non è possibile catturare keyPressEvents.
  • Una soluzione per questo (kludgy, imo) è a use the widget's grabKeyboard class, che è pericoloso se mi dimentico di rilasciareKeyboard in seguito. Questo non è ottimale.

Quindi la domanda è, c'è un modo per rimuovere questo bordo punteggiato strano (per lo più solo brutto) senza disattivare l'attenzione per tutto nella mia app? Grazie in anticipo!

+0

Quale sistema operativo utilizzate? – jdi

+0

Windows (7), ho paura. – Cryptite

+0

Bene, potreste essere interessati a un paintEvent personalizzato: -/ – jdi

risposta

37

Impostare outline: 0 dell'oggetto desiderato. Fare riferimento all'esempio seguente che lo imposta per un QTableView.

QTableView 
{ 
    outline: 0; 
} 

Lavori per classi ereditate QAbstractItemView. (QTreeWidget, QTableWidget ecc.). Sorprendentemente questa proprietà CSS non è menzionata nella documentazione QT.Vedere QT Style Sheet Reference Documenation.

+5

Santo dio, basta così. Attaccalo sul tuo stile QTreeView e sei d'oro. – Cryptite

+1

Funziona anche per le classi di ereditarietà QAbstractButton, ad es. QPushButton, QRadioButton e QCheckBox. Lo ho usato nella mia applicazione Qt C++ proprio ora. Grande! – Sumyrda

+0

Mio signore mi ha salvato la giornata, questo ha portato il mio qpushbutton al livello successivo mentre i miei pulsanti sono stretti ei punti coprivano il testo. Piccola e ovvia nota per coloro che non leggono tra le righe, "outline: 0;" viene aggiunto direttamente nelle proprietà qstylesheet. Grazie! – JavaBeast

3

Su OSX è possibile eseguire QWidget.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False). Non sono sicuro di Win o Linux. Potrebbe essere necessario farlo attraverso i fogli di stile.

+0

Solo per puro divertimento, ho provato a impostarlo, ma come potete immaginare non ha fatto nulla per me in Windows. Sono andato avanti e ho messo una taglia nel tentativo di attirare più attenzione su questo. Grazie per l'aiuto jdi in ogni caso. L'app che sto scrivendo avrà una porta Mac prima possibile, quindi sarà comunque utile. – Cryptite

1

Molti stili delegano il disegno dell'indicatore di messa a fuoco alla funzione QStyle::drawPrimitive con PE_FrameFocusRect come elemento da disegnare.

Così si dovrebbe essere in grado di disabilitare che a livello mondiale con la seguente classe di stile installata sul istanza di applicazione:

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: Non funziona con QGtkStyle per alcuni widget (pulsanti, ComboBox), in modo da potrebbe non funzionare anche per Windows o Mac.

+0

Dovrò vedere se non riesco a convertirlo in python per PyQT, ma ci provo. – Cryptite

+0

@Cryptite: non funziona con PyQt (o PySide) perché la classe 'QProxyStyle' non viene esportata in python. E poiché gli stili specifici ('QWindowsStyle',' QWindowsXPStyle' ...) non vengono esportati, non puoi semplicemente sovrascrivere quella funzione nello stile corrente (ho provato anche la patch delle scimmie, per sostituire drawPrimitive sul 'QApplication.style() ', ma non sono sicuro di averlo fatto correttamente). – alexisdm

+0

Quindi la trama si addensa. Ci deve essere un modo per raggiungere questo obiettivo. Qualcuno nell'oscurità dell'interwebs deve aver risolto questo problema. – Cryptite

0

Si può fare questo con 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()) 
+0

Questa non è una soluzione eccezionale in quanto fa sì che un QTableWidget subisca un ritardo significativo. – Kermit