Question sur une fonction

Le problème exposé dans ce sujet a été résolu.

Bonjour a tous, alors voila mon soucie, j'ai creer une fonction qui me permet de charger un fichier et de l'afficher dans un nouvelle onglet, lorsque j'ai aucun onglet d'ouvert tout marche mais le hic c'est lorsque que j'ai deja un onglet d'ouvert, ma fonction ouvre un nouvelle onglet avec le nom du fichier, mais toute les donnees de ce fichier son afficher a la suite de mon premier onglet.Du coup je viens demander votre aides car je vois pas du tout ce qui cloche dans ma foncion donc si quel qu'un pourait m'expliquer pourquoi ca me serais d'une grande aide! ^^

1
2
3
4
5
6
7
8
9
    def ShowFile(self):
        filename = QFileDialog.getOpenFileName(self, 'Open File', '')
        for F in filename.split('/') :
            NameFile = []
            NameFile.append(F)
        NameFile.reverse()
        self.tab_widget.addTab(Conf_Tab(self),NameFile[0])
        widget = self.tab_widget.currentWidget()
        widget.read_data(filename)

Le programme complet dans la balise spoil si cela peut etre utile.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
import sys,os
import itertools
import inspect
import glob
import BINoculars.util, BINoculars.main
import time
from PyQt4.QtGui import *
from PyQt4.QtCore import *



class SimpleGUI(QMainWindow):

    def __init__(self):
        super(SimpleGUI, self).__init__()
        self.initUI()
        self.tab_widget = QTabWidget(self)
        self.setCentralWidget(self.tab_widget)
        close = self.tab_widget.setTabsClosable(True)
        self.tab_widget.tabCloseRequested.connect(self.close_tab)

    def close_tab(self, tab):
        self.tab_widget.removeTab(tab)

    def initUI(self):
        openFile = QAction('Open', self)
        openFile.setShortcut('Ctrl+O')
        openFile.setStatusTip('Open new File')
        openFile.triggered.connect(self.ShowFile)

        saveFile = QAction('Save', self)
        saveFile.setShortcut('Ctrl+S')
        saveFile.setStatusTip('Save File')
        saveFile.triggered.connect(self.Save)

        Create = QAction('Create', self)
        Create.setStatusTip('Create new configuration')
        Create.triggered.connect(self.New_Config)


        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(openFile)
        fileMenu.addAction(saveFile)
        fileMenu = menubar.addMenu('&New Configuration')
        fileMenu.addAction(Create)


        palette = QPalette()
        palette.setColor(QPalette.Background,Qt.gray)
        self.setPalette(palette)
        self.setGeometry(250, 100,500,500)
        self.setWindowTitle('Binoculars')
        self.setWindowIcon(QIcon('binoculars.png'))
        self.show()

    def ShowFile(self):
        filename = QFileDialog.getOpenFileName(self, 'Open File', '')
       for F in filename.split('/') :
            NameFile = []
            NameFile.append(F)
        NameFile.reverse()
        self.tab_widget.addTab(Conf_Tab(self),NameFile[0])
        widget = self.tab_widget.currentWidget()
        widget.read_data(filename)


    def Save(self):
        filename = QFileDialog().getSaveFileName(self, 'Enregistrer', '', '*.txt')
        widget = self.tab_widget.currentWidget() 
        widget.save(filename) 
        
    def New_Config(self):
        self.tab_widget.addTab(Conf_Tab(self),'New configuration')



