IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Comment ne pas exécuter deux fois la même application


Sujet :

PyQt Python

  1. #1
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 320
    Points : 204
    Points
    204
    Par défaut Comment ne pas exécuter deux fois la même application
    Bonjour à tous,

    Afin de parfaire mon apprentissage de PySide6, je me suis fait une petite application genre "Lecteur vidéo".
    Je peux ouvrir une vidéo, la lire et en charger une autre etc....

    J'ai par la suite compilé le code avec Nuitka pour obtenir un fichier exécutable sous windows. Là encore, tout fonctionne bien. En exécutant le fichier, je peux faire la même chose qu'en "version" Python.

    Je peux aussi ouvrir une vidéo, avec le "Ouvrir Avec" de windows.

    Par contre, j'ai un problème : Si une vidéo est en train d'être lue, et que par ailleurs, je lance une autre vidéo avec un "Ouvrir Avec....", cela me crée une seconde instance de mon app.

    Comment puis-je faire pour que le lancement de ma seconde vidéo se déroule dans le même processus en lieu et place de la première.

    JE suis allé voir QCoreApplication.instance(), mais je ne sais si je fais fausse route.

    J'espère que vous aurez des informations qui pourraient m'aider.

    Bonne journée à tous.
    Douter de tout, toujours, et surtout de soi-même...

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Salut,

    Citation Envoyé par FadeToBlack Voir le message
    Comment puis-je faire pour que le lancement de ma seconde vidéo se déroule dans le même processus en lieu et place de la première.
    Il faut détecter que l'application est déjà lancé et avoir une porte pour lui communiquer d'arrêter la vidéo en cours pour démarrer la nouvelle.
    C'est juste de la programmation.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 320
    Points : 204
    Points
    204
    Par défaut
    Bonjour wiztricks,

    Je pensais effectivement faire une chose de la sorte. Mais je n'arrive pas à la mettre en pratique et surtout comment.
    Douter de tout, toujours, et surtout de soi-même...

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Citation Envoyé par FadeToBlack Voir le message
    Mais je n'arrive pas à la mettre en pratique et surtout comment.
    Certes mais est ce une question de programmation python?
    Cherchez du côté de QtSingleApplication, cela devrait vous donner des idées... la plus simple étant de démarrer la première application avec un serveur (socket), la deuxième qui essaiera de démarrer le service plantera (le port est utilisé).... et on a une socket pour dialoguer avec l'application déjà démarrée.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 320
    Points : 204
    Points
    204
    Par défaut
    j'ai essayé un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import sys
     
    from PySide6.QtCore import QCoreApplication
    from PySide6.QtWidgets import QApplication
    from src.emp import Emp
     
    if __name__ == '__main__':
     
        if QCoreApplication.instance() is None:
            print("Pas d'instance est ouverte")
            app = QApplication(sys.argv)
            if len(sys.argv) < 2:
                # Création de ma fenêtre de lecture vidéo
                main = Emp()
            else:
                main = Emp(sys.argv[1])
            main.show()
        else:
            print("Une instance est ouverte")
            Emp.open_file_with_parameters(sys.argv[1])
        print(sys.argv)
        app.setStyle("Fusion")
        app.exec()
    Mais cela m'ouvre quand même un seconde fenêtre
    Douter de tout, toujours, et surtout de soi-même...

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Citation Envoyé par FadeToBlack Voir le message
    j'ai essayé un truc du genre :
    ...
    Mais cela m'ouvre quand même un seconde fenêtre
    A partir du moment où vous utilisez des interfaces documentées, vous êtes supposé avoir lu la documentation et plus ou moins compris que ça pourrait le faire.
    Si ça ne le fait pas, c'est que vous utilisez mal le truc ou que ca ne pourra pas résoudre le problème: à vous de relire la documentation et de dire pourquoi vous espérez que çà marche...

    Je vous ai suggéré une autre approche.
    A vous de voir...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 245
    Points : 4 742
    Points
    4 742
    Par défaut
    Si tu désires "juste" bloquer une nouvelle "même application", existe une solution simple avec QT (A voir si bon lorsque plantages)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/usr/bin/env python
    import sys
    from PySide6.QtCore import QSharedMemory
    from PySide6.QtWidgets import QApplication, QComboBox
     
    if __name__ == '__main__':
     
        sharedMemory = QSharedMemory('MaSignatureUniqueDeMonApp')
        if not sharedMemory.create( 64, QSharedMemory.ReadWrite):
            print("Déja ouvert !")  # ou ...
            exit(66)
        try:
            app = QApplication(sys.argv)
            main = QComboBox()
            main.show()
            app.exec()
        finally:
            sharedMemory.detach()
    Mais, ce que tu demandes est beaucoup plus compliqué. La réponse #4 est claire :
    - Transformer ton application en serveur
    - si "serveur" détecté (un "ping" au serveur), alors lui envoyer une commande (charge_fichier), sinon lancer le serveur

    sous win existe 36 moyens de faire communiquer la seconde instance indésirable avec "la première" (et autres sous linux...)
    Note ! la première solution du lien est surprenante (j'ai jamais testé) et certainement amusante à écrire genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if pressepapier.search("SignatureApp"):
       pressepapier.write(f"SignatureApp load {sys.argv[1]}")
       exit()
    #Lancer app
        pressepapier.write("SignatureApp")   # type mime spécifique a l'app
        ...
        chaque seconde :
           if fichier :=pressepapier.seach("SignatureApp load")
               app.load(fichier)
    finally:
          pressepapier.clearAll("SignatureApp*")
    $moi= ( !== ) ? : ;

  8. #8
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 320
    Points : 204
    Points
    204
    Par défaut
    @wiztricks

    QtSingleApplication n'existe plus depuis la version 6, mais je vais regarder du côté des sockets.
    Par ailleurs, effectivement, j'ai lu la doc, mais sans doute pas en entier car elle est extrêmement imposante. Lorsque je j'essaie ce type d'appli sans intérêt, c'est aussi pour confronter ma compréhension à la pratique.
    Si par hasard, ce que j'essaie de faire ne fonctionne pas c'est, je suis d'accord, un problème de compréhension. Je vais donc y retourner.

    Je pensais que le forum était fait pour faciliter les échanges entre les sachant et les apprenants. Je ne cherche pas un code tout fait, je cherche juste à comprendre une problématique et trouver une solution.
    Aujourd'hui, j'ai essayé de résoudre le problème avec Psutil et Wmi, sans résultat, mais comme le dev n'est pas le centre de ma profession, je ne peux creuser pendant des heures.

    @papajoker:
    Je prends les éléments et les ajoutes à la liste de mes recherches. Je vous tiendrai au courant de l'évolution de mon code.

    En tout cas merci à vous deux.
    Douter de tout, toujours, et surtout de soi-même...

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Citation Envoyé par FadeToBlack Voir le message
    Je pensais que le forum était fait pour faciliter les échanges entre les sachant et les apprenants. Je ne cherche pas un code tout fait, je cherche juste à comprendre une problématique et trouver une solution.
    La communication entre processus est une problématique système qui n'a rien à voir avec le langage (le langage devra être utilisé pour mettre en œuvre).... et la solution à votre problème devra avoir choisi une méthode (j'ai proposé socket parce qu'à priori tout le monde devrait connaître et si vous aviez poursuivi un peu sur QtSingleApplication, c'est une suggestion de remplacement...).

    Pour le reste, il y a plein de forum de discussions parce que l'informatique embrasse de multiples domaines.... Et c'est à vous de choisir le bon forum où demander le l'aide. Pour faire simple, dans un forum de programmation python vous devriez poster un code qui ne fonctionne pas (alors que vosu avez pensé qu'il devrait fonctionner), demander de l'aide sur l'architecture de son application pour qu'elle puisse réaliser la fonctionnalité X n'est pas encore du code donc c'est pas le bon forum.

    Citation Envoyé par FadeToBlack Voir le message
    Aujourd'hui, j'ai essayé de résoudre le problème avec Psutil et Wmi, sans résultat, mais comme le dev n'est pas le centre de ma profession, je ne peux creuser pendant des heures.
    Vous êtes venu sur ce forum pour avoir des idées... je vous ai suggéré de créer un serveur via socket et apparemment vous n'en faites rien. A quoi sert de demander des idées si vous n'en faites rien?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 320
    Points : 204
    Points
    204
    Par défaut
    Bonjour à vous deux,

    Bon j'ai creusé la proposition de la création d'un serveur. Pour faire simple, je me suis tourné vers le module "Socket" plutôt qu'un pendant de Pyside6.

    Voici ce que cela donne :
    fichier main.py:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    import sys
    from PySide6.QtWidgets import QApplication
    from src.emp import Emp
    import socket
     
     
    host = "127.0.0.1"
    port = 6958
     
    # Test présence d'un serveur
    def try_server():
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        sock.settimeout(2)
        try:
            sock.connect(host,port)
            return sock
        except:
            return False
     
    if __name__ == '__main__':
        # on test la présence d'un serveur
        connexion = try_server()
        if  connexion == False:
            print("Pas de serveur en écoute")
            app = QApplication(sys.argv)
            #
            if len(sys.argv) < 2:
                main = Emp()
            else:
                main = Emp(sys.argv[1])
            main.show()
            app.setStyle("Fusion")
            app.exec()
     
        else:
            connexion.sendall(sys.argv[1].encode("utf8"))
     
     
            sys.exit()

    le fichier de ma classe Emp() (je ne mets pas tout, histoire de ne pas avoir un post trop long, mais si besoin.....).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
     
     
    from importlib.metadata import metadata
     
    from PySide6.QtCore import QFile, QTextStream, QCoreApplication, Slot, QUrl, QTime, QFileInfo, Qt, QSize
    from PySide6.QtGui import QScreen, QIcon, QAction, QIconEngine
    from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput, QMediaMetaData
    from PySide6.QtMultimediaWidgets import QVideoWidget
    from PySide6.QtWidgets import (QMainWindow,
                                   QWidget,
                                   QApplication,
                                   QVBoxLayout,
                                   QHBoxLayout,
                                   QPushButton, QLabel, QTimeEdit, QFileDialog, QSlider, QComboBox, QStyle)
    import pathlib
    from src.assets.css import *
    from src.utils.utils_hours import hhmmss
    import os
    import sys
    from src.resultat import NewWindows
    import src.assets.icons.all_icons_rc
    import socket
     
     
    class Emp(QMainWindow):
        def __init__(self, file=None):
            super().__init__()
            self.settings()
            self.initUi()
            self.event_handler()
            self.result = None
            self.set_style()
            self.fileName = file
            if file:
                self.open_file_with_parameters(file)
            self.leSocket = self.open_server()
            if self.leSocket:
                self.leSocket.listen()
                conn, address = self.leSocket.accept()
                data = conn.recv(1024)
                self.stop_media()
                self.open_file_with_parameters(data.decode("utf8"))
     
        def open_server(self):
            sock  = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.bind(("127.0.0.1", 6958))
            print('le serveur est démarré...')
            return sock
     
     
        # Setting
        def settings(self):
            self.setWindowTitle("Essai Media Player")
            self.setGeometry(0, 0, 800, 500)
            center = QScreen.availableGeometry(QApplication.primaryScreen()).center()
            geo = self.frameGeometry()
            geo.moveCenter(center)
            self.move(geo.topLeft())
            #
            # qss = QFile(r"src/assets/css/Qstyle.qss")
            # qss.open( QFile.ReadOnly | QFile.Text )
            # File =QTextStream(qss)
            # self.setStyleSheet(File.readAll())
            # qss.close()
     
            menu = self.menuBar()
            file_menu = menu.addMenu("&Fichier")
            menu.addMenu(" A &Propos")
            self.open_action = file_menu.addAction("&Ouvrir")
            self.open_action.setShortcut('Ctrl+O')
            self.quit_action = file_menu.addAction("&Quitter")
            self.quit_action.setShortcut('Ctrl+Q')
     
            # self.command = []
     
        # Design
        def initUi(self):
            self.VB = QVBoxLayout()
            self.control_HB = QHBoxLayout()
            self.select_HB = QHBoxLayout()
     
            # Construction du player
            self.video_player = QVideoWidget()
            self.player = QMediaPlayer(None)
            self.audioOutput = QAudioOutput()
            self.player.setAudioOutput(self.audioOutput)
            self.player.setVideoOutput(self.video_player)
     
            # Les widgets du control_HB
            self.running_lbl = QLabel("00:00:00:000")
            self.running_lbl.setFixedWidth(80)
            self.slash_label = QLabel("/")
            self.slash_label.setFixedWidth(10)
            self.total_time_lbl = QLabel("00:00:00")
            self.total_time_lbl.setFixedWidth(80)
            self.speed_lbl = QLabel('Vitesse: ')
            self.speed_lbl.setFixedWidth(50)
            # self.speed_slider = QSlider()
            # self.speed_slider.setOrientation(Qt.Horizontal)
            # self.speed_slider.setMinimum(0)
            # self.speed_slider.setMaximum(200)
            # self.speed_slider.setValue(100)
     
            self.combobox = QComboBox()
            self.combobox.addItems(['2', '1.75', '1.5', '1.25', '1', '0.75', '0.50', '0.25'])
            self.combobox.setCurrentIndex(4)
            self.combobox.setFixedWidth(50)
     
            self.hundred_btn = QPushButton("100%")
            self.hundred_btn.setFixedWidth(66)
     
            self.play_btn = QPushButton()
            icon_play = QIcon()
            icon_play.addFile(u":/Buttons/play.png", QSize(), QIcon.Normal, QIcon.Off)
            self.play_btn.setIcon(icon_play)
            # self.play_btn.setIcon(QIcon(r"./src/assets/images/play.png"))
            self.play_btn.setFixedWidth(70)
     
            self.pause_btn = QPushButton()
            self.pause_btn.setFixedWidth(70)
            icon_pause = QIcon()
            icon_pause.addFile(u":/Buttons/pause.png", QSize(), QIcon.Normal, QIcon.Off)
            self.pause_btn.setIcon(icon_pause)
            # self.pause_btn.setIcon(QIcon(r"./src/assets/images/pause.png"))
     
     
            self.stop_btn = QPushButton()
            self.stop_btn.setFixedWidth(70)
            icon_stop = QIcon()
            icon_stop.addFile(u":/Buttons/stop.png", QSize(), QIcon.Normal, QIcon.Off)
            self.stop_btn.setIcon(icon_stop)
            # self.stop_btn.setIcon(QIcon(r"./src/assets/images/stop.png"))
     
        # icon = QIcon()
        # icon.addFile(u":/Buttons_icons/assets/icons/check-mark.png", QSize(), QIcon.Normal, QIcon.Off)
        # self.btnOk2.setIcon(icon)
     
     
     
            self.control_HB.addWidget(self.running_lbl)
            self.control_HB.addWidget(self.slash_label)
            self.control_HB.addWidget(self.total_time_lbl)
            self.control_HB.addStretch(80)
            self.control_HB.addWidget(self.speed_lbl)
            self.control_HB.addWidget(self.combobox)
            self.control_HB.addWidget(self.hundred_btn)
            self.control_HB.addWidget(self.play_btn)
            self.control_HB.addWidget(self.pause_btn)
            self.control_HB.addWidget(self.stop_btn)
     
            # LEs widgets du select_HB
            self.timeEdit = QTimeEdit()
            self.timeEdit.setFixedWidth(90)
            self.timeEdit.setFixedWidth(110)
            self.timeEdit.setDisplayFormat(
                QCoreApplication.translate("MainWindow", "HH:mm:ss:zzz", None)
            )
            self.go_btn = QPushButton("Allez")
            self.go_btn.setFixedWidth(100)
            self.start_btn = QPushButton("Début")
            self.start_btn.setFixedWidth(70)
            self.start_btn.setObjectName("start_btn")
            self.start_btn.setDisabled(True)
            self.start_lbl = QLabel("00:00:00:000")
            self.end_lbl = QLabel("00:00:00:000")
            self.end_btn = QPushButton("Fin")
            self.end_btn.setFixedWidth(70)
            self.end_btn.setObjectName("end_btn")
            self.end_btn.setDisabled(True)
            self.add_btn = QPushButton("Ajouter")
            self.add_btn.setFixedWidth(80)
            self.add_btn.setDisabled(True)
     
            self.select_HB.addWidget(self.timeEdit)
            self.select_HB.addWidget(self.go_btn)
            self.select_HB.addStretch()
            self.select_HB.addWidget(self.start_btn)
            self.select_HB.addWidget(self.start_lbl)
            self.select_HB.addWidget(self.end_btn)
            self.select_HB.addWidget(self.end_lbl)
            self.select_HB.addWidget(self.add_btn)
     
            self.VB.addWidget(self.video_player)
            self.VB.addLayout(self.control_HB)
            self.VB.addLayout(self.select_HB)
     
            # Conteneur Principal
            container = QWidget()
            container.setLayout(self.VB)
            self.setCentralWidget(container)
     
        # Event handler
        def event_handler(self):
            self.open_action.triggered.connect(self.open_file)
            self.quit_action.triggered.connect(QApplication.quit)
            self.play_btn.clicked.connect(self.play_media)
            self.pause_btn.clicked.connect(self.pause_media)
            self.stop_btn.clicked.connect(self.stop_media)
            self.start_btn.clicked.connect(self.add_start)
            self.end_btn.clicked.connect(self.add_end)
            self.player.durationChanged.connect(self.view_total_time)
            self.player.positionChanged.connect(self.view_current_time)
            self.go_btn.clicked.connect(self.on_time_changed)
            self.add_btn.clicked.connect(self.add_command_line)
            # self.speed_slider.valueChanged.connect(lambda value: self.player.setPlaybackRate(value / 100))
            self.combobox.currentTextChanged.connect(self.change_speed)
            self.hundred_btn.clicked.connect(self.slider_hundred)
     
        @Slot()
        def open_file(self,f):
            self.file_name, _ = QFileDialog.getOpenFileName(self, "Ouvrir Vidéo", "", "Fichiers Vidéo (*.mp4 *.avi *.mov *.mkv *.mxf)")
            if self.file_name:
                self.player.setSource(QUrl.fromLocalFile(self.file_name))
                self.player.play()
                self.start_btn.setEnabled(True)
                self.end_btn.setEnabled(True)
                self.add_btn.setEnabled(True)
     
        @Slot()
        def play_media(self):
            self.player.play()
     
        @Slot()
        def pause_media(self):
            self.player.pause()
     
        @Slot()
        def stop_media(self):
            self.player.stop()
     
        @Slot()
        def add_start(self):
            self.start_lbl.setText(self.timeEdit.text())
     
        @Slot()
        def add_end(self):
            self.end_lbl.setText(self.timeEdit.text())
     
        @Slot()
        def view_total_time(self, p):
            self.total_time_lbl.setText(hhmmss(self.player.duration()))
     
        @Slot()
        def view_current_time(self, p):
            self.running_lbl.setText(
                QTime.fromString("00:00:00").addMSecs(p).toString("hh:mm:ss:zzz")
            )
            self.timeEdit.setTime(QTime.fromString("00:00:00").addMSecs(p))
     
        @Slot()
        def change_speed(self, s):
            # print (s)
            self.player.setPlaybackRate(float(s))
     
        @Slot()
        def on_time_changed(self):
            txt = self.timeEdit.text()
            time_splitted = txt.split(":")
            mill = (
                    int(time_splitted[3])
                    + int(time_splitted[2]) * 1000
                    + int(time_splitted[1]) * 60000
                    + int(time_splitted[0]) * 60 * 60000
            )
            self.player.setPosition(mill)
     
        @Slot()
        def add_command_line(self, checked):
            if self.result is None:
                self.result = NewWindows()
                # self.result.setStyle(QFusionStyle)
                self.result.show()
            if self.fileName is None:
                self.result.add_line(QFileInfo(self.file_name).fileName()[:-4] , self.start_lbl.text(), self.end_lbl.text() )
            else:
                self.result.add_line(QFileInfo(self.fileName).fileName()[:-4] , self.start_lbl.text(), self.end_lbl.text() )
                metadata = self.player.metaData()
                print(metadata.value(QMediaMetaData.Title))
     
            # self.result.close()  # Close window.
            # self.result = None  # Discard reference.
            # self.command.append((fileName.baseName(), self.start_lbl.text(),self.end_lbl.text() ))
            # print(self.command)
     
        @Slot()
        def slider_hundred(self):
            self.player.setPlaybackRate(1)
            # self.speed_slider.setValue(100)
            self.combobox.setCurrentIndex(4)
     
        def open_file_with_parameters(self, file):
            self.player.setSource(QUrl.fromLocalFile(file))
            self.player.play()
            self.start_btn.setEnabled(True)
            self.end_btn.setEnabled(True)
            self.add_btn.setEnabled(True)
     
     
        def set_style(self):
            self.setStyleSheet("""
                QWidget {
                    background-color: #b8c9e1;
                }
                
                QLabel {
                    color: #333;
                    font-size: 14px;
                }
                
                QLineEdit, QComboBox, QDateEdit, QPushButton {
                    background-color: #b8c9e1;
                    color: #333;
                    border: 1px solid #444;
                    padding: 5px;
                }
                
                QTableWidget {
                    background-color: #b8c9e1;
                    color: #333;
                    border: 1px solid #444;
                    selection-background-color: #ddd;
                }
                
                QPushButton {
                    background-color: #4caf50;
                    color: #fff;
                    border: none;
                    padding: 8px 16px;
                    font-size: 14px;
                    border-radius: 15px;
                }
                
                QPushButton:hover {
                    background-color: #45a049;
                }
                
                QPushButton:disabled {
                    background-color: #838b96;
                }
                
                QComboBox {
                    background-color: #45a049;
                    border-radius: 5px;
                    border-width: 0px;
                }
                
                
                QTimeEdit {
                    font-size: 14px;
                }
                QPushButton #start_btn {
                    width: 50px;
                }
            
            """)

    Bon cela fonctionne d'un point de vu "serveur". J'ai bien un message que le serveur n'est pas démarré, puis ensuite qu'il a démarré.
    Mais en fait, je reste bloqué à ce niveau là. Mais fenêtre de mon application ne s'ouvre pas.

    Le serveur écoute bien, mais la mise en attente bloque l'ouverture de ma fenêtre.
    Je dois surement louper un truc, là je ne vois pas.
    Douter de tout, toujours, et surtout de soi-même...

  11. #11
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 320
    Points : 204
    Points
    204
    Par défaut
    La solution ne serait-elle pas de construire mon serveur sur un thread séparé ?

    Je vais regarder de ce côté
    Douter de tout, toujours, et surtout de soi-même...

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Citation Envoyé par FadeToBlack Voir le message
    La solution ne serait-elle pas de construire mon serveur sur un thread séparé ?
    Vous utilisez Qt qui vient avec un mécanisme sophistiqué de communications entre objets basés sur les signaux et slots ...
    Les développeurs de Qt ont bossé pour fabriquer un module QTcpXYZ qui soit compatible avec ces mécanismes... (et vous éviter d'avoir à utiliser un thread séparé).
    Utiliser au mieux Qt serait la solution.

    Là, en utilisant les sockets de base, vous avez crée un problème qui a aussi sa solution qui sera sans doute plus compliquée qu'elle ne paraît (il faudra plus que des threads) en réinventant le fil a couper le beurre.

    note: pour "valider" cette solution, il faudrait essayer de démarrer la 2 applications pour constater l'exceptions levée lorsqu'un serveur est déjà démarré et imaginer le traitement à faire dans ce cas. Vous partez déjà à bricoler le code qui fonctionne (sans cette fonctionnalité) en espérant que ça ne va pas changer grand chose à l'existant sans avoir pris le temps d'identifier tout ce qu'il y aura à faire... (ce qui est la base du boulot et le sens de "programmer").


    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  13. #13
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 484
    Points : 9 286
    Points
    9 286
    Billets dans le blog
    6
    Par défaut
    Bonjour

    C'est un problème qu'on rencontre assez souvent, et voilà la solution que j'utilise. C'est en PyQt5, et j'espère que c'est utilisable en PyQt6.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    # -*- coding: utf-8 -*-
     
    import sys
    import os
    from PyQt5 import (QtWidgets, QtCore)
     
    #############################################################################
    class Fenetre(QtWidgets.QMainWindow):
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
    #############################################################################
    if __name__ == "__main__":
     
        # lancement du graphique
        app = QtWidgets.QApplication(sys.argv)
     
        # on définit l'identificateur unique de ce programme
        progid = "D6BB05B2919732D8F29045842531CAD23162E1B9"
     
        # auquel on ajoute le chemin du "home" de l'utilisateur
        progid += os.path.expanduser('~')
     
        # on prépare la création d'une zone partagée avec cette clé unique
        sharedMemory = QtCore.QSharedMemory(progid)
     
        # on essaye de créer cette zone partagée de taille 50 (quelconque):
        # si ce n'est pas possible, c'est qu'elle existe déjà, et donc
        # qu'elle a été créée par une instance précédente du même programme!
        if not sharedMemory.create(50):
            QtWidgets.QMessageBox.warning(None,
                             "Vérification",
                             """
     
    Attention:
     
    ce programme est déjà en cours d'exécution
     
    utilisez la version déjà lancée!
     
                             """)
            app.quit()
            sys.exit(0)
     
        # lancement de la fenêtre
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    Pour fabriquer un code aléatoire de 40 caractères, voilà ce que j'utilise:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # -*- coding: utf-8 -*-
     
    from random import randint
     
    #############################################################################
    guidrand = lambda n=40, alphanum=u"0123456789ABCDEF": \
                ''.join([alphanum[randint(0,len(alphanum)-1)] for i in range(n)])
     
    #############################################################################
     
    print(guidrand(40))
    # exemple: D6BB05B2919732D8F29045842531CAD23162E1B9
    A l'exécution la 1ère fois, la fenêtre s'affiche
    A la seconde exécution, une nouvelle fenêtre s'affiche (QMessageBox.warning) avec la mention de l'échec. On peut, bien sûr, se contenter de ne rien faire dans ce cas!
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    C'est un problème qu'on rencontre assez souvent, et voilà la solution que j'utilise. C'est en PyQt5, et j'espère que c'est utilisable en PyQt6.
    L'avantage d'un serveur Web est qu'on peut facilement échanger des messages pour demander à l'application qui est déjà démarrée de changer la vidéo suivante.... avec de la mémoire partagé, c'est un peu plus sportif.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  15. #15
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 484
    Points : 9 286
    Points
    9 286
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    avec de la mémoire partagé, c'est un peu plus sportif.
    Mais c'est très simple à programmer!

    D'un autre côté, il est vrai que Python possède tout ce qu'il faut pour créer et exploiter un serveur, y compris un serveur basique comme TCP.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Mais c'est très simple à programmer!
    programmer n'est jamais compliqué pour autant qu'on ait les bases et qu'on maîtrise un peu les mécanismes utilisés.
    Si on découvre tout ça, la marche peut être haute surtout si on est pressé.

    Citation Envoyé par tyrtamos Voir le message
    D'un autre côté, il est vrai que Python possède tout ce qu'il faut pour créer et exploiter un serveur, y compris un serveur basique comme TCP.
    L'avantage d'une socket est qu'on est déjà dans un mode client-serveur. Avec une mémoire partagés, il va falloir ajouter des trucs pour savoir qui écrit, quand a-t-il fini,... en plus des soucis de sérialisation (qu'on a aussi avec "socket").

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  17. #17
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 245
    Points : 4 742
    Points
    4 742
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Mais c'est très simple à programmer!
    utiliser un fichier lock, mémoire partagée, le presse papier , ... En fait c'est toujours la même chose "simple", je dirais que c'est la même architecture de code mais avec des technos différentes.

    vrai que Python possède tout
    Mais Qt est un framework qui propose ces propres solutions, et en GUI il est préférable de suivre la "recommendation" du framework

    Un exemple basique (pas pour piloter une app depuis un client !) avec Qt5 ou 6:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    import sys
    if "qt5" in sys.argv:
        from PyQt5.QtCore import QTextStream, pyqtSignal as Signal
        from PyQt5.QtWidgets import QApplication, QComboBox, QMainWindow
        from PyQt5.QtNetwork import QLocalSocket, QLocalServer
    else :
        from PySide6.QtCore import QTextStream, Signal
        from PySide6.QtWidgets import QApplication, QComboBox, QMainWindow
        from PySide6.QtNetwork import QLocalSocket, QLocalServer
     
     
    class QOneApplication(QApplication):
        message = Signal(str)
        def __init__(self, args, idApp="X25"):
            super().__init__(args)
            idApp = f"{self.applicationName()}-{idApp}"
     
            self._socket = QLocalSocket()
            self._socket.connectToServer(idApp)
            self.isActive = self._socket.waitForConnected(1000)
            if not self.isActive:
                self._server = QLocalServer()
                self._server.listen(idApp)
                self._server.newConnection.connect(self._onNewConnection)
     
        def sendMessage(self, msg):
            if not self.isActive:
                return 0
            self._socket.write(str.encode(msg + "\n"))
            return self._socket.waitForBytesWritten()
     
        def _onNewConnection(self):
            self._socket = self._server.nextPendingConnection()
            if self._socket:
                self._socket.readyRead.connect(self._onReadLine)
     
        def _onReadLine(self):
            in_stream = QTextStream(self._socket)
            while not in_stream.atEnd():
                if msg := in_stream.readLine():
                    self.message.emit(msg)
     
     
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.resize(420, 80)
            self.statusBar()        
            self.truc = QComboBox()
            self.truc.setEditable(True)
            self.truc.addItems(["en attente", "-", "-"])
            self.setCentralWidget(self.truc)
     
        def recevoirCmd(self, data: str):
            if data.startswith("OPEN "):
                print("  CMD depuis autre instance :", data)
                self.truc.setEditText(data[5:])
            elif data[1].isupper():
                print(f"  CMD {data} ?")
     
     
    if __name__ == '__main__':
     
        app = QOneApplication(sys.argv, idApp=42)
        if app.isActive:
            print("Déjà en route")
            app.sendMessage("STOP")
            app.sendMessage(f"OPEN /tmp/toto.txt  {sys.argv[1:]}")
            sys.exit(app.quit())
     
        main = MainWindow()
        app.message.connect(main.recevoirCmd)
        main.show()
        sys.exit(app.exec())
    $moi= ( !== ) ? : ;

  18. #18
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 514
    Points : 37 131
    Points
    37 131
    Par défaut
    Quand je trouve ligne 30 du C++ mal traduit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
            out_stream = QTextStream(self._socket)
            out_stream << msg << "\n"
            out_stream.flush()
    je ne comprends pas trop ce qu'on cherche à démontrer!

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  19. #19
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 245
    Points : 4 742
    Points
    4 742
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    je ne comprends pas
    Mois non plus (ta remarque), c'est tiré de la doc Qt ...
    Pour écrire dans un flux (en qt), cet opérateur est redéfini
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    class QTextStream(PySide6.QtCore.QIODeviceBase):
    ...
        @overload
        def __init__(self) -> None: ...
        @overload
        def __init__(self, array: Union[PySide6.QtCore.QByteArray, bytes, bytearray, memoryview], openMode: PySide6.QtCore.QIODeviceBase.OpenModeFlag = ...) -> None: ...
        @overload
        def __init__(self, device: PySide6.QtCore.QIODevice) -> None: ...
     
        @overload
        def __lshift__(self, array: Union[PySide6.QtCore.QByteArray, bytes, bytearray, memoryview]) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, ch: str) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, ch: int) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, f: float) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, i: int) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, i: int) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, m: PySide6.QtCore.QTextStreamManipulator) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, s: str) -> PySide6.QtCore.QTextStream: ...
        @overload
        def __lshift__(self, s: str) -> PySide6.QtCore.QTextStream: ...
        def __rshift__(self, array: Union[PySide6.QtCore.QByteArray, bytes, bytearray, memoryview]) -> PySide6.QtCore.QTextStream: ...
    ou c'est plutot cela que tu attends ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    out_stream << msg + "\n"
    ou directement un socket.write() ? Qui oui est plus simple
    $moi= ( !== ) ? : ;

  20. #20
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 966
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 966
    Points : 7 389
    Points
    7 389
    Par défaut
    Citation Envoyé par papajoker
    ou c'est plutot cela que tu attends ?
    Pas sûr... Pourquoi pas la méthode write de QIODevice ?

    Ça prend des bytes en paramètre, pas grave, on utilise la méthode .encode("utf8")
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

Discussions similaires

  1. [Sonar] Ne pas executer deux fois les tests
    Par woodwai dans le forum Qualimétrie
    Réponses: 3
    Dernier message: 23/03/2010, 18h54
  2. [AC-2007] Ne pas imprimer deux fois la même chose
    Par Flup dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 24/11/2009, 21h47
  3. [Perl POO] ne pas créer deux fois le même objet
    Par seben dans le forum Langage
    Réponses: 4
    Dernier message: 30/03/2009, 22h19
  4. Réponses: 7
    Dernier message: 30/10/2008, 12h31
  5. Comment ne pas enregistrer plusieurs fois une touche ?
    Par Jordinateur dans le forum SDL
    Réponses: 33
    Dernier message: 05/10/2007, 22h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo