Seite 1 von 1

Signal wird bei Scrollen aktiviert

Verfasst: Dienstag 15. Juni 2010, 00:51
von anogayales
Hi,

ich bin mir nicht sicher ob es ein Bug ist oder ich einfach das ganze falsch verwende:

Jedesmal wenn ich nur die Scrollbalken benutzen will, wird immer das erste Element aus der Tableview selektiert und das entsprechende Signal emitiert.

Ich habe mir mein eigenes Tablemodel definiert:

Ganz primitiv also:

Code: Alles auswählen

class MyTableModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None, text = ""):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self.text = text
        
    def rowCount(self, index):        
        return 200
        
    def columnCount(self, index):
        return 5
        
    def data(self, index, role): 
        if role == QtCore.Qt.DisplayRole:
            return QtCore.QString(self.text)
        return QtCore.QVariant()     
Und jetzt die Hauptanwendung:

Code: Alles auswählen

class Example(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        hbox = QtGui.QHBoxLayout(self)
        self.table = table = QtGui.QTableView(self)
        tablemodel = MyTableModel(text = "mammy mia")
        
        hbox.addWidget(table)
        self.changebutton = QtGui.QPushButton("Change")
        hbox.addWidget(self.changebutton)
        self.changebutton.clicked.connect(self.change)
        self.setLayout(hbox)

        self.setWindowTitle("My table example")
        self.move(250, 200)

    def test(self):
        print "testing"

    def change(self):
        self.table.setModel(MyTableModel(text = "pirlo"))
        self.table.selectionModel().currentRowChanged.connect(self.test)
Hier alles als http://paste.pocoo.org/show/225498/


Um den Fehler zu reproduzieren, muss man lediglich auf "Change" klicken und den Scrollbalken scrollen und schon sieht man das "testing" ausgegeben wird. Dieses Verhalten ist nicht erwünscht, da ja nichts ausgewählt wurde.

Ich hoffe, dass ihr mir helfen könnt, das ganze schnüffelt nämlich hochgradig nach einem Bug oder wie gesagt, ich lese die Doku einfach falsch.

Grüße,
anogayales

Re: Signal wird bei Scrollen aktiviert

Verfasst: Mittwoch 16. Juni 2010, 19:44
von anogayales
Wenn ich in die Funktion, die aufgerufen wird, folgendes mache, klappt es:

Code: Alles auswählen

    def test(self, index, previous):
        if previous.isValid():
              print "testing"
Nur ist es dann nicht möglich das erste Element auszuwählen. Man muss dann erst ein anderes auswählen um das erste Element auswählen zu können und das kann es ja irgendwie nicht sein.

Grüße,
anogayales

Re: Signal wird bei Scrollen aktiviert

Verfasst: Mittwoch 16. Juni 2010, 20:01
von DaMutz

Code: Alles auswählen

def change(self):
        self.table.setModel(MyTableModel(text = "pirlo"))
        self.table.selectionModel().selectionChanged.connect(self.test)
damit wird bei jedem Zellenwechsel ein Signal ausgesendet. Jetzt müsste man in der test Funktion nur noch Filtern ob die selbe Zeile ausgewählt wurde wie beim letzten mal.

Re: Signal wird bei Scrollen aktiviert

Verfasst: Mittwoch 16. Juni 2010, 20:13
von anogayales
Editiert:

Editiert, da falsch :P

Re: Signal wird bei Scrollen aktiviert

Verfasst: Mittwoch 16. Juni 2010, 22:02
von lunar
Lies Current Item and Selected Items, und zwar richtig ...

Das aktuelle Element ist nicht dasselbe wie ein ausgewähltes Element. Es gibt immer ein aktuelles Element, sobald eine Ansicht den Tastaturfokus erhält. Das aktuelle Element markiert nur, wo die Tastatureingabe gerade liegt, und wohin man mit einem Druck auf die Tabulatortaste oder die Pfeiltasten kommen würde. Das aktuelle Element ist nichts anderes als das Pendant zur Positionsmarke aka Cursor in einem Textfeld. Man benutzt das aktuelle Element beispielsweise, wenn man Tastaturkürzel zum Einfügen einer Zeile anbietet. In diesem Fall wäre die logische Position für die eingefügte Zeile direkt nach der aktuellen Position der Tastaturnavigation, also ".selectionModel().currentIndex().row() + 1".

Die ausgewählten Elemente dagegen ändern sich nicht, wenn Du dem Steuerelement den Fokus gibst, denn genau wie in einem Textfeld hat die Auswahl mit der Tastaturnavigation nichts zu tun. Um an die ausgewählten Elemente zu gelangen, muss man allerdings eben auch die Funktionen und Signale verwenden, die mit den ausgewählten Elementen arbeiten. "Auswahl" heißt auf Englisch "selection" und nicht "current". Das Signal, welches Du wohl suchst, ist QItemSelectionModel.selectionChanged.

Re: Signal wird bei Scrollen aktiviert

Verfasst: Mittwoch 16. Juni 2010, 22:24
von anogayales
Vielen Dank!

Das war's! Manchmal sieht man den Wald for lauter Bäumen nicht!


Wie kann ich jetzt einstellen, dass ich die Einträge zwar selektieren kann, nicht aber das hässliche Blau Highlight erscheint.

Ich habe schon probiert mit

Code: Alles auswählen

palette.setColor(QtGui.QPalette.Highlight, QtGui.QColor(0,0,0,0))
zu hantieren, aber er ignoriert einfach den Alphawert.

Ich will einfach, dass nicht angezeigt wird, welches Objekt man ausgewählt hat.

Edit:

Ich hab das ganze jetzt so gelöst:

Code: Alles auswählen

self.tableview.selectionModel().select(QtCore.QModelIndex(), QtGui.QItemSelectionModel.Clear)
            self.tableview.selectionModel().setCurrentIndex(QtCore.QModelIndex(), QtGui.QItemSelectionModel.Clear)
ist aber in keinster Weise schön anzusehen.

Vorschläge?

Grüße,
anogayales

Re: Signal wird bei Scrollen aktiviert

Verfasst: Mittwoch 16. Juni 2010, 23:43
von lunar
Sorry, aber es übersteigt meine Fantasie, dem Ausdruck „hässliches Blau“ ein konkretes Phänomen zuzuordnen. Hässlich ist ziemlich subjektiv, und nicht jedes System hat dasselbe Farbschema wie Windows ... worauf bezieht sich denn nun das „hässliche Blau“? Die Auswahl oder aktuelle Element?

Wenn Du die Auswahl nicht anzeigen möchtest, bleibt Dir nur die Möglichkeit, die Auswahl zu verbieten. Andernfalls wäre das Verstecken der Auswahl sowieso nicht sonderlich sinnvoll, was nutzt eine Auswahl, wenn man sie nicht sehen kann?.

Wenn Du das aktuelle Element nicht anzeigen möchtest, dann kannst Du versuchen, mit ".setFocusPolicy()" zu verhindern, dass die Ansicht den Tastaturfokus entgegen nimmt. Dann allerdings kannst Du in der Ansicht weder mit der Tastatur navigieren, noch Einträge in der Ansicht bearbeiten. Wenn Du diese Möglichkeiten allerdings erhalten möchtest, dann ist es auch nicht sinnvoll, das aktuelle Element nicht anzuzeigen, denn ohne den Kontext dieses Elements sind weder Tastaturnavigation noch Bearbeiten eines Eintrags sinnvoll möglich. Was nutzt Tastaturnavigation, wenn man nicht sieht, wohin man navigiert?

Im Allgemeinen würde ich Dir vor allem raten, nicht gegen das Rahmenwerk zu kämpfen, und die Standards, die es setzt, zu akzeptieren. Das „hässliche Blau“ ist ja nicht dazu da, um Dich zu ärgern, sondern hat einen guten Grund. Wenn Dir die Farbe nicht gewählt, dann ändere sie. Das hat aber nichts mit Qt, sondern mit der Konfiguration Deiner Desktop-Umgebung zu tun.

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 00:22
von anogayales
Qt stellt einem Bereit über QPalette einzelne Elemente nach seinem belieben zu verändern (Farbgebung usw.). Ich will hier also _nicht_ gegen das Rahmenwerk arbeiten, sondern _mit_ dem Rahmenwerk.

Hässliches Blau, da es nicht zu meiner Designvorlage passt und eben unter Windows 7 die Standardfarbe für Highlight ist.

Das Selektieren kann ich nicht verbieten, weil man ja was selektieren soll, blos eben das Selektionshighlight soll nicht angezeigt werden. (siehe http://doc.trolltech.com/4.6/qpalette.html)

Vielen Dank, dennoch, ich habe eine Lösung gefunden, die für meine Ansprüche genügt.

Vielen, vielen Dank nochmal.

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 08:25
von lunar
Da komme ich nicht mit. Wozu ist die Auswahl denn gut, wenn man sie als Nutzer nicht sehen kann?!

QPalette wäre hier im Übrigen auch nicht die richtige Lösung gewesen. Gefällt Dir Farbe Dir persönlich nicht, dann ändere sie in den Systemeinstellungen, nicht im Programm. Gibt es dagegen eine eigene Stilvorlage, einen eigenen Skin für das Programm, dann benutze ein Stylesheet für die Anwendung.

Ohne Deine spezielle Situation zu kennen, würde ich allerdings sagen, dass man auf solche Extras eher verzichten und stattdessen die Integration in die Zielplattform suchen sollte.

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 10:41
von anogayales
Ich habe eine Tabelle, wenn man auf einen Eintrag der Tabelle klickt, wird in einem anderen Widget weitere Information über den ausgewählten Eintrag angezeigt.

Mit Stylesheet kann ich leider nicht das Highlight des ausgewählten Eintrags ändern, dies geht aber mit QPalette ohne Probleme. Aber du hast schon recht, dass es wohl besser ist Konsistent mit anderen System zu arbeiten, über die ich nicht bescheid weiß.

Grüße,
Cauchy

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 11:52
von lunar
Dieser Beitrag erklärt nicht wirklich, von welchem Nutzer die Auswahl ist, wenn sie nicht angezeigt wird. Davon abgesehen kann die Farbe der Auswahl mit Style Sheets ändern (über "selection-background-color").

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 12:11
von ichisich
Du kannst ja in der Methode

Code: Alles auswählen

data() 
und 
role == Qt.BackgroundRole:
Hintergrundfarben für einzelne Zellen, Spalten oder Zeilen bestimmen.
Bei mir (momentan Win 7) ist dann die selektierte Zelle nur zusätzlich mit dem
gepunkteten Rahmen als Markiert gekennzeichnet. Das "hässliche Blau" ( die arme Farbe :cry: ) kommt dann nur noch wenn ich die Zelle Editier also der Wert in der Zelle ist dann schön hässlich blau. Diese Farbe kannst Du dann in deinem Delegate

Code: Alles auswählen

def createEditor(self, parent, option, index):
am Editorobjekt selber wie Lunar schon sagte über Stylsheets mit unhässliche Farben anzeigen lasse ;-)

Hoffe geholfen zu haben ...

Gruß

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 12:19
von anogayales
Vielen Dank lunar!

Ich sehe jetzt endlich auch ein, dass es sinn macht dem Benutzter feedback über seine Auswahl zu geben.

Jetzt will ich eben aber, dass nicht nur eine Zelle der Tabelle ausgewählt wird, sondern die ganze Reihe. Das passt auch dann gut in mein Designkonzept :)
DaMutz hat geschrieben:

