pyxllib 0.3.197__py3-none-any.whl → 3.201.1__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.
- pyxllib/__init__.py +14 -21
- pyxllib/algo/__init__.py +8 -8
- pyxllib/algo/disjoint.py +54 -54
- pyxllib/algo/geo.py +537 -541
- pyxllib/algo/intervals.py +964 -964
- pyxllib/algo/matcher.py +389 -389
- pyxllib/algo/newbie.py +166 -166
- pyxllib/algo/pupil.py +629 -629
- pyxllib/algo/shapelylib.py +67 -67
- pyxllib/algo/specialist.py +241 -241
- pyxllib/algo/stat.py +494 -494
- pyxllib/algo/treelib.py +145 -149
- pyxllib/algo/unitlib.py +62 -66
- pyxllib/autogui/__init__.py +5 -5
- pyxllib/autogui/activewin.py +246 -246
- pyxllib/autogui/all.py +9 -9
- pyxllib/autogui/autogui.py +846 -852
- pyxllib/autogui/uiautolib.py +362 -362
- pyxllib/autogui/virtualkey.py +102 -102
- pyxllib/autogui/wechat.py +827 -827
- pyxllib/autogui/wechat_msg.py +421 -421
- pyxllib/autogui/wxautolib.py +84 -84
- pyxllib/cv/__init__.py +5 -5
- pyxllib/cv/expert.py +267 -267
- pyxllib/cv/imfile.py +159 -159
- pyxllib/cv/imhash.py +39 -39
- pyxllib/cv/pupil.py +9 -9
- pyxllib/cv/rgbfmt.py +1525 -1525
- pyxllib/cv/slidercaptcha.py +137 -137
- pyxllib/cv/trackbartools.py +251 -251
- pyxllib/cv/xlcvlib.py +1040 -1040
- pyxllib/cv/xlpillib.py +423 -423
- pyxllib/data/echarts.py +236 -240
- pyxllib/data/jsonlib.py +85 -89
- pyxllib/data/oss.py +72 -72
- pyxllib/data/pglib.py +1111 -1127
- pyxllib/data/sqlite.py +568 -568
- pyxllib/data/sqllib.py +297 -297
- pyxllib/ext/JLineViewer.py +505 -505
- pyxllib/ext/__init__.py +6 -6
- pyxllib/ext/demolib.py +251 -246
- pyxllib/ext/drissionlib.py +277 -277
- pyxllib/ext/kq5034lib.py +12 -12
- pyxllib/ext/qt.py +449 -449
- pyxllib/ext/robustprocfile.py +493 -497
- pyxllib/ext/seleniumlib.py +76 -76
- pyxllib/ext/tk.py +173 -173
- pyxllib/ext/unixlib.py +821 -827
- pyxllib/ext/utools.py +345 -351
- pyxllib/ext/webhook.py +124 -119
- pyxllib/ext/win32lib.py +40 -40
- pyxllib/ext/wjxlib.py +91 -88
- pyxllib/ext/wpsapi.py +124 -124
- pyxllib/ext/xlwork.py +9 -9
- pyxllib/ext/yuquelib.py +1110 -1105
- pyxllib/file/__init__.py +17 -17
- pyxllib/file/docxlib.py +757 -761
- pyxllib/file/gitlib.py +309 -309
- pyxllib/file/libreoffice.py +165 -165
- pyxllib/file/movielib.py +144 -148
- pyxllib/file/newbie.py +10 -10
- pyxllib/file/onenotelib.py +1469 -1469
- pyxllib/file/packlib/__init__.py +330 -330
- pyxllib/file/packlib/zipfile.py +2441 -2441
- pyxllib/file/pdflib.py +422 -426
- pyxllib/file/pupil.py +185 -185
- pyxllib/file/specialist/__init__.py +681 -685
- pyxllib/file/specialist/dirlib.py +799 -799
- pyxllib/file/specialist/download.py +193 -193
- pyxllib/file/specialist/filelib.py +2825 -2829
- pyxllib/file/xlsxlib.py +3122 -3131
- pyxllib/file/xlsyncfile.py +341 -341
- pyxllib/prog/__init__.py +5 -5
- pyxllib/prog/cachetools.py +58 -64
- pyxllib/prog/deprecatedlib.py +233 -233
- pyxllib/prog/filelock.py +42 -42
- pyxllib/prog/ipyexec.py +253 -253
- pyxllib/prog/multiprogs.py +940 -940
- pyxllib/prog/newbie.py +451 -451
- pyxllib/prog/pupil.py +1208 -1197
- pyxllib/prog/sitepackages.py +33 -33
- pyxllib/prog/specialist/__init__.py +348 -391
- pyxllib/prog/specialist/bc.py +203 -203
- pyxllib/prog/specialist/browser.py +497 -497
- pyxllib/prog/specialist/common.py +347 -347
- pyxllib/prog/specialist/datetime.py +198 -198
- pyxllib/prog/specialist/tictoc.py +240 -240
- pyxllib/prog/specialist/xllog.py +180 -180
- pyxllib/prog/xlosenv.py +110 -108
- pyxllib/stdlib/__init__.py +17 -17
- pyxllib/stdlib/tablepyxl/__init__.py +10 -10
- pyxllib/stdlib/tablepyxl/style.py +303 -303
- pyxllib/stdlib/tablepyxl/tablepyxl.py +130 -130
- pyxllib/text/__init__.py +8 -8
- pyxllib/text/ahocorasick.py +36 -39
- pyxllib/text/airscript.js +754 -744
- pyxllib/text/charclasslib.py +121 -121
- pyxllib/text/jiebalib.py +267 -267
- pyxllib/text/jinjalib.py +27 -32
- pyxllib/text/jsa_ai_prompt.md +271 -271
- pyxllib/text/jscode.py +922 -922
- pyxllib/text/latex/__init__.py +158 -158
- pyxllib/text/levenshtein.py +303 -303
- pyxllib/text/nestenv.py +1215 -1215
- pyxllib/text/newbie.py +300 -300
- pyxllib/text/pupil/__init__.py +8 -8
- pyxllib/text/pupil/common.py +1121 -1121
- pyxllib/text/pupil/xlalign.py +326 -326
- pyxllib/text/pycode.py +47 -47
- pyxllib/text/specialist/__init__.py +8 -8
- pyxllib/text/specialist/common.py +112 -112
- pyxllib/text/specialist/ptag.py +186 -186
- pyxllib/text/spellchecker.py +172 -172
- pyxllib/text/templates/echart_base.html +10 -10
- pyxllib/text/templates/highlight_code.html +16 -16
- pyxllib/text/templates/latex_editor.html +102 -102
- pyxllib/text/vbacode.py +17 -17
- pyxllib/text/xmllib.py +741 -747
- pyxllib/xl.py +42 -39
- pyxllib/xlcv.py +17 -17
- pyxllib-3.201.1.dist-info/METADATA +296 -0
- pyxllib-3.201.1.dist-info/RECORD +125 -0
- {pyxllib-0.3.197.dist-info → pyxllib-3.201.1.dist-info}/licenses/LICENSE +190 -190
- pyxllib/ext/old.py +0 -663
- pyxllib-0.3.197.dist-info/METADATA +0 -48
- pyxllib-0.3.197.dist-info/RECORD +0 -126
- {pyxllib-0.3.197.dist-info → pyxllib-3.201.1.dist-info}/WHEEL +0 -0
pyxllib/ext/seleniumlib.py
CHANGED
@@ -1,76 +1,76 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
# @Author : 陈坤泽
|
4
|
-
# @Email : 877362867@qq.com
|
5
|
-
# @Date : 2023/03/28
|
6
|
-
|
7
|
-
import time
|
8
|
-
|
9
|
-
from selenium import webdriver
|
10
|
-
from selenium.webdriver.common.by import By
|
11
|
-
from selenium.webdriver.support.ui import WebDriverWait
|
12
|
-
from selenium.webdriver.support import expected_conditions as EC
|
13
|
-
from selenium.common.exceptions import ElementClickInterceptedException, NoSuchWindowException
|
14
|
-
|
15
|
-
|
16
|
-
class element_has_text(object):
|
17
|
-
def __init__(self, locator, text):
|
18
|
-
self.locator = locator
|
19
|
-
self.text = text
|
20
|
-
|
21
|
-
def __call__(self, driver):
|
22
|
-
element = driver.find_element(*self.locator)
|
23
|
-
if self.text in element.text:
|
24
|
-
return element
|
25
|
-
else:
|
26
|
-
return False
|
27
|
-
|
28
|
-
|
29
|
-
class XlChrome(webdriver.Chrome):
|
30
|
-
def __init__(self, *args, **kwargs):
|
31
|
-
super().__init__(*args, **kwargs)
|
32
|
-
self.maximize_window()
|
33
|
-
|
34
|
-
def locate(self, locator, seconds=10):
|
35
|
-
""" 定位一个元素 """
|
36
|
-
if isinstance(locator, str): # 默认是XPATH格式
|
37
|
-
locator = (By.XPATH, locator)
|
38
|
-
return WebDriverWait(self, seconds).until(EC.presence_of_element_located(locator))
|
39
|
-
|
40
|
-
def click(self, locator, seconds=10, check=True):
|
41
|
-
""" 点击一个元素 """
|
42
|
-
if isinstance(locator, str):
|
43
|
-
locator = (By.XPATH, locator)
|
44
|
-
if check:
|
45
|
-
element = WebDriverWait(self, seconds).until(EC.element_to_be_clickable(locator))
|
46
|
-
else:
|
47
|
-
element = self.locate(locator, seconds)
|
48
|
-
time.sleep(0.5) # 最好稍微等一下再点击
|
49
|
-
try:
|
50
|
-
element.click()
|
51
|
-
except ElementClickInterceptedException:
|
52
|
-
# 特殊情况,例如小鹅通下载页面的"下载"按钮没法正常click,要用js脚本去click
|
53
|
-
self.execute_script("arguments[0].click();", element)
|
54
|
-
|
55
|
-
def locate_text(self, locator, text, seconds=10):
|
56
|
-
""" 判断指定元素位置是否含有指定文本 """
|
57
|
-
if isinstance(locator, str):
|
58
|
-
locator = (By.XPATH, locator)
|
59
|
-
return WebDriverWait(self, seconds).until(element_has_text(locator, text))
|
60
|
-
|
61
|
-
def __bool__(self):
|
62
|
-
""" 判断driver是否还存在,如果已被手动关闭,这个值会返回False """
|
63
|
-
try:
|
64
|
-
self.title
|
65
|
-
return True
|
66
|
-
except NoSuchWindowException:
|
67
|
-
return False
|
68
|
-
|
69
|
-
|
70
|
-
def get_global_driver(_driver_store=[None]): # trick
|
71
|
-
""" 通过这个接口可以固定一个driver来使用 """
|
72
|
-
if _driver_store[0] is None:
|
73
|
-
_driver_store[0] = XlChrome()
|
74
|
-
if not _driver_store[0]: # 如果驱动没了,重新启动
|
75
|
-
_driver_store[0] = XlChrome()
|
76
|
-
return _driver_store[0]
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Author : 陈坤泽
|
4
|
+
# @Email : 877362867@qq.com
|
5
|
+
# @Date : 2023/03/28
|
6
|
+
|
7
|
+
import time
|
8
|
+
|
9
|
+
from selenium import webdriver
|
10
|
+
from selenium.webdriver.common.by import By
|
11
|
+
from selenium.webdriver.support.ui import WebDriverWait
|
12
|
+
from selenium.webdriver.support import expected_conditions as EC
|
13
|
+
from selenium.common.exceptions import ElementClickInterceptedException, NoSuchWindowException
|
14
|
+
|
15
|
+
|
16
|
+
class element_has_text(object):
|
17
|
+
def __init__(self, locator, text):
|
18
|
+
self.locator = locator
|
19
|
+
self.text = text
|
20
|
+
|
21
|
+
def __call__(self, driver):
|
22
|
+
element = driver.find_element(*self.locator)
|
23
|
+
if self.text in element.text:
|
24
|
+
return element
|
25
|
+
else:
|
26
|
+
return False
|
27
|
+
|
28
|
+
|
29
|
+
class XlChrome(webdriver.Chrome):
|
30
|
+
def __init__(self, *args, **kwargs):
|
31
|
+
super().__init__(*args, **kwargs)
|
32
|
+
self.maximize_window()
|
33
|
+
|
34
|
+
def locate(self, locator, seconds=10):
|
35
|
+
""" 定位一个元素 """
|
36
|
+
if isinstance(locator, str): # 默认是XPATH格式
|
37
|
+
locator = (By.XPATH, locator)
|
38
|
+
return WebDriverWait(self, seconds).until(EC.presence_of_element_located(locator))
|
39
|
+
|
40
|
+
def click(self, locator, seconds=10, check=True):
|
41
|
+
""" 点击一个元素 """
|
42
|
+
if isinstance(locator, str):
|
43
|
+
locator = (By.XPATH, locator)
|
44
|
+
if check:
|
45
|
+
element = WebDriverWait(self, seconds).until(EC.element_to_be_clickable(locator))
|
46
|
+
else:
|
47
|
+
element = self.locate(locator, seconds)
|
48
|
+
time.sleep(0.5) # 最好稍微等一下再点击
|
49
|
+
try:
|
50
|
+
element.click()
|
51
|
+
except ElementClickInterceptedException:
|
52
|
+
# 特殊情况,例如小鹅通下载页面的"下载"按钮没法正常click,要用js脚本去click
|
53
|
+
self.execute_script("arguments[0].click();", element)
|
54
|
+
|
55
|
+
def locate_text(self, locator, text, seconds=10):
|
56
|
+
""" 判断指定元素位置是否含有指定文本 """
|
57
|
+
if isinstance(locator, str):
|
58
|
+
locator = (By.XPATH, locator)
|
59
|
+
return WebDriverWait(self, seconds).until(element_has_text(locator, text))
|
60
|
+
|
61
|
+
def __bool__(self):
|
62
|
+
""" 判断driver是否还存在,如果已被手动关闭,这个值会返回False """
|
63
|
+
try:
|
64
|
+
self.title
|
65
|
+
return True
|
66
|
+
except NoSuchWindowException:
|
67
|
+
return False
|
68
|
+
|
69
|
+
|
70
|
+
def get_global_driver(_driver_store=[None]): # trick
|
71
|
+
""" 通过这个接口可以固定一个driver来使用 """
|
72
|
+
if _driver_store[0] is None:
|
73
|
+
_driver_store[0] = XlChrome()
|
74
|
+
if not _driver_store[0]: # 如果驱动没了,重新启动
|
75
|
+
_driver_store[0] = XlChrome()
|
76
|
+
return _driver_store[0]
|
pyxllib/ext/tk.py
CHANGED
@@ -1,173 +1,173 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
# @Author : 陈坤泽
|
4
|
-
# @Email : 877362867@qq.com
|
5
|
-
# @Date : 2018/07/24 19:42
|
6
|
-
|
7
|
-
"""
|
8
|
-
tkinter相关工具
|
9
|
-
"""
|
10
|
-
|
11
|
-
import tkinter as tk
|
12
|
-
|
13
|
-
from pyxllib.text.pupil import strwidth
|
14
|
-
|
15
|
-
|
16
|
-
def askquestion(title='code4101py', message='void', **options):
|
17
|
-
"""对tk.messagebox.askquestion的封装,用于消息提示
|
18
|
-
|
19
|
-
默认会弹出一个主窗口,这里关掉了主窗口
|
20
|
-
"""
|
21
|
-
from tkinter import messagebox
|
22
|
-
|
23
|
-
win = tk.Tk()
|
24
|
-
win.withdraw() # 不显示主窗口
|
25
|
-
|
26
|
-
# 弹出信息提示窗口,根据选择会返回yes、no
|
27
|
-
return tk.messagebox.askquestion(title, message, **options)
|
28
|
-
|
29
|
-
|
30
|
-
def askstring(title='code4101py', prompt='void', **kwargs):
|
31
|
-
""" 类似askquestion
|
32
|
-
"""
|
33
|
-
from tkinter import simpledialog, messagebox
|
34
|
-
|
35
|
-
# 不显示主窗口
|
36
|
-
win = tk.Tk()
|
37
|
-
win.withdraw()
|
38
|
-
|
39
|
-
# 如果提示内容太短,要增加空格,使得标题的显示长度足够
|
40
|
-
# tk的askstring默认最短有11个汉字多的长度
|
41
|
-
# 标题非文本内容已经占掉大概13个汉字的宽度
|
42
|
-
# 根据以上规律可推导出下述宽度控制算法
|
43
|
-
len1 = strwidth(title) * 2 + 26
|
44
|
-
len2 = strwidth(prompt)
|
45
|
-
if len2 < len1:
|
46
|
-
prompt += ' ' * (len1 - len2)
|
47
|
-
# 显示窗口
|
48
|
-
s = tk.simpledialog.askstring(title, prompt, **kwargs)
|
49
|
-
return s
|
50
|
-
|
51
|
-
|
52
|
-
def tk_init(title='tk', geometry='300x200'):
|
53
|
-
"""主窗口初始化"""
|
54
|
-
from tkinter import Tk
|
55
|
-
|
56
|
-
tk = Tk()
|
57
|
-
tk.title(title)
|
58
|
-
tk.geometry(geometry)
|
59
|
-
|
60
|
-
# 可以设置字体
|
61
|
-
# tk.option_add('*font', ('verdana', 12, 'bold'))
|
62
|
-
return tk
|
63
|
-
|
64
|
-
|
65
|
-
class AskStringByList:
|
66
|
-
"""使用举例:
|
67
|
-
ob = AskStringByList(['选项1', '选项2'], title='AskStringByList')
|
68
|
-
print(ob.value.get())
|
69
|
-
"""
|
70
|
-
|
71
|
-
def __init__(self, ls=tuple(range(3)), **kwargs):
|
72
|
-
"""
|
73
|
-
:param ls:
|
74
|
-
:param kwargs:
|
75
|
-
title: 设置主窗口名
|
76
|
-
geometry: 设置主窗口大小,例如'300x200'
|
77
|
-
"""
|
78
|
-
from tkinter import Frame
|
79
|
-
from tkinter.constants import YES, BOTH
|
80
|
-
|
81
|
-
self.ls = ls
|
82
|
-
self.kwargs = kwargs
|
83
|
-
|
84
|
-
self.tk = self.tk_init()
|
85
|
-
self.frame = Frame()
|
86
|
-
self.value = None
|
87
|
-
self.entry = None
|
88
|
-
self.listbox = None
|
89
|
-
self.frame_init()
|
90
|
-
|
91
|
-
self.frame.pack(fill=BOTH, expand=YES)
|
92
|
-
self.tk.mainloop()
|
93
|
-
|
94
|
-
def tk_init(self):
|
95
|
-
# 1 设置基本属性
|
96
|
-
from tkinter import Tk
|
97
|
-
tk = Tk()
|
98
|
-
|
99
|
-
# 设置标题
|
100
|
-
if 'title' not in self.kwargs:
|
101
|
-
self.kwargs['title'] = 'AskStringByList'
|
102
|
-
tk.title(self.kwargs['title'])
|
103
|
-
|
104
|
-
# 设置窗口大小
|
105
|
-
if 'geometry' not in self.kwargs:
|
106
|
-
self.kwargs['geometry'] = '300x400'
|
107
|
-
tk.geometry(self.kwargs['geometry'])
|
108
|
-
|
109
|
-
# 禁用窗口调整大小
|
110
|
-
tk.resizable(False, False)
|
111
|
-
|
112
|
-
# 2 绑定快捷键
|
113
|
-
tk.bind("<Return>", self.enter) # 回车键跟 enter() 绑定
|
114
|
-
tk.bind("<Escape>", self.esc) # Esc键跟 esc() 绑定
|
115
|
-
|
116
|
-
return tk
|
117
|
-
|
118
|
-
def enter(self, ev=None):
|
119
|
-
"""按下确认键后的功能"""
|
120
|
-
self.tk.quit()
|
121
|
-
# self.result = xxx
|
122
|
-
|
123
|
-
def esc(self, ev=None):
|
124
|
-
"""按下esc键后的反应"""
|
125
|
-
self.tk.quit()
|
126
|
-
self.value.set('')
|
127
|
-
|
128
|
-
def onselect(self, ev):
|
129
|
-
d = self.listbox.curselection()
|
130
|
-
d = d[0] if d else 0 # 如果没有选择,默认选第0个
|
131
|
-
self.value.set(self.ls[d])
|
132
|
-
|
133
|
-
def listbox_init(self):
|
134
|
-
from tkinter import Listbox, Scrollbar
|
135
|
-
from tkinter.constants import END
|
136
|
-
|
137
|
-
# 1 创建listbox
|
138
|
-
listbox = Listbox(self.frame, width=35)
|
139
|
-
for t in self.ls:
|
140
|
-
listbox.insert(END, t)
|
141
|
-
listbox.place(relx=0.1, rely=0.3)
|
142
|
-
listbox.bind('<<ListboxSelect>>', self.onselect)
|
143
|
-
|
144
|
-
# 2 为列表添加滚动条
|
145
|
-
s = Scrollbar(listbox)
|
146
|
-
s.place(relx=0.94, relheight=1)
|
147
|
-
s.config(command=listbox.yview)
|
148
|
-
listbox.config(yscrollcommand=s.set)
|
149
|
-
|
150
|
-
return listbox
|
151
|
-
|
152
|
-
def frame_init(self):
|
153
|
-
"""主要是设置布局"""
|
154
|
-
from tkinter import Button, Label, Entry, StringVar
|
155
|
-
|
156
|
-
fm = self.frame
|
157
|
-
Label(fm, text='请选择一个值或输入自定义新值:').place(relx=0.1, rely=0.1)
|
158
|
-
|
159
|
-
self.value = StringVar()
|
160
|
-
self.entry = Entry(fm, textvariable=self.value, width=35).place(relx=0.1, rely=0.2)
|
161
|
-
self.listbox = self.listbox_init()
|
162
|
-
|
163
|
-
# 默认第1个为初始值
|
164
|
-
self.listbox.select_set(0)
|
165
|
-
self.value.set(self.ls[0])
|
166
|
-
|
167
|
-
Button(fm, text='确认(Enter)', command=self.enter, width=12).place(relx=0.15, rely=0.85)
|
168
|
-
Button(fm, text='取消(Esc)', command=self.esc, width=12).place(relx=0.5, rely=0.85)
|
169
|
-
|
170
|
-
|
171
|
-
if __name__ == '__main__':
|
172
|
-
ob = AskStringByList()
|
173
|
-
print(ob.value.get())
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Author : 陈坤泽
|
4
|
+
# @Email : 877362867@qq.com
|
5
|
+
# @Date : 2018/07/24 19:42
|
6
|
+
|
7
|
+
"""
|
8
|
+
tkinter相关工具
|
9
|
+
"""
|
10
|
+
|
11
|
+
import tkinter as tk
|
12
|
+
|
13
|
+
from pyxllib.text.pupil import strwidth
|
14
|
+
|
15
|
+
|
16
|
+
def askquestion(title='code4101py', message='void', **options):
|
17
|
+
"""对tk.messagebox.askquestion的封装,用于消息提示
|
18
|
+
|
19
|
+
默认会弹出一个主窗口,这里关掉了主窗口
|
20
|
+
"""
|
21
|
+
from tkinter import messagebox
|
22
|
+
|
23
|
+
win = tk.Tk()
|
24
|
+
win.withdraw() # 不显示主窗口
|
25
|
+
|
26
|
+
# 弹出信息提示窗口,根据选择会返回yes、no
|
27
|
+
return tk.messagebox.askquestion(title, message, **options)
|
28
|
+
|
29
|
+
|
30
|
+
def askstring(title='code4101py', prompt='void', **kwargs):
|
31
|
+
""" 类似askquestion
|
32
|
+
"""
|
33
|
+
from tkinter import simpledialog, messagebox
|
34
|
+
|
35
|
+
# 不显示主窗口
|
36
|
+
win = tk.Tk()
|
37
|
+
win.withdraw()
|
38
|
+
|
39
|
+
# 如果提示内容太短,要增加空格,使得标题的显示长度足够
|
40
|
+
# tk的askstring默认最短有11个汉字多的长度
|
41
|
+
# 标题非文本内容已经占掉大概13个汉字的宽度
|
42
|
+
# 根据以上规律可推导出下述宽度控制算法
|
43
|
+
len1 = strwidth(title) * 2 + 26
|
44
|
+
len2 = strwidth(prompt)
|
45
|
+
if len2 < len1:
|
46
|
+
prompt += ' ' * (len1 - len2)
|
47
|
+
# 显示窗口
|
48
|
+
s = tk.simpledialog.askstring(title, prompt, **kwargs)
|
49
|
+
return s
|
50
|
+
|
51
|
+
|
52
|
+
def tk_init(title='tk', geometry='300x200'):
|
53
|
+
"""主窗口初始化"""
|
54
|
+
from tkinter import Tk
|
55
|
+
|
56
|
+
tk = Tk()
|
57
|
+
tk.title(title)
|
58
|
+
tk.geometry(geometry)
|
59
|
+
|
60
|
+
# 可以设置字体
|
61
|
+
# tk.option_add('*font', ('verdana', 12, 'bold'))
|
62
|
+
return tk
|
63
|
+
|
64
|
+
|
65
|
+
class AskStringByList:
|
66
|
+
"""使用举例:
|
67
|
+
ob = AskStringByList(['选项1', '选项2'], title='AskStringByList')
|
68
|
+
print(ob.value.get())
|
69
|
+
"""
|
70
|
+
|
71
|
+
def __init__(self, ls=tuple(range(3)), **kwargs):
|
72
|
+
"""
|
73
|
+
:param ls:
|
74
|
+
:param kwargs:
|
75
|
+
title: 设置主窗口名
|
76
|
+
geometry: 设置主窗口大小,例如'300x200'
|
77
|
+
"""
|
78
|
+
from tkinter import Frame
|
79
|
+
from tkinter.constants import YES, BOTH
|
80
|
+
|
81
|
+
self.ls = ls
|
82
|
+
self.kwargs = kwargs
|
83
|
+
|
84
|
+
self.tk = self.tk_init()
|
85
|
+
self.frame = Frame()
|
86
|
+
self.value = None
|
87
|
+
self.entry = None
|
88
|
+
self.listbox = None
|
89
|
+
self.frame_init()
|
90
|
+
|
91
|
+
self.frame.pack(fill=BOTH, expand=YES)
|
92
|
+
self.tk.mainloop()
|
93
|
+
|
94
|
+
def tk_init(self):
|
95
|
+
# 1 设置基本属性
|
96
|
+
from tkinter import Tk
|
97
|
+
tk = Tk()
|
98
|
+
|
99
|
+
# 设置标题
|
100
|
+
if 'title' not in self.kwargs:
|
101
|
+
self.kwargs['title'] = 'AskStringByList'
|
102
|
+
tk.title(self.kwargs['title'])
|
103
|
+
|
104
|
+
# 设置窗口大小
|
105
|
+
if 'geometry' not in self.kwargs:
|
106
|
+
self.kwargs['geometry'] = '300x400'
|
107
|
+
tk.geometry(self.kwargs['geometry'])
|
108
|
+
|
109
|
+
# 禁用窗口调整大小
|
110
|
+
tk.resizable(False, False)
|
111
|
+
|
112
|
+
# 2 绑定快捷键
|
113
|
+
tk.bind("<Return>", self.enter) # 回车键跟 enter() 绑定
|
114
|
+
tk.bind("<Escape>", self.esc) # Esc键跟 esc() 绑定
|
115
|
+
|
116
|
+
return tk
|
117
|
+
|
118
|
+
def enter(self, ev=None):
|
119
|
+
"""按下确认键后的功能"""
|
120
|
+
self.tk.quit()
|
121
|
+
# self.result = xxx
|
122
|
+
|
123
|
+
def esc(self, ev=None):
|
124
|
+
"""按下esc键后的反应"""
|
125
|
+
self.tk.quit()
|
126
|
+
self.value.set('')
|
127
|
+
|
128
|
+
def onselect(self, ev):
|
129
|
+
d = self.listbox.curselection()
|
130
|
+
d = d[0] if d else 0 # 如果没有选择,默认选第0个
|
131
|
+
self.value.set(self.ls[d])
|
132
|
+
|
133
|
+
def listbox_init(self):
|
134
|
+
from tkinter import Listbox, Scrollbar
|
135
|
+
from tkinter.constants import END
|
136
|
+
|
137
|
+
# 1 创建listbox
|
138
|
+
listbox = Listbox(self.frame, width=35)
|
139
|
+
for t in self.ls:
|
140
|
+
listbox.insert(END, t)
|
141
|
+
listbox.place(relx=0.1, rely=0.3)
|
142
|
+
listbox.bind('<<ListboxSelect>>', self.onselect)
|
143
|
+
|
144
|
+
# 2 为列表添加滚动条
|
145
|
+
s = Scrollbar(listbox)
|
146
|
+
s.place(relx=0.94, relheight=1)
|
147
|
+
s.config(command=listbox.yview)
|
148
|
+
listbox.config(yscrollcommand=s.set)
|
149
|
+
|
150
|
+
return listbox
|
151
|
+
|
152
|
+
def frame_init(self):
|
153
|
+
"""主要是设置布局"""
|
154
|
+
from tkinter import Button, Label, Entry, StringVar
|
155
|
+
|
156
|
+
fm = self.frame
|
157
|
+
Label(fm, text='请选择一个值或输入自定义新值:').place(relx=0.1, rely=0.1)
|
158
|
+
|
159
|
+
self.value = StringVar()
|
160
|
+
self.entry = Entry(fm, textvariable=self.value, width=35).place(relx=0.1, rely=0.2)
|
161
|
+
self.listbox = self.listbox_init()
|
162
|
+
|
163
|
+
# 默认第1个为初始值
|
164
|
+
self.listbox.select_set(0)
|
165
|
+
self.value.set(self.ls[0])
|
166
|
+
|
167
|
+
Button(fm, text='确认(Enter)', command=self.enter, width=12).place(relx=0.15, rely=0.85)
|
168
|
+
Button(fm, text='取消(Esc)', command=self.esc, width=12).place(relx=0.5, rely=0.85)
|
169
|
+
|
170
|
+
|
171
|
+
if __name__ == '__main__':
|
172
|
+
ob = AskStringByList()
|
173
|
+
print(ob.value.get())
|