2

解決できない別の問題があります

ツリービューにユーザー(名、姓、年齢)を追加する次のコードがあります。1つの小さなことを除いて、すべてうまく機能します。初めてユーザーを追加するときにのみうまく機能します。[追加]をクリックしてからさらに別のユーザーを追加しようとすると、2人のユーザーが追加され、次に3人、4人というように追加され、追加するたびに増加します。クリックイベントをキャッチするコードは次のとおりです。

onClicked (dodajUczBt gui) (dodajUcz gui dbh stores)

dodajUczクリックを処理する関数は次のとおりです。

dodajUcz gui dbh stores =
    do  entrySetText (nImie gui) ""
        entrySetText (nNazwisko gui) ""
        entrySetText (nWiek gui) ""
        onClicked (cancelAddUczBt gui) (widgetHide (dodajUzDialog gui))
        onClicked (zapiszUczBtn gui) procADD
        windowPresent (dodajUzDialog gui)
    where procADD = do
            ucz <- getUczestnik
            let store = uczestnicy stores
            New.listStoreAppend store ucz
            dlugosc <- New.listStoreGetSize store
            labelSetText (lblLiczbaUcz gui) $ "Liczba uczestników: "++ show dlugosc 
            widgetHide (dodajUzDialog gui)
            addUser ucz dbh
          getUczestnik = do
                                imie <- entryGetText (nImie gui)
                                nazwisko <- entryGetText (nNazwisko gui)
                                wiek <- entryGetText (nWiek gui)
                                let wiek' = read wiek :: Integer
                                return $ Uczestnik 0 imie nazwisko wiek' False

Uczestnikは代数的データ型であり、データベースにaddUserを追加する関数です。Uczestnikguiは代数的データ型GUIでもあり、によって作成されたすべてのgui要素を保持します。castToXml

それwidgetHideが主な問題だと思います。何もしなくても(ダイアログを開いてから閉じるだけ)、次に開いたときに2人のユーザーを追加しようとするからです。

この問題を解決する方法はありますか?どんな助けでも大歓迎です:)

4

1 に答える 1

1

まあ、私の理解はそれです:

  1. ダイアログを再度表示するには、dodajUczコード内の別の場所から呼び出します。
  2. ユーザーを追加するたびに、ダイアログを非表示にします(そして、ダイアログを再度表示するように要求します)
  3. 最も重要なこと:評価する(つまり実行する)たびに、(を使用して)dodajUczもう一度イベント「クリック」のイベントハンドラーをインストールしzapiszUczBtn ますonClicked。イベントのイベントハンドラーをインストールすると、イベントハンドラーは永久にそこにとどまり、イベントがトリガーされるたびに実行されます。2回インストールすると、2回実行されます。この特定のケースでは、dodajUcz2回呼び出した後、でクリックされたイベントがトリガーされると、イベントハンドラーが2回実行されzapiszUczBtnます。

    onClickedまたはその他のイベントハンドラインストーラを使用しても、以前のハンドラは削除されず、そのウィジェットとイベントのハンドラスタックに追加されます。

    GUIを初期化するとき(最初に作成するとき)、コードでイベントハンドラーを一度だけ設定し、そのコードを再度実行しないでください。その後、GUIとストアを引数として渡すことができますprocADD

    例えば:

    startGUI :: DBH -> IO (GUI, Stores)
    startGUI dbh = do
      gui <- giveMeGUI -- or some other function that returns a gui
      stores <- giveMeStores -- or some other function that returns the stores
      onClicked (cancelAddUczBT gui) (widgetHide (dodaUzDialog gui))
      onClicked (zapiszUczBtn gui) (procADD gui dbh stores)
      return (gui, stores)
    
    dodajUcz gui dbh stores = do
       entrySetText (nImie gui) ""
       entrySetText (nNazwisko gui) ""
       entrySetText (nWiek gui) ""
       windowPresent (dodajUzDialog gui)
    
    procADD gui dbh stores = do
       ...
    
于 2012-03-09T02:11:23.667 に答える