Code: Alles auswählen

def change(self):
        self.table.setModel(MyTableModel(text = "pirlo"))
        self.table.selectionModel().selectionChanged.connect(self.test)
damit wird bei jedem Zellenwechsel ein Signal ausgesendet. Jetzt müsste man in der test Funktion nur noch Filtern ob die selbe Zeile ausgewählt wurde wie beim letzten mal.
So, ich hab das bisher so implementiert:

Code: Alles auswählen

    def test(self,selected):
    
        try:
            index = selected.indexes()[0]
            
            same_row = False
            try:
                if self.last_selected_index.row() == index.row():
                    same_row = True
            except AttributeError:
                pass
            
            if not same_row:               
                self.last_selected_index = index                 
                self.table.selectRow(index.row())                         
  
        except IndexError:  
            pass  
Leider will sich nicht die ganze Zeile, also: self.table.selectRow(index.row()) auswählen lassen. Es wird zwar kurz alles ausgewählt aber letztendlich bleibt die letzte Selektion bestehen.


Vielen, vielen Dank für eure bisherige Hilfe. Ich weiß ich frage viel zu viel und mache viel zu wenig selbst, aber ich finde einfach den Fehler nicht.

Grüße,
anogayales

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 12:36
von lunar
Wenn die Auswahl immer zeilenweise vorgenommen werden soll, musst Du das "SelectionBehavior" anpassen:

Code: Alles auswählen

self.table.setSelectionBehavior(QTableView.SelectRows)
Diese Eigenschaft ist im Übrigen dokumentiert, bitte nehme Dir doch einmal die Zeit, die Dokumentation sorgfältig zu lesen.

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 12:39
von ichisich
hier mal ein paar tipps wonach du in der Doku suchen kannst:

Code: Alles auswählen

tableView.setSelectionBehavior(QTableWidget.SelectRows)
und
tableView.selectRow(i)
dazu können noch die Signale passen:

Code: Alles auswählen

tableView, SIGNAL("clicked(QModelIndex)")
oder und
tableView.verticalHeader(), SIGNAL("sectionClicked(int)")
gegebenfalls (ich synchronisiere darüber eine apralleles scrollen von zwei Views:
tableView.verticalScrollBar(), SIGNAL("valueChanged(int)")
Aus allen drei Signalen kommst du an die entsprechende Zeile oder Spalte
(verticalHeader() wäre dann natürlich horizontalHeader() für die Spalte)

Kannst Du die Zeile komplett markieren lassen eben mit :

Code: Alles auswählen

tableView.selectRow(intRow)
oder selectColumn(intColumn)

Re: Signal wird bei Scrollen aktiviert

Verfasst: Donnerstag 17. Juni 2010, 13:41
von anogayales
lunar hat geschrieben:Wenn die Auswahl immer zeilenweise vorgenommen werden soll, musst Du das "SelectionBehavior" anpassen:

Code: Alles auswählen

self.table.setSelectionBehavior(QTableView.SelectRows)
Diese Eigenschaft ist im Übrigen dokumentiert, bitte nehme Dir doch einmal die Zeit, die Dokumentation sorgfältig zu lesen.
Vielen Dank!

Leider verstehe ich dann nicht warum es dann self.table.selectRow(index.row()) gibt, dies aber nicht die komplette Zeile auswählt.

Naja, ich Zukunft werde ich die Doku wohl noch gründlicher lesen müssen!

Grüße,
anogayales