class Table(QWidget):
    def __init__(self, parent = None):
        super(Table, self).__init__()
        
       # create a QTableWidget
        self.table = QTableWidget(1, 2, self)
        self.table.setHorizontalHeaderLabels(['Parameter', 'Value','Comment'])
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.verticalHeader().setVisible(False)
        
        #create combobox
       self.combobox = QComboBox()
        #add items
        self.cell = QTableWidgetItem(QString("type"))
        self.table.setItem(0, 0,self.cell)
        self.table.setCellWidget(0, 1, self.combobox)
        #we create pushbuttons and we call the method when we clic on 
        self.btn_add_row = QPushButton('+', self)
        self.connect(self.btn_add_row, SIGNAL('clicked()'), self.add_row)
        self.buttonRemove = QPushButton('-',self)
        self.connect(self.buttonRemove, SIGNAL("clicked()"), self.remove)
        self.btn_add_row.resize(10,10)
        self.buttonRemove.resize(10,10) 
        #the dispositon of the table and the butttons
        layout =QGridLayout()
        layout.addWidget(self.table,1,0,1,0)
        layout.addWidget(self.btn_add_row,0,0)
        layout.addWidget(self.buttonRemove,0,1)
        self.setLayout(layout)

    def add_row(self):
        self.table.insertRow(self.table.rowCount())
    
    def remove(self):
        self.table.removeRow(self.table.currentRow()) 

    def get_keys(self):
        return list(self.table.item(index,0).text() for index in range(self.table.rowCount())) 


    def getParam(self):#Here we take all values on tables
        for index in range(self.table.rowCount()):
            key = str(self.table.item(index,0).text())
            comment = str(self.table.item(index,0).toolTip())
            if self.table.item(index,1):
                value = str(self.table.item(index, 1).text())
            else:
                value = str(self.table.cellWidget(index, 1).currentText())
            if self.table.item == None:
                value = str(self.table.item(index,1).text(""))
            yield key, value, comment
        
    def addData(self, data):#Here we put all values on tables
        for item in data:
            if item[0] == 'type':
                box = self.table.cellWidget(0,1)
                box.setCurrentIndex(box.findText(item[1], Qt.MatchFixedString))
                self.cell.setToolTip(item[2])
            else: 
                self.add_row()
                row = self.table.rowCount()
               for col in range(self.table.columnCount()):
                    self.newitem = QTableWidgetItem(item[col])
                    self.table.setItem(row -1, col, self.newitem)
                    self.newitem.setToolTip(item[2])
                        

    def addDataConf(self, items):
        keys = self.get_keys()
        newconfigs = list([item[0], '', item[1]] for item in items if item[0] not in keys)
        self.addData(newconfigs)
                
    def add_to_combo(self, items):
        self.combobox.clear()
        self.combobox.addItems(items)
    


class Conf_Tab(QWidget):
    def __init__(self, parent = None):

        super(Conf_Tab,self).__init__()
        #we create 3 tables
        self.Dis = Table()
        self.Inp = Table()
        self.Pro = Table()

        label1 = QLabel('<strong>Dispatcher</strong>')
        label2 = QLabel('<strong>Input</strong>')
        label3 = QLabel('<strong>Projection<strong>')

        self.select = QComboBox()
        backends = list(backend.lower() for backend in BINoculars.util.get_backends())
        #we add the list of different backends on the select combobox
        self.select.addItems(QStringList(backends))
        self.start = QPushButton('run')
        self.connect(self.start, SIGNAL("clicked()"), self.run)
        self.scan = QLineEdit()
        self.start.setStyleSheet("background-color: darkred")

        #the dispositon of all elements of the gui
        Layout = QGridLayout()
        Layout.addWidget(label1,0,2)
        Layout.addWidget(label2,0,1)
        Layout.addWidget(label3,0,3)
        Layout.addWidget(self.select,0,0)
        Layout.addWidget(self.Dis,1,2)
        Layout.addWidget(self.Inp,1,1)
        Layout.addWidget(self.Pro,1,3) 
        Layout.addWidget(self.start,2,0)
        Layout.addWidget(self.scan,2,1)
        self.setLayout(Layout)| 
 
        self.Dis.add_to_combo(QStringList(BINoculars.util.get_dispatchers()))
        self.select.activated['QString'].connect(self.DataCombo)
        self.Inp.combobox.activated['QString'].connect(self.DataTableInp)
        self.Pro.combobox.activated['QString'].connect(self.DataTableInpPro)
        self.Dis.combobox.activated['QString'].connect(self.DataTableInpDis)
        

    def DataCombo(self,text):
        self.Inp.add_to_combo(QStringList(BINoculars.util.get_inputs(str(text))))
        self.Pro.add_to_combo(QStringList(BINoculars.util.get_projections(str(text))))

    def DataTableInp (self,text):
        backend = str(self.select.currentText())
        inp = BINoculars.util.get_input_configkeys(backend, str(self.Inp.combobox.currentText()))
        self.Inp.addDataConf(inp)

    def DataTableInpPro (self,text):
        backend = str(self.select.currentText())
        proj = BINoculars.util.get_projection_configkeys(backend, str(self.Pro.combobox.currentText()))
        self.Pro.addDataConf(proj)

    def DataTableInpDis (self,text):
        backend = str(self.select.currentText())
        disp = BINoculars.util.get_dispatcher_configkeys(str(self.Dis.combobox.currentText()))
        self.Dis.addDataConf(disp)

 
    def save(self, filename): 
        with open(filename, 'w') as fp:
            fp.write('[dispatcher]\n')
            for key, value, comment in self.Dis.getParam():# cycles over the iterator object
                fp.write('{0} = {1} #{2}\n'.format(key, value, comment))
            fp.write('[input]\n')
            for key, value, comment in self.Inp.getParam():
                if key == 'type':
                    value = '{0}:{1}'.format(self.select.currentText(),value)
                fp.write('{0} = {1} #{2}\n'.format(key, value, comment))
            fp.write('[projection]\n')
            for key, value, comment in self.Pro.getParam():
                if key == 'type':
                    value = '{0}:{1}'.format(self.select.currentText(),value)
                fp.write('{0} = {1} #{2}\n'.format(key, value, comment))

    def get_configobj(self):

        inInp = {}
        inDis = {}
        inPro = {}

        InDis = dict((key, value) for key, value, comment in self.Dis.getParam())

        for key, value, comment in self.Inp.getParam():
            if key == 'type':
                value = '{0}:{1}'.format(self.select.currentText(),value)
            inInp[key] = value 

        for key, value, comment in self.Pro.getParam():
            if key == 'type':
                value = '{0}:{1}'.format(self.select.currentText(),value)
            inPro[key] = value

        cfg = BINoculars.util.ConfigFile('gui {0}'.format(time.strftime('%d %b %Y %H:%M:%S', time.localtime())))
        setattr(cfg, 'input', inInp)
        setattr(cfg, 'dispatcher', inDis)
        setattr(cfg, 'projection', inPro)
        return cfg


    def read_data(self,filename):
        with open(filename, 'r') as inf:
            lines = inf.readlines()
 
        data = {'dispatcher': [], 'input': [], 'projection': []}
        for line in lines:
            line = line.strip('\n')
            if '[dispatcher]' in line:
                key = 'dispatcher'
            elif '[input]' in line:
                key = 'input'
            elif '[projection]' in line: 
                key = 'projection'
            else:
                if '#' in line:
                    index = line.index('#')
                    caput = line[:index]
                    cauda = line[index:]
                else:
                    caput = line
                    cauda = ''
                if '=' in caput:
                    name, value = caput.split('=')
                    if name.strip(' ') == 'type' and ':' in value:
                        backend, value = value.strip(' ').split(':')
                    data[key].append([name.strip(' '), value.strip(' '), cauda.strip(' ')])

        self.select.setCurrentIndex(self.select.findText(backend, Qt.MatchFixedString))
        self.DataCombo(backend)

        for key in data:
            if key == 'dispatcher':
                self.Dis.addData(data[key])
            elif key == 'input':
                self.Inp.addData(data[key])
            elif key == 'projection':
                self.Pro.addData(data[key])

                
    def run(self):
        command = [str(self.scan.text())]
        cfg = self.get_configobj()
        BINoculars.main.Main.from_object(cfg, command)

