python_custom_tkinter_CTkTextbox_スレッド監視の部分と_CTkTexboxのbindメソッド


はじめはキーイベントとキーイベントの間にはタイムラグがあると思って

threading threadで処理しようと思っていたが、

hidの場合だと バーコードの入力完了時に

エンターキーのイベントを送信するらしいので、


CTkEntryのbindでも対応できるらしい。


----------------------------------------------------------------------


pythonの Custom tkinter を使った

以下のような2つのサンプルコードがあるのですが、


一つ目は次のようなものです。


class MyApp(ctk.CTk):


    def __init__(self):


        self.cnt = 0


self.text_var = tk.StringVar()

        self.text_var.trace("w", self.on_text_change)


        # Entries

        self.entry1

= ctk.CTkEntry(self, textvariable=self.text_var)

        self.entry1.pack(pady=10)




    def start_worker_thread(self):

        

        """Starts a new worker thread."""

        if self.thread is None or not self.thread.is_alive():

            self.thread = threading.Thread(target=self.worker2)

            self.thread.start()



    def worker2(self):

        

        """Thread that handles delayed entry updates."""

        print("Thread started")


        try:

            

            # Wait for 10 seconds or until interrupted

            for _ in range(10):  

                

                if self.stop_event.is_set():

                    print("Thread interrupted before completion")

                    return

                    

                time.sleep(0.1)


            # Update the second entry after delay

            new_text = self.entry1.get()

            self.after(0, lambda: self.ready_for_input(new_text))

            


        except Exception as e:

            print(f"Thread encountered an exception: {e}")



    def ready_for_input(self, text):

        

        """Updates the text of entry2."""

        #self.entry2.configure(text=text)

        

        self.text_var.set( "" )

            

## この記述がないので 2回目以降の画像読み込みでスレッドが起動しないことによる

        self.cnt = 0

     

        self.text_var2.set( text )




二つ目は次のようなものです。


class BarcodeScannerApp(ctk.CTk):


    def __init__(self):

        super().__init__()

        

        self.title("Barcode Scanner")

        self.geometry("500x400")


# 商品データ (キー: バーコード, 値: {名前, 価格, 数量})

        self.items = {} 

# 状態管理

        self.state = "INIT"  

        

        # バーコード入力

        self.entry_barcode

= ctk.CTkEntry(

self, placeholder_text="Enter barcode")

        

self.entry_barcode.pack(pady=10)

        self.entry_barcode.bind(

"<Return>", self.process_barcode)



        

    def process_barcode(self, event):

        barcode

= self.entry_barcode.get().strip()

        if not barcode:

            return

        

        if barcode in self.items:

            self.items[barcode]["quantity"] += 1

        else:

            self.items[barcode]

= {"name": f"Item {barcode}",

"price": 100, "quantity": 1}

        

        self.update_list()

        self.entry_barcode.delete(0, tk.END)




CTkTextboxに関するメソッド


tk.StringVar() のtrace("w", self.on_text_change)

では連続するキーボード入力に対応したしょりですが、


二つ目のサンプルで使用しているCTkEntryの bindメソッドでは、

一つのバーコードのすべての桁の入力が完了した際の処理でしょうか?


バーコードリーダでの入力モードがhidだと

入力方法がキーボードからのものに準ずるので、


その場合の CTkEntryに関する処理は、

上記サンプルの2つの部分を組み合わせたほうがいいのでしょうか?




はい、二つのサンプルコードを組み合わせるのが良い方法です。


---


### **1. `trace("w", self.on_text_change)` の動作**


- `tk.StringVar()` の 

`trace("w", self.on_text_change)` を使用すると、

**文字が変更されるたびに** `on_text_change` が呼ばれます。


- これは **手入力やHIDモードのバーコードリーダーの逐次入力** に適しています。


- しかし、バーコードの途中で処理をすると不完全なデータが処理されるリスクがあります。


---


### **2. `<Return>` (Enterキー) による処理**


- `bind("<Return>", self.process_barcode)` は 

**入力が完了し、Enterキーが押されたときに処理** されます。

- 一般的な **HIDモードのバーコードリーダー** は、

バーコードをすべて入力した後、自動的にEnterキー(Returnキー)を送信するため、

この方法で処理を確定できます。


- ただし、手入力の場合は 

`Enter` を押さなければ処理が進まないため、

**リアルタイムで処理したい場合には不便** です。



---


### **3. どのように組み合わせるべきか?**

- **HIDバーコードリーダーでの入力**

→ `bind("<Return>")` を使うのが基本


- **手入力やソフトウェアキーボード** 

→ `trace("w", self.on_text_change)` 

を使うと即時反応が可能


そのため、

**「リアルタイム更新」と「Enterキー確定」を組み合わせる」**のが理想です。


---


## **改良版のアプローチ**


```python


import customtkinter as ctk

import tkinter as tk


class BarcodeScannerApp(ctk.CTk):


    def __init__(self):

        super().__init__()


        self.title("Barcode Scanner")

        self.geometry("500x400")


        # 商品データ (キー: バーコード, 値: {名前, 価格, 数量})

        self.items = {}


        # 状態管理

        self.state = "INIT"


        # StringVar でリアルタイム検知

        self.barcode_var = tk.StringVar()

        self.barcode_var.trace("w", self.on_text_change)


        # バーコード入力

        self.entry_barcode

= ctk.CTkEntry(self, 

textvariable=self.barcode_var, 

placeholder_text="Enter barcode")

        self.entry_barcode.pack(pady=10)


        # Enterキーが押されたら確定処理

        self.entry_barcode.bind("<Return>", self.process_barcode)



    def on_text_change(self, *args):

        """

        入力途中の処理(リアルタイムで入力監視)

        """

        barcode = self.barcode_var.get()

        print(f"入力中のバーコード: {barcode}")


        # 例えば、一定桁数(12桁など)で自動確定するなら

        if len(barcode) >= 12:

            self.process_barcode(None)



    def process_barcode(self, event):

        """

        確定したバーコードの処理

        """

        barcode = self.entry_barcode.get().strip()

        if not barcode:

            return


        if barcode in self.items:

            self.items[barcode]["quantity"] += 1

        else:

            self.items[barcode]

= {"name": f"Item {barcode}", 

"price": 100, "quantity": 1}


        print(f"処理済みバーコード: {barcode}")

        self.update_list()


        # 入力欄をクリア

        self.barcode_var.set("")


    def update_list(self):

        """ダミーの更新処理"""

        print("商品リスト更新:", self.items)



# 実行

app = BarcodeScannerApp()

app.mainloop()


```


---


### **4. この改良版のポイント**


✅ **リアルタイムで監視 (`trace("w", self.on_text_change)`)**


  - 手入力でも反応し、バーコード途中のデータを確認可能



✅ **HIDモード(Enterキー送信)に対応

(`bind("<Return>", self.process_barcode)`)**


  - HIDモードのバーコードリーダーがEnterキーを送信すれば、

確定処理が実行される



✅ **一定桁数で自動確定 (`if len(barcode) >= 12:`)**


  - HIDモード以外でも、

  

  例えばバーコードが12桁以上になったら処理することで、

  **手入力でもEnter不要に**


---


### **5. まとめ**


- **HIDモードのバーコードリーダー** 


→ `bind("<Return>", self.process_barcode)` で対応


- **手入力でもリアルタイム更新したい**

 

→ `trace("w", self.on_text_change)` を使う


- **桁数が決まっている場合** 


→ `if len(barcode) >= 12:` で自動確定



このように **両方の方法を組み合わせることで、

どの入力方法でもスムーズに動作** するようになります。



コメント