PyQt Problem mit zweitem Fenster (Unterfenster)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,

Mein Hauptfenster listet Datensätze aus eine Liste auf.
Beim selectieren einer Datenspalte mit anschließendem 'Return', soll sich ein zweites Fenster öffnen, in dem der ausgewählte Datensatz gezeigt wird, um diesen zu bearbeiten der dann im Hauptfenster aktualisiert werden soll.

Hauptfenster und zweites Fenster, funktionieren wenn man diese einzeln aufruft.
Starte ich das Hauptfenster und wähle einen Datensatz aus, öffnet sich das zweite Fenster kurz und schließt sich gleich wieder.

Ich habe meine Code, versucht zu reduzieren.
Für Fehler oder falsche Anwendungsweise, sowie zur Lösung meines Problems, würde ich mich über Euren Input freuen!

Code: Alles auswählen

import sys
import operator  # used for sorting
from PyQt4 import QtCore, QtGui


class DatasetModel(QtGui.QWidget): 

    def __init__(self, title, dataset, header): 
        super(DatasetModel, self).__init__()
        self.setWindowTitle(title)
        self.dataset = dataset
        self.installEventFilter(self)
        self.datasetwidget = QtGui.QWidget(self) 
        self.view = QtGui.QTableView(self.datasetwidget)

        self.button0 = QtGui.QPushButton("Ok", self.datasetwidget)
        self.connect(self.button0, QtCore.SIGNAL('clicked()'), self.take)
        self.button1 = QtGui.QPushButton("Cancel", self.datasetwidget)
        self.connect(self.button1, QtCore.SIGNAL('clicked()'), self.close)

        grid = QtGui.QGridLayout() 
        grid.addWidget(self.view, 0, 0) 
        grid.addWidget(self.button0, 1, 0) 
        grid.addWidget(self.button1, 2, 0)
        self.datasetwidget.setLayout(grid)

        self.model = QtGui.QStandardItemModel(self) 

        # Load dataset
        [self.model.invisibleRootItem().appendRow(
            QtGui.QStandardItem(column)) for column in self.dataset]
        # Vertical header
        [self.model.setHeaderData(i, QtCore.Qt.Vertical, column)
            for i, column in enumerate(header)]

        self.proxy = QtGui.QSortFilterProxyModel(self) 
        self.proxy.setSourceModel(self.model)
        self.view.setModel(self.proxy)

    def take(self):
        self.trueData = True
        self.exec_()
        try:
            sys.exit(app.aboutToQuit.connect(self.closeEvent))
        except NameError:
            self.view.destroy()

    def close(self):
        self.exec_() 
        try:
            sys.exit(app.aboutToQuit.connect(self.closeEvent))
        except NameError:
            sys.quit()

    def exec_(self):
        try:
            self.trueData
            print('RRRRRRRRR', self.dataset)
            return self.dataset
        except AttributeError:
            return []

    def sizeHint(self):
        # and the margins which include the frameWidth and the extra
        # margins that would be set via a stylesheet or something else
        margins = self.contentsMargins()
        # y
        height = round(self.fontMetrics().height() * 1.1)
        height += self.view.verticalHeader().length()
        height += self.view.horizontalHeader().height()
        height += self.view.horizontalScrollBar().height()
        height += margins.left() + margins.right()
        # x
        width = self.view.horizontalHeader().length()
        width += self.view.verticalHeader().width()
        width += self.view.verticalScrollBar().width()
        width += margins.left() + margins.right()

        return QtCore.QSize(width, height)

    def eventFilter(self, widget, event):
        if event.type() == QtCore.QEvent.KeyPress and widget is self:
            key = event.key()
            if key == QtCore.Qt.Key_Escape:
                print('escape')
            else:
                if key in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
                    index = self.view.selectedIndexes()[0].row()
                    value = self.dataset[index]
                    print('value', value)
                return True
        return QtGui.QWidget.eventFilter(self, widget, event)