Première remarque : un nom de fonction en Python est normalement de la forme aaa_bbb_ccc (snake_case). Comme PyQt utilie le camelCase, il n'est pas absurde d'adopter cette convention, mais du coup tu as showFile. ShowFile serait pour une classe.

Cela vaut aussi pour les noms de variables.

Sinon, tu as sûrement un problème dans ta boucle : seul le dernier tour est pris en compte vu que tu initialises ta liste à l'intérieur. D'ailleurs, un name_file = filename.split('/') suffit.

Après ça, le bug est-il toujours présent ?

+0 -0

Oui le bug est toujours present, en fait ma boucle sert juste a recuper le dernier element du path qui est le fichier, pour l'avoir comme nom pour l'onglet.

Je pense que le soucie viens plus de quand je declare widget et que je lui applique la fonction read_data.Mais la encore je ne comprend pas pourquoi car ce bug n'arrive que lorsque j'ai deja un onglet d'ouvert…

Pour récupérer le dernier élément, tu peux simplement faire :

1
tab_name = filename.split('/')[-1]

Sinon, ton problème provient du fait qu'ajouter un onglet à un QTabWidget ne rend pas cet onglet actif. Du coup, ta ligne 8 te retourne le premier onglet.

Si on regarde la doc, addTab te retourne l'indice de l'onglet ajouté. Il ne te reste plus qu'à récupérer le widget associé (l'onglet que tu viens de créer) via cette méthode.

+1 -0

addTab te renvois l'index du nouveau tab. Plutot que de prendre le currentWidget qui du coup n'est pas le dernier créé.

Avant de récupérer le widget courant, tu devrais faire un setCurrentIndex(...) en utilisant cette valeur pour sélectionner le dernier tab créé et ainsi ton currentWidget sera le bon.

Vayel je ne comprend pas trop la methode que tu me proposes, sinon Kje j'ai suivis ton conseille et utilisé setCurrentIdex().

Le resultat est meilleur, seulement je pense pas l'utiliser de la bonne maniere car pour que cela marche lorsque je charge un fichier il faut que je sois sur le dernier onglet.

1
2
3
4
        currentIndex = self.tab_widget.currentIndex()
        self.tab_widget.setCurrentIndex(currentIndex + 1)
        widget = self.tab_widget.currentWidget()
        widget.read_data(filename) 

d'ou ma prochaine question est ce qu'il y'a une maniere pour avoir l'index de tout les onglets ?

+0 -0

filename.split('/') te sépare chaque partie de ton chemin dans une liste, [-1] te renvoie le dernier element d'une liste, donc filename.split('/')[-1] te renvoie le nom de ton fichier.

Sinon, dans le code que tu nous donne, tu n'utilise pas le retour de la fonction addTab alors que c'est elle qui va te retourner l'index auquel te veux te positionner. Ici tu ne fait que te déplacer d'un onglet (ce qui marche donc lorsque tu était sur le dernier, puisque tu va en créer un nouveau avec un index supérieur de 1 et te déplacer dessus).

Il faut donc se positionner au bon endroit dans tous les cas :

1
2
newIndex =  self.tab_widget.addTab(Conf_Tab(self),NameFile[0])
self.tab_widget.setCurrentIndex(newIndex)

Avec ça tu crée un nouvel onglet et tu positionne dessus.

Question peut-être bête, mais est-il prévu une sortie au cas où l'utilisateur appuie sur Cancel au lieu de sélectionner un fichier ?

Parce-que si je teste,

1
2
3
4
5
6
>>> from PyQt4.QtCore import QString
>>> QString("").split('\')
  File "<stdin>", line 1
    QString("").split('\')
                         ^
SyntaxError: EOL while scanning string literal

Je pense qu'il faut tester si la chaîne est vide

1
2
>>> QString("").isEmpty()
True
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte