ikkVisualKit 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ikkVisualKit/CTkUiBase.py +555 -0
- ikkVisualKit/Dialog/CdialogBase.py +96 -0
- ikkVisualKit/Dialog/CdialogOk.py +102 -0
- ikkVisualKit/Dialog/CdialogYesNo.py +91 -0
- ikkVisualKit/Dialog/DialogBase.py +97 -0
- ikkVisualKit/Dialog/DialogOk.py +59 -0
- ikkVisualKit/Dialog/DialogSelectReaderPort.py +110 -0
- ikkVisualKit/Dialog/DialogYesNo.py +62 -0
- ikkVisualKit/Dialog/__init__.py +21 -0
- ikkVisualKit/TkUiBase.py +167 -0
- ikkVisualKit/Tray/ResidentApp.py +264 -0
- ikkVisualKit/Tray/TrayMenu.py +140 -0
- ikkVisualKit/Tray/__init__.py +4 -0
- ikkVisualKit/Window/WindowBase.py +149 -0
- ikkVisualKit/Window/WindowBaseModan.py +233 -0
- ikkVisualKit/Window/__init__.py +3 -0
- ikkVisualKit/__init__.py +22 -0
- ikkVisualKit/image/clear.dio.png +0 -0
- ikkVisualKit/image/goto.dio.png +0 -0
- ikkVisualKit/image/help.dio.png +0 -0
- ikkVisualKit/image/link.dio.png +0 -0
- ikkVisualKit/image/lock.dio.png +0 -0
- ikkVisualKit/image/log.dio.png +0 -0
- ikkVisualKit/image/open.dio.png +0 -0
- ikkVisualKit/image/recipe.dio.png +0 -0
- ikkVisualKit/image/save.dio.png +0 -0
- ikkVisualKit/image/search.dio.png +0 -0
- ikkVisualKit/image/setting.dio.png +0 -0
- ikkVisualKit/image/start.dio.png +0 -0
- ikkVisualKit/image/unlock.dio.png +0 -0
- ikkvisualkit-0.0.0.dist-info/METADATA +176 -0
- ikkvisualkit-0.0.0.dist-info/RECORD +35 -0
- ikkvisualkit-0.0.0.dist-info/WHEEL +5 -0
- ikkvisualkit-0.0.0.dist-info/licenses/LICENSE +21 -0
- ikkvisualkit-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# WindowBase.py
|
|
2
|
+
from typing import Optional
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
import tkinter as tk
|
|
6
|
+
|
|
7
|
+
# パッケージ内部のモジュールなので明示的な相対インポートを使用する
|
|
8
|
+
from ..TkUiBase import TkUiBase
|
|
9
|
+
from ..Dialog.DialogOk import DialogOk
|
|
10
|
+
from ..Dialog.DialogYesNo import DialogYesNo
|
|
11
|
+
from ..Dialog.DialogBase import DialogResult
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
class WindowBase(TkUiBase):
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
title="Window",
|
|
20
|
+
size=(600, 300),
|
|
21
|
+
icon_path: Optional[str] = None,
|
|
22
|
+
tray_app: bool = False, #常駐アプリにしたいならTrue
|
|
23
|
+
):
|
|
24
|
+
self._fontSize = 16
|
|
25
|
+
self._tray_app = tray_app
|
|
26
|
+
super().__init__(title, size, icon_path)
|
|
27
|
+
|
|
28
|
+
# ---------------------------------
|
|
29
|
+
def _build(self, root):
|
|
30
|
+
super()._build(root) #アイコン設定は親クラスで行う
|
|
31
|
+
root.protocol("WM_DELETE_WINDOW", self._on_window_close)
|
|
32
|
+
|
|
33
|
+
# ---------------------------------
|
|
34
|
+
def _on_window_close(self):
|
|
35
|
+
"""
|
|
36
|
+
tray_app=True: 常駐アプリ想定で×は非表示
|
|
37
|
+
tray_app=False: 通常アプリ想定で×は終了
|
|
38
|
+
"""
|
|
39
|
+
if self._tray_app:
|
|
40
|
+
self.hide_window()
|
|
41
|
+
return
|
|
42
|
+
self.close()
|
|
43
|
+
|
|
44
|
+
# ---------------------------------
|
|
45
|
+
def close(self):
|
|
46
|
+
"""完全終了"""
|
|
47
|
+
super().close()
|
|
48
|
+
def hide_temporarily(self, delay_ms=2000):
|
|
49
|
+
"""
|
|
50
|
+
一時的に隠して、delay_ms後に再表示
|
|
51
|
+
"""
|
|
52
|
+
self.hide_window()
|
|
53
|
+
|
|
54
|
+
if self._tkRoot:
|
|
55
|
+
self._tkRoot.after(delay_ms, self.show_window)
|
|
56
|
+
# ==========================================================
|
|
57
|
+
# 🔥 ダイアログ表示ヘルパ
|
|
58
|
+
# ==========================================================
|
|
59
|
+
def show_ok_dialog(self, title="OK", message="Message", icon=None):
|
|
60
|
+
dialog = DialogOk(
|
|
61
|
+
parent=self._tkRoot,
|
|
62
|
+
title=title,
|
|
63
|
+
message=message,
|
|
64
|
+
icon=icon
|
|
65
|
+
)
|
|
66
|
+
return dialog.show()
|
|
67
|
+
|
|
68
|
+
def show_yesno_dialog(self, title="Confirm", message="実行しますか?"):
|
|
69
|
+
dialog = DialogYesNo(
|
|
70
|
+
parent=self._tkRoot,
|
|
71
|
+
title=title,
|
|
72
|
+
message=message
|
|
73
|
+
)
|
|
74
|
+
return dialog.show()
|
|
75
|
+
# ==========================================================
|
|
76
|
+
# 🔥 テスト用ウィンドウ
|
|
77
|
+
# ==========================================================
|
|
78
|
+
class TestWindow(WindowBase):
|
|
79
|
+
def __init__(
|
|
80
|
+
self,
|
|
81
|
+
title="Test Window",
|
|
82
|
+
size=(400, 300),
|
|
83
|
+
icon_path: Optional[str] = None,
|
|
84
|
+
tray_app: bool = True,
|
|
85
|
+
):
|
|
86
|
+
super().__init__(title, size, icon_path, tray_app)
|
|
87
|
+
def _build(self, root):
|
|
88
|
+
super()._build(root)
|
|
89
|
+
|
|
90
|
+
root.geometry("400x300")
|
|
91
|
+
|
|
92
|
+
tk.Label(root, text="WindowBase Test", font=("Meiryo", 18)).pack(pady=20)
|
|
93
|
+
|
|
94
|
+
tk.Button(
|
|
95
|
+
root,
|
|
96
|
+
text="OKダイアログ",
|
|
97
|
+
width=20,
|
|
98
|
+
command=self._test_ok
|
|
99
|
+
).pack(pady=10)
|
|
100
|
+
|
|
101
|
+
tk.Button(
|
|
102
|
+
root,
|
|
103
|
+
text="YES/NOダイアログ",
|
|
104
|
+
width=20,
|
|
105
|
+
command=self._test_yesno
|
|
106
|
+
).pack(pady=10)
|
|
107
|
+
|
|
108
|
+
tk.Button(
|
|
109
|
+
root,
|
|
110
|
+
text="2秒隠す",
|
|
111
|
+
width=20,
|
|
112
|
+
command=lambda: self.hide_temporarily(2000)
|
|
113
|
+
).pack(pady=10)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
tk.Button(
|
|
117
|
+
root,
|
|
118
|
+
text="終了",
|
|
119
|
+
width=20,
|
|
120
|
+
command=self.close
|
|
121
|
+
).pack(pady=20)
|
|
122
|
+
|
|
123
|
+
def _test_ok(self):
|
|
124
|
+
self.show_ok_dialog(
|
|
125
|
+
title="完了",
|
|
126
|
+
message="処理が完了しました。"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def _test_yesno(self):
|
|
130
|
+
result = self.show_yesno_dialog(
|
|
131
|
+
title="確認",
|
|
132
|
+
message="本当に実行しますか?"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
if result == DialogResult.YES:
|
|
136
|
+
self.show_ok_dialog(message="YESが選択されました")
|
|
137
|
+
elif result == DialogResult.NO:
|
|
138
|
+
self.show_ok_dialog(message="NOが選択されました")
|
|
139
|
+
# ==========================================================
|
|
140
|
+
# 🔥 実行テスト
|
|
141
|
+
# ==========================================================
|
|
142
|
+
if __name__ == "__main__":
|
|
143
|
+
logging.basicConfig(
|
|
144
|
+
level=logging.DEBUG,
|
|
145
|
+
format="%(asctime)s [%(name)s] %(levelname)s: %(message)s"
|
|
146
|
+
)
|
|
147
|
+
app = TestWindow(title="WindowBase Test", size=(400, 300),icon_path="../../icon.ico")
|
|
148
|
+
app.show_window()
|
|
149
|
+
app.run()
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# WindowBase.py
|
|
2
|
+
from typing import Optional
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
import customtkinter as ctk
|
|
6
|
+
import tkinter as tk
|
|
7
|
+
|
|
8
|
+
# パッケージ内部のモジュールなので明示的な相対インポートを使用する
|
|
9
|
+
from ikkVisualKit.CTkUiBase import CTkUiBase
|
|
10
|
+
from ikkVisualKit.Dialog.DialogOk import DialogOk
|
|
11
|
+
from ikkVisualKit.Dialog.DialogYesNo import DialogYesNo
|
|
12
|
+
from ikkVisualKit.Dialog.DialogBase import DialogResult
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
class WindowBaseModan(CTkUiBase):
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
title="Window",
|
|
20
|
+
version="version",
|
|
21
|
+
size=(600, 300),
|
|
22
|
+
icon_path: Optional[str] = None,
|
|
23
|
+
tray_app: bool = False, #常駐アプリにしたいならTrue
|
|
24
|
+
):
|
|
25
|
+
self._fontSize = 14
|
|
26
|
+
self._tray_app = tray_app
|
|
27
|
+
self._version = version
|
|
28
|
+
self._warning_blink_id: Optional[str] = None # 警告点滅のタイマーID
|
|
29
|
+
self._warning_state = False # True=赤, False=通常
|
|
30
|
+
self._default_fg_color = "#f0f0f0" # デフォルト背景色
|
|
31
|
+
super().__init__(f"{title} - ({version})", size, icon_path)
|
|
32
|
+
|
|
33
|
+
def _MenuBuild(self, menubar):
|
|
34
|
+
# メニューバー作成 (tk を使用)
|
|
35
|
+
menubar = tk.Menu(self._tkRoot, font=("Meiryo", self._fontSize + 6))
|
|
36
|
+
if self._tkRoot:
|
|
37
|
+
self._tkRoot.config(menu=menubar)
|
|
38
|
+
# ファイルメニュー
|
|
39
|
+
file_menu = tk.Menu(menubar, tearoff=0, font=("Meiryo", self._fontSize))
|
|
40
|
+
menubar.add_cascade(label="ファイル", menu=file_menu, font=("Meiryo", self._fontSize + 4))
|
|
41
|
+
file_menu.add_command(label="開く", command=self._on_open)
|
|
42
|
+
file_menu.add_separator()
|
|
43
|
+
file_menu.add_command(label="終了", command=self.close)
|
|
44
|
+
|
|
45
|
+
# 編集メニュー
|
|
46
|
+
edit_menu = tk.Menu(menubar, tearoff=0, font=("Meiryo", self._fontSize))
|
|
47
|
+
menubar.add_cascade(label="編集", menu=edit_menu, font=("Meiryo", self._fontSize + 4))
|
|
48
|
+
edit_menu.add_command(label="コピー", command=self._on_copy)
|
|
49
|
+
# ---------------------------------
|
|
50
|
+
def _build(self, root):
|
|
51
|
+
super()._build(root) #アイコン設定は親クラスで行う
|
|
52
|
+
root.protocol("WM_DELETE_WINDOW", self._on_window_close)
|
|
53
|
+
|
|
54
|
+
# ---------------------------------
|
|
55
|
+
def _on_window_close(self):
|
|
56
|
+
"""
|
|
57
|
+
tray_app=True: 常駐アプリ想定で×は非表示
|
|
58
|
+
tray_app=False: 通常アプリ想定で×は終了
|
|
59
|
+
"""
|
|
60
|
+
if self._tray_app:
|
|
61
|
+
self.hide_window()
|
|
62
|
+
return
|
|
63
|
+
self.close()
|
|
64
|
+
|
|
65
|
+
# ---------------------------------
|
|
66
|
+
def close(self):
|
|
67
|
+
"""完全終了"""
|
|
68
|
+
if self._tkRoot:
|
|
69
|
+
self._tkRoot.quit()
|
|
70
|
+
super().close()
|
|
71
|
+
def hide_temporarily(self, delay_ms=2000):
|
|
72
|
+
"""
|
|
73
|
+
一時的に隠して、delay_ms後に再表示
|
|
74
|
+
"""
|
|
75
|
+
self.hide_window()
|
|
76
|
+
|
|
77
|
+
if self._tkRoot:
|
|
78
|
+
self._tkRoot.after(delay_ms, self.show_window)
|
|
79
|
+
# ==========================================================
|
|
80
|
+
# 🔥 ダイアログ表示ヘルパ
|
|
81
|
+
# ==========================================================
|
|
82
|
+
def show_ok_dialog(self, title="OK", message="Message", icon=None):
|
|
83
|
+
dialog = DialogOk(
|
|
84
|
+
parent=self._tkRoot,
|
|
85
|
+
title=title,
|
|
86
|
+
message=message,
|
|
87
|
+
icon=icon
|
|
88
|
+
)
|
|
89
|
+
return dialog.show()
|
|
90
|
+
|
|
91
|
+
def show_yesno_dialog(self, title="Confirm", message="実行しますか?"):
|
|
92
|
+
dialog = DialogYesNo(
|
|
93
|
+
parent=self._tkRoot,
|
|
94
|
+
title=title,
|
|
95
|
+
message=message
|
|
96
|
+
)
|
|
97
|
+
return dialog.show()
|
|
98
|
+
|
|
99
|
+
# ==========================================================
|
|
100
|
+
# メニューハンドラ
|
|
101
|
+
# ==========================================================
|
|
102
|
+
def _on_open(self):
|
|
103
|
+
"""ファイル開くメニューのハンドラ"""
|
|
104
|
+
logger.info("Open file clicked")
|
|
105
|
+
self.show_ok_dialog(title="ファイルを開く", message="ファイル選択機能を実装してください")
|
|
106
|
+
|
|
107
|
+
def _on_copy(self):
|
|
108
|
+
"""コピーメニューのハンドラ"""
|
|
109
|
+
logger.info("Copy clicked")
|
|
110
|
+
self.show_ok_dialog(title="コピー", message="コピー機能を実装してください")
|
|
111
|
+
# ==========================================================
|
|
112
|
+
# 警告表示
|
|
113
|
+
# ==========================================================
|
|
114
|
+
def warning_blink(self, blink_interval_ms: int = 200,blink_count: int = 3):
|
|
115
|
+
"""
|
|
116
|
+
ウィンドウの背景を赤くチカチカさせる警告表示
|
|
117
|
+
blink_interval_ms: 点滅の間隔(ミリ秒)
|
|
118
|
+
blink_count: 点滅の回数(デフォルト3回)
|
|
119
|
+
"""
|
|
120
|
+
if not self._tkRoot:
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
# 既に点滅中ならキャンセル
|
|
124
|
+
if self._warning_blink_id:
|
|
125
|
+
self._tkRoot.after_cancel(self._warning_blink_id)
|
|
126
|
+
|
|
127
|
+
counter = [0] # 点滅回数カウンター
|
|
128
|
+
|
|
129
|
+
def blink():
|
|
130
|
+
if not self._tkRoot:
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
# 指定回数に達したら終了
|
|
134
|
+
if counter[0] >= blink_count * 2: # 赤と通常で2回カウント
|
|
135
|
+
self._tkRoot.configure(fg_color=self._default_fg_color)
|
|
136
|
+
self._warning_blink_id = None
|
|
137
|
+
return
|
|
138
|
+
|
|
139
|
+
# 赤と通常を交互に表示
|
|
140
|
+
self._warning_state = not self._warning_state
|
|
141
|
+
color = "#ff4444" if self._warning_state else self._default_fg_color
|
|
142
|
+
self._tkRoot.configure(fg_color=color)
|
|
143
|
+
|
|
144
|
+
counter[0] += 1
|
|
145
|
+
# 次の点滅をスケジュール
|
|
146
|
+
self._warning_blink_id = self._tkRoot.after(blink_interval_ms, blink)
|
|
147
|
+
|
|
148
|
+
blink()
|
|
149
|
+
|
|
150
|
+
def stop_warning(self):
|
|
151
|
+
"""警告点滅を停止してデフォルト色に戻す"""
|
|
152
|
+
if not self._tkRoot:
|
|
153
|
+
return
|
|
154
|
+
|
|
155
|
+
if self._warning_blink_id:
|
|
156
|
+
self._tkRoot.after_cancel(self._warning_blink_id)
|
|
157
|
+
self._warning_blink_id = None
|
|
158
|
+
|
|
159
|
+
self._tkRoot.configure(fg_color=self._default_fg_color)
|
|
160
|
+
# ==========================================================
|
|
161
|
+
# 🔥 テスト用ウィンドウ
|
|
162
|
+
# ==========================================================
|
|
163
|
+
class TestWindow(WindowBaseModan):
|
|
164
|
+
def __init__(
|
|
165
|
+
self,
|
|
166
|
+
title="Test Window",
|
|
167
|
+
size=(400, 300),
|
|
168
|
+
icon_path: Optional[str] = None,
|
|
169
|
+
):
|
|
170
|
+
super().__init__(title, size, icon_path, tray_app=False)
|
|
171
|
+
def _build(self, root):
|
|
172
|
+
super()._build(root)
|
|
173
|
+
|
|
174
|
+
root.geometry("400x300")
|
|
175
|
+
|
|
176
|
+
ctk.CTkLabel(root, text="WindowBaseModan Test", font=("Meiryo", 18)).pack(pady=20)
|
|
177
|
+
|
|
178
|
+
ctk.CTkButton(
|
|
179
|
+
root,
|
|
180
|
+
text="OKダイアログ",
|
|
181
|
+
width=20,
|
|
182
|
+
command=self._test_ok
|
|
183
|
+
).pack(pady=10)
|
|
184
|
+
|
|
185
|
+
ctk.CTkButton(
|
|
186
|
+
root,
|
|
187
|
+
text="YES/NOダイアログ",
|
|
188
|
+
width=20,
|
|
189
|
+
command=self._test_yesno
|
|
190
|
+
).pack(pady=10)
|
|
191
|
+
|
|
192
|
+
ctk.CTkButton(
|
|
193
|
+
root,
|
|
194
|
+
text="2秒隠す",
|
|
195
|
+
width=20,
|
|
196
|
+
command=lambda: self.hide_temporarily(2000)
|
|
197
|
+
).pack(pady=10)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
ctk.CTkButton(
|
|
201
|
+
root,
|
|
202
|
+
text="終了",
|
|
203
|
+
width=20,
|
|
204
|
+
command=self.close
|
|
205
|
+
).pack(pady=20)
|
|
206
|
+
|
|
207
|
+
def _test_ok(self):
|
|
208
|
+
self.show_ok_dialog(
|
|
209
|
+
title="完了",
|
|
210
|
+
message="処理が完了しました。"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
def _test_yesno(self):
|
|
214
|
+
result = self.show_yesno_dialog(
|
|
215
|
+
title="確認",
|
|
216
|
+
message="本当に実行しますか?"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
if result == DialogResult.YES:
|
|
220
|
+
self.show_ok_dialog(message="YESが選択されました")
|
|
221
|
+
elif result == DialogResult.NO:
|
|
222
|
+
self.show_ok_dialog(message="NOが選択されました")
|
|
223
|
+
# ==========================================================
|
|
224
|
+
# 🔥 実行テスト
|
|
225
|
+
# ==========================================================
|
|
226
|
+
if __name__ == "__main__":
|
|
227
|
+
logging.basicConfig(
|
|
228
|
+
level=logging.DEBUG,
|
|
229
|
+
format="%(asctime)s [%(name)s] %(levelname)s: %(message)s"
|
|
230
|
+
)
|
|
231
|
+
app = TestWindow(title="WindowBase Test", size=(400, 300),icon_path="../../icon.ico")
|
|
232
|
+
app.show_window()
|
|
233
|
+
app.run()
|
ikkVisualKit/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from .TkUiBase import TkUiBase
|
|
2
|
+
from .CTkUiBase import CTkUiBase
|
|
3
|
+
from .Window import WindowBase
|
|
4
|
+
from .Window import WindowBaseModan
|
|
5
|
+
from .Dialog import DialogBase, DialogResult, DialogIcon, DialogOk, DialogYesNo, DialogSelectReaderPort
|
|
6
|
+
from .Tray import TrayMenu, acquire_single_instance_guard, SingleInstanceGuard
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"TkUiBase",
|
|
10
|
+
"CTkUiBase",
|
|
11
|
+
"WindowBase",
|
|
12
|
+
"WindowBaseModan",
|
|
13
|
+
"DialogBase",
|
|
14
|
+
"DialogResult",
|
|
15
|
+
"DialogIcon",
|
|
16
|
+
"DialogOk",
|
|
17
|
+
"DialogYesNo",
|
|
18
|
+
"DialogSelectReaderPort",
|
|
19
|
+
"TrayMenu",
|
|
20
|
+
"acquire_single_instance_guard",
|
|
21
|
+
"SingleInstanceGuard",
|
|
22
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ikkVisualKit
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: Insight.k.k. VisualKit for easy application development
|
|
5
|
+
Author-email: "Insight.k.k. Team" <maintainer@insightkk.net>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://insightkk.net/oss/ikkVisualKit
|
|
8
|
+
Project-URL: Documentation, https://insightkk.net/oss/ikkVisualKit/api/index.html
|
|
9
|
+
Project-URL: Issues, https://github.com/Insight-kk/ikkVisualKit/issues
|
|
10
|
+
Project-URL: Source, https://github.com/Insight-kk/ikkVisualKit
|
|
11
|
+
Keywords: gui,tkinter,toolkit,ui,framework
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: cantok>=0.0.1
|
|
26
|
+
Requires-Dist: asyncio-cancel-token>=0.2.0
|
|
27
|
+
Requires-Dist: pystray>=0.19.4
|
|
28
|
+
Requires-Dist: Pillow>=9.0
|
|
29
|
+
Requires-Dist: keyboard>=0.13.5
|
|
30
|
+
Requires-Dist: customtkinter>=5.2.2
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# ikkVisualKit
|
|
34
|
+
|
|
35
|
+
Pythonアプリケーション開発用の軽量GUIツールキット。tkinterとcustomtkinterをベースに、ウィンドウ、ダイアログ、システムトレイアプリケーション用の汎用コンポーネントを提供します。
|
|
36
|
+
|
|
37
|
+
## 主な機能
|
|
38
|
+
|
|
39
|
+
- **ウィンドウベースクラス** - CTkやtkinterベースのウィンドウを簡単に構築
|
|
40
|
+
- **ダイアログコンポーネント** - OK、YesNo、カスタムダイアログなど汎用ダイアログ
|
|
41
|
+
- **システムトレイ対応** - トレイメニュー、常駐アプリケーション機能
|
|
42
|
+
- **画像管理** - パッケージ内の画像リソースを統一的に管理
|
|
43
|
+
|
|
44
|
+
## インストール
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install ikkVisualKit
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 使用例
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from ikkVisualKit import WindowBaseModan
|
|
54
|
+
|
|
55
|
+
class MainWindow(WindowBaseModan):
|
|
56
|
+
def __init__(self):
|
|
57
|
+
super().__init__(
|
|
58
|
+
title="My Application",
|
|
59
|
+
version="1.0.0",
|
|
60
|
+
size=(1000, 600)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def _build(self, root):
|
|
64
|
+
super()._build(root)
|
|
65
|
+
# UIパーツの配置
|
|
66
|
+
|
|
67
|
+
if __name__ == "__main__":
|
|
68
|
+
app = MainWindow()
|
|
69
|
+
app.show_window()
|
|
70
|
+
app.run()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Overview
|
|
74
|
+
[ikkVisualKit](https://github.com/Insight-kk/ikkVisualKit/tree/8c55eac18e43b5ea5136d7e2d33febff9a346d79)はGUIアプリ作成用典型的なパーツのToolKitです。
|
|
75
|
+
|
|
76
|
+
# Feature
|
|
77
|
+
* CustomTkinterベース
|
|
78
|
+
* DPIスケーリング対応
|
|
79
|
+
* フォームアプリの作成が容易になるBaseクラスの提供
|
|
80
|
+
* フォームアプリ向けに
|
|
81
|
+
* 常駐(タスクトレイ)アプリの作成を用意するテンプレートの提供
|
|
82
|
+
* サイズの大きいカスタムメッセージダイアログの提供
|
|
83
|
+
|
|
84
|
+
# インストール方法
|
|
85
|
+
```
|
|
86
|
+
pip install ikkVisualKit
|
|
87
|
+
````
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# 利用方法
|
|
92
|
+
```python
|
|
93
|
+
from ikkVisualKit import WindowBaseModan #ファームアプリを作成する場合
|
|
94
|
+
from ikkVisualKit import DialogResult #ダイアログを利用する場合
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# フォームアプリケーションの作成方法
|
|
99
|
+
|
|
100
|
+
## フォームの作成
|
|
101
|
+
1. `WindowBaseModan`を継承した任意のウインドウクラスを作成します。
|
|
102
|
+
1. `def _build(self, root):`をオーバライドして,`super()._build(root)`を実行します。
|
|
103
|
+
1. `show_window()`と`run()`を実行するとWindowアプリケーションが起動します。
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from ikkVisualKit import WindowBaseModan
|
|
107
|
+
|
|
108
|
+
class MainWindow(WindowBaseModan):
|
|
109
|
+
def __init__(self):
|
|
110
|
+
super().__init__(
|
|
111
|
+
title="MyApplecation", #アプリ名
|
|
112
|
+
version="0.0.0", #バージョン
|
|
113
|
+
size=(1000, 600), #ウィンドウサイズ
|
|
114
|
+
icon_path="resources/icon.dio.ico", #アイコンパス(.ico推奨)
|
|
115
|
+
tray_app=False #常駐アプリにしたいならTrue
|
|
116
|
+
)
|
|
117
|
+
#----------------------------------------------
|
|
118
|
+
def _build(self, root):
|
|
119
|
+
super()._build(root)
|
|
120
|
+
#パーツの配置
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
app = MainWindow()
|
|
123
|
+
app.show_window()
|
|
124
|
+
app.run()
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
## カスタムボタン
|
|
129
|
+
* 大中小3タイプのボタンサイズを用意
|
|
130
|
+
* ツールチップテキストをプロパティとして用意
|
|
131
|
+
* マウスホバー時の色変更
|
|
132
|
+
* ボタンに付与するアイコン画像を予め用意
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
### 小さいアイコン付きボタン
|
|
137
|
+
以下のコードは小さいサイズのアイコン付きボタンを作成する例です。
|
|
138
|
+
コンストラクタのx,yに配置する座標を指定し、image_keyで[アイコン](#小さいアイコン付きボタン)を指定してください。
|
|
139
|
+
ツールチップテキストと、イベントハンドラを後から登録することが可能です。
|
|
140
|
+
```python
|
|
141
|
+
self.btnSetting = self.make_ActionButton(x=16 , y=176, image_key="setting.dio")
|
|
142
|
+
self.btnSetting.tooltip_text = "設定を開く" #ツールチップテキスト設定
|
|
143
|
+
self.btnSetting.command = self.on_setting #ボタン押下で実行する関数の登録
|
|
144
|
+
```
|
|
145
|
+

|
|
146
|
+
|
|
147
|
+
### 大きいサイズのボタン
|
|
148
|
+
大きいサイズのボタンを利用する場合ば`size_rank=1`もしくは`size_rank=2`を指定してください。また、`text=`で指定した文字がアイコンと共に表示されます。
|
|
149
|
+
```python
|
|
150
|
+
self.btnStart = self.make_ActionButton(624, 16 , image_key="start.dio",size_rank=2,text="検査スタート")
|
|
151
|
+
self.btnClear = self.make_ActionButton(784, 16 , image_key="clear.dio",size_rank=1,text="クリア")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
### アイコンの一覧
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Name |Image
|
|
162
|
+
----------|-------------------------
|
|
163
|
+
clear.dio | 
|
|
164
|
+
goto.dio | 
|
|
165
|
+
help.dio | 
|
|
166
|
+
link.dio | 
|
|
167
|
+
lock.dio | 
|
|
168
|
+
log.dio | 
|
|
169
|
+
open.dio | 
|
|
170
|
+
recipe.dio | 
|
|
171
|
+
save.dio | 
|
|
172
|
+
search.dio | 
|
|
173
|
+
setting.dio | 
|
|
174
|
+
start.dio | 
|
|
175
|
+
unlock.dio | 
|
|
176
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
ikkVisualKit/CTkUiBase.py,sha256=m6P-rMANSKtYbifM-lvDOK0SVid7z-xlnhzpui2jLIc,21487
|
|
2
|
+
ikkVisualKit/TkUiBase.py,sha256=GZ14L6_QsP_ZP0p5v7aKf2JcZFNR7KezG0eaZFtTZJA,6296
|
|
3
|
+
ikkVisualKit/__init__.py,sha256=UaYw1vDRK28v80mMW4eAkOywuNEeizWfDUrS3wSpkWU,624
|
|
4
|
+
ikkVisualKit/Dialog/CdialogBase.py,sha256=pON-idPRmYGPNMca1KyChXgw9cxtN4fbzUFDI1EBIPg,2731
|
|
5
|
+
ikkVisualKit/Dialog/CdialogOk.py,sha256=xSCKnBaj2_uvSwYTh-6CuSZr1S11kFUbliZffFnB36w,3919
|
|
6
|
+
ikkVisualKit/Dialog/CdialogYesNo.py,sha256=bcQ_qYWrTO6aAKWJhswwVG3URS4IT9gZQnS5GuqGe78,3308
|
|
7
|
+
ikkVisualKit/Dialog/DialogBase.py,sha256=HWDtvvHUj2E8-baVRoAncGh-17mZJZq_I6V-paCYluo,2559
|
|
8
|
+
ikkVisualKit/Dialog/DialogOk.py,sha256=C84fS0Qthiq8kiHZ0L2IRtEsbRUvtsW9tXJBLztTWUg,1744
|
|
9
|
+
ikkVisualKit/Dialog/DialogSelectReaderPort.py,sha256=8QwV_qL7ezmov9KDkWaZROtuVWfdsN3R7pQi8YdiB-U,4216
|
|
10
|
+
ikkVisualKit/Dialog/DialogYesNo.py,sha256=KoiH7E4xazocvcqKF8lMG0Ekfu7Omk0lWBcZdCKH5MU,1791
|
|
11
|
+
ikkVisualKit/Dialog/__init__.py,sha256=taqpiXoytQYrdjedb2eo9PhO4WQk93Iyte-SQ5X5u-A,583
|
|
12
|
+
ikkVisualKit/Tray/ResidentApp.py,sha256=vLWyGjeostSLxBJ44jn60quMA92woTEMrujkrknOl3o,11161
|
|
13
|
+
ikkVisualKit/Tray/TrayMenu.py,sha256=5kIPFoQU5ME89zIDv4L9GD9YYBfykpgH9xZBbX3pocM,5909
|
|
14
|
+
ikkVisualKit/Tray/__init__.py,sha256=buX2-NLnW5GohIlS9O_WsuoMbMziqEJsngMIkY9jPc0,189
|
|
15
|
+
ikkVisualKit/Window/WindowBase.py,sha256=RxA7ERKCGRE0bCx76Fd97pJqIUcQrQrDEk3GHOPH2QY,4592
|
|
16
|
+
ikkVisualKit/Window/WindowBaseModan.py,sha256=Ve6WGbDR3XJGqsgkhdkn0OaUHJG5pc9OPUkhSRTmr4Y,8548
|
|
17
|
+
ikkVisualKit/Window/__init__.py,sha256=I6CUnRL9PhipKrFm8rzk4CBctxp4WYaoi0kwdJ54H1s,124
|
|
18
|
+
ikkVisualKit/image/clear.dio.png,sha256=RqpihM7ueImKat3AgTsFeyC6VplP9YXc-HPp00VDOec,4180
|
|
19
|
+
ikkVisualKit/image/goto.dio.png,sha256=V7IJzu9Z9OLqHtKCjLbOIs8IH4Q3SbZ-0Eg-qSdYtIo,2853
|
|
20
|
+
ikkVisualKit/image/help.dio.png,sha256=SWrxIIrEE-9nJn45pBcjI6ywEKAukzgMM78YvqwfYGs,4438
|
|
21
|
+
ikkVisualKit/image/link.dio.png,sha256=_ZnUtiwQC2CKRK8zlWioyK-kr6kojzsbLC7LDBpVxZQ,3764
|
|
22
|
+
ikkVisualKit/image/lock.dio.png,sha256=dNykfUNn5u4epur44YlVx_ZrMs0wg5xBQ4ohjB1oPZw,1920
|
|
23
|
+
ikkVisualKit/image/log.dio.png,sha256=Z3UWEpkBnAv3yDILB5QVK-7T-YcaIRV0anW3SoOAzSQ,7759
|
|
24
|
+
ikkVisualKit/image/open.dio.png,sha256=tVk-iYtD6CMTau0YU4pgT_Wvik3zs8zUrFlYHE15Esc,3495
|
|
25
|
+
ikkVisualKit/image/recipe.dio.png,sha256=zLZkFqbpPPQ_lKRoQs6yaDetLn0N8YxLNR2YdDWBL9I,4287
|
|
26
|
+
ikkVisualKit/image/save.dio.png,sha256=mn7TNq4j-i-PCuTGy8qbq6__7X3YK_xMA3iZRX50ACA,3806
|
|
27
|
+
ikkVisualKit/image/search.dio.png,sha256=rphbFSic2GOxyJJ7rBG5XW9ixD6QgqWJHsy-G-GOTso,3617
|
|
28
|
+
ikkVisualKit/image/setting.dio.png,sha256=d2SlQv2kUxoWg6T6ctPs-BKDcQgB-1povtAiM6x8QCw,5713
|
|
29
|
+
ikkVisualKit/image/start.dio.png,sha256=aTAw-qEYn5exK4JSU9Fsmmj9rC29hKxHJ5vO9xkSCr4,2677
|
|
30
|
+
ikkVisualKit/image/unlock.dio.png,sha256=uUh_0o4OlMSefRfjkwzm-_93ldAHqMwyW2eAUx6gmF8,1992
|
|
31
|
+
ikkvisualkit-0.0.0.dist-info/licenses/LICENSE,sha256=iZYpTwH3MGkBfHX33UbeM0xcbdfUDRUXFZ27Y72IR2s,1089
|
|
32
|
+
ikkvisualkit-0.0.0.dist-info/METADATA,sha256=5Sc-Dv2Zq1ttPUUKDknodYLzA7KLdIvgRinSCqVUIcQ,6887
|
|
33
|
+
ikkvisualkit-0.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
34
|
+
ikkvisualkit-0.0.0.dist-info/top_level.txt,sha256=bUu-5M-Culj3c-FB5ag_2xKW9lrx4T93AaozSv5BSHg,13
|
|
35
|
+
ikkvisualkit-0.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Insight.k.k
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|