class Window(QtGui.QWidget):
    def __init__(self, title, dataList, header, *args):
        QtGui.QWidget.__init__(self, *args)
        self.setWindowTitle(title) 
        self.dataList = dataList
        self.header = header
        self.installEventFilter(self)
        self.table_view = QtGui.QTableView()
        self.table_model = TableModel(self, self.dataList, header)
        self.table_view.setModel(self.table_model)
        self.table_view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.table_view)
        self.setLayout(layout)

    def eventFilter(self, widget, event):
        if event.type() == QtCore.QEvent.KeyPress and widget is self:
            key = event.key()
            if key == QtCore.Qt.Key_Escape:
                print('escape')
            else:
                if key in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
                    self.datasetView()
                return True
        return QtGui.QWidget.eventFilter(self, widget, event)

    def datasetView(self):
        mylist = self.table_model.sorted_list()
        self.index = self.table_view.selectedIndexes()[0].row()
        dataset = mylist[self.index]
        view = DatasetModel('DATASET', dataset, self.header)
        view.show()


class TableModel(QtCore.QAbstractTableModel):
    """
    keep the method names
    they are an integral part of the model
    """
    def __init__(self, parent, mylist, header, *args):
        QtCore.QAbstractTableModel.__init__(self, parent, *args)
        self.mylist = mylist
        self.header = header

    def rowCount(self, parent):
        return len(self.mylist)

    def columnCount(self, parent):
        return len(self.mylist[0])

    def data(self, index, role):
        if not index.isValid():
            return None
        elif role != QtCore.Qt.DisplayRole:
            return None
        return self.mylist[index.row()][index.column()]

    def headerData(self, col, orientation, role):
        if (orientation == QtCore.Qt.Horizontal
                and role == QtCore.Qt.DisplayRole):
            return self.header[col]
        return None

    def sorted_list(self):
        return self.mylist


def main():

    title = 'Backlight management'
    header = ['Pos', 'Supplier', 'Artikel']
    dataList = [
        ['001', 'Meyer', '47110'],
        ['002', 'Meyer', '47124'],
        ['003', 'Meyer', '47121']
        ]

    app = QtGui.QApplication(sys.argv)
    app.setApplicationName('TableModel')       # ????
    view = Window(title, dataList, header)
    view.show()
    result = app.exec_()

if __name__ == '__main__':
    main()
Hoffe auf Eure Hilfe, Grüße Nobuddy
Mätti
User
Beiträge: 7
Registriert: Freitag 28. Dezember 2018, 04:57

Hey Nobuddy,

ich kenn mich mit zweiten Fenstern nicht aus, ich arbeite meistens mit Tabs, aber mal sehen, vielleicht finden wir das Problem!
Bei zwei separaten Tabs, die nebeneinander laufen sollen kann ich mir vorstellen, dass das zweite Fenster auf einem neuen thread laufen muss. Ansonsten klingt dein Problem so, als würde was mit der Datenübergabe nicht funktionieren. Starte dein Programm mal aus dem cmd heraus, dann sollte dir das cmd eine Fehlermeldung ausgeben, vielleicht hilft die ja weiter.

LG und gutes Neues Jahr!
Martin
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Mätti: Threads und GUI sind ganz bestimmt nicht das Problem. Die vertragen sich nur unter bestimmten Bedingungen, und gerade die GUI selbst darf NUR aus einem Thread betrieben werden. Oft sogar nur der Main-Thread. Das ist bei Qt definitiv so.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Nobuddy: Listcomprehensions sind nicht dazu da, for-Schleifen zu ersetzen, wenn man gar nichts mit der erzeugten Liste macht. take, close und _exec sind ein einziger Programmierfehler. AttributeError und NameError sollten normalerweise nicht abgefangen werden, weil sie auf Programmierfehler hindeuten und was da mit exit und quit gemacht wird, ist falsch. `app` ist nicht definiert.
Was Du da eigentlich machen willst, macht man mit einem Modal-Fenster.
Antworten