はじめはキーイベントとキーイベントの間にはタイムラグがあると思って
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:` で自動確定
このように **両方の方法を組み合わせることで、
どの入力方法でもスムーズに動作** するようになります。
コメント
コメントを投稿