python - 扩展布局添加的输入框的 PySimpleGui Rick Click Menu 剪贴板
问题描述
TL; DR:我基本上是想弄清楚如何从 PySimpleGui Github 合并这两个示例代码:https ://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Extend.py和 https:// github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py其中已动态创建传递给剪贴板函数的元素键...
使用 PySimpleGui 的文档以及关于 stackoverflow 和 Github 演示的大量信息,我制作了一个“简单”的 gui,可以添加和删除输入字段,并且我已经为这方面的所有内容进行了排序(即使用添加元素到 GUI layout_extend,使用 .hide_row() 删除元素并保留已删除值的列表等...
就像 layout_extend 演示一样,我正在使用 Frame,并使用迭代器向其中添加 GUI 元素以确保创建唯一的“键”。
##CODE SNIPPET AS MOST OF IT IS PRETTY MUCH THE SAME AS THE EXAMPLE DEMO CODE WITH MINOR CHANGES
right_click_menu = ['', ['Copy', 'Paste', 'Select All', 'Cut']]
def do_clipboard_operation(event, window, element):
#Same as Demo Code Here No Point Copying!
...
...
if event in right_click_menu[1]:
do_clipboard_operation(event, program_window, element)
if event == '-ADDPATH-':
program_window.extend_layout(program_window['-FRAME1-'], [[sg.Text('PATH:'),sg.Input(key=f'-PATH{i}-', rick_click_menu=right_click_menu), sg.FolderBrowse(initial_folder="/base/path", key=f'-BROWSEPATH{i}-'), sg.Button('Remove Path', key=f'-REMOVEPATH{i}-')]])
i += 1
...
...
当用户看到一个输入字段时,他们希望在其中放入一长串文本(在我的情况下为文件夹路径),因此需要“右键单击上下文菜单”,因此我想考虑添加它。
我的问题是 Multi-line Rick Click Menu Clipboard 演示需要将触发元素键传递给函数(然后用于向其中添加/删除文本),但是因为我为我需要的元素“动态生成”了键名在能够通过之前找出哪个元素键激活了右键菜单,我只是不知道该怎么做.....
我写的代码和 Layout_extend 演示基本相同.....
我很欣赏 PySimpleGui,尽管它很棒,但它可能并不是处理动态 GUI 的最佳工具,但由于我一直在为 OO 编程而苦苦挣扎,这几乎是我能够构建功能性 Python GUI 的唯一方法日期....
如果在现阶段无法做到这一点,那没关系,但至少我问过(当我不可避免地有人在使用它时说“我不能右键单击它真的很烦人”时,这让我感觉更好)!
一如既往地提前感谢!
欧文。
编辑:: 添加代码(必须删除对特定细节的一些引用 - 根路径和其他此类信息,将 '<' '>' 放置在数据存在位置的占位符周围 - 但代码是相同的:
#!/bin/python3
import PySimpleGUI as sg
import os.path
from getpass import getuser
from string import ascii_letters, digits
from random import choice as rchoice
SPLASH_IMAGE_PATH=r'<AN IMAGE FILE LOCATION>'
OUT_PATH='./'
DISPLAY_SPLASH_MS = 1500
REMOVE_LIST=[]
VERSION_NUM='0.3.0'
splash_theme = {'BACKGROUND': '#ffcc00',
'TEXT': '#000000',
'INPUT': '#ffffff',
'TEXT_INPUT': '#ffffff',
'SCROLL': '#ffffff',
'BUTTON': ('white', '#000000'),
'PROGRESS': ('#ffffff', '#ffffff'),
'BORDER': 0,
'SLIDER_DEPTH': 0,
'PROGRESS_DEPTH': 0
}
right_click_menu = ['', ['Copy','Paste','Select All','Cut']]
def do_clipboard_operation(event, window, element):
print(event)
print(window)
print(element)
##Random string generator: https://www.stackoverflow.com/questions/2257441/random-sting-generation-with-upper-case-letters-and-digits (Ignacio Vazquez-Abrams answer)
def random_string_gen(size=8, chars=ascii_letters + digits):
return ''.join(rchoice(chars) for _ in range(size))
def main():
sg.theme_add_new('SplashScreen', splash_theme)
sg.theme('SplashScreen')
splash_window= sg.Window('Uploader', [[sg.Image(SPLASH_IMAGE_PATH)], [sg.Text('Uploader', font=("any",20))], [sg.Text(f'Version: {VERSION_NUM}', font=('any',12))]], element_justification='c', no_titlebar=True, keep_on_top=True).read(timeout=DISPLAY_SPLASH_MS, close=True)
sg.theme('DarkAmber')
layout = [ [sg.Text('Please Enter FULL Paths. Use The Browse Button To Navigate, Or Copy Path Into Field.')],
[sg.Text('Use The "Add Path" Button To Add More Rows, And The "Remove Path" Button To Remove A Row.')],
[sg.Text('When Finished, Press The "Upload" Button - This Will Take Time To Process.')],
[sg.Frame('Paths:', [[sg.Text('PATH:'), sg.Input(key='-PATH0-', right_click_menu=right_click_menu), sg.FolderBrowse(initial_folder="<ROOT PATH>", key='-BROWSEPATH0-' ), sg.Button('Remove Path', key='-REMOVEPATH0-')]], key='-FRAME1-')],
[sg.OK('Upload',key='-RUN-'), sg.Button('Add Additional Path', key='-ADDPATH-'), sg.Cancel('Exit', key='-EXIT-')]
]
program_window = sg.Window('Uploader', layout)
i = 1
num_rows=1
user=str(getuser())
while True:
event, values = program_window.read()
if event == sg.WIN_CLOSED or event == '-EXIT-':
break
if event in right_click_menu[1]:
print(values)
# do_clipboard_operation(event, program_window, element)
if event == '-ADDPATH-':
##Add new row to output window. uses f' ' string formatting to use the i iterator to create unique keys
program_window.extend_layout(program_window['-FRAME1-'], [[sg.Text('PATH:'), sg.Input(key=f'-PATH{i}-', right_click_menu=right_click_menu), sg.FolderBrowse(initial_folder="<ROOT PATH>", key=f'-BROWSEPATH{i}-' ), sg.Button('Remove Path', key=f'-REMOVEPATH{i}-')]])
i += 1
num_rows += 1
if event == '-RUN-':
##Iterate over values and remove duplicates (both the text field and the browse button can be populated with the same data so duplicates cannot be avoided
##Remove blank values (can occur when path is pasted into text field and browse button not used, and remove any paths that occur in the remove_list. generated when lines are removed
##Remove items that appear in REMOVE_LIST (created when removing lines)
##Output to a new out_list as items in value cannot be changed
##Validate User input to: ensure no <AVOID PATH> paths, no invalid paths, at least one path is submitted, and path submitted actually contains an <SPECIFIC FILES>... Show popup errors if any found and allow user to remove / alter offending paths.
##If all is OK generate a random string with the username appended and write all valid paths into a temp file with that random name. This is for back-end program to run.
out_list = []
error_list = []
avoid_path_error=False
invalid_path=False
for key, value in values.items():
if value not in out_list and not value == '' and not value in REMOVE_LIST:
if '<AVOID PATH>' in value:
avoid_path_error=True
sg.popup('One Or More Of Your Paths Is Located In The <AVOID PATH> And Cannot Be Used As An Input!\n\nPlease Remove The Offending Path.', title='<AVOID PATH> FOUND', keep_on_top=True, custom_text=('Sorry'), button_color=('white', 'red'))
break
elif not os.path.isdir(value):
invalid_path=True
sg.popup(f'The Following Invalid Path Has Been Entered And Does Not Seem To Exist / Is Unreadable:\n\n{value}', title='INVALID PATH ENTERED', keep_on_top=True, custom_text=('Oops!'), button_color=('white', 'red'))
break
else:
out_list.append(value)
if not avoid_path_error == True and not invalid_path == True:
if not out_list:
sg.popup('You Have Not Added Any Paths!!! Please Try Again', title='NO PATH ENTERED', keep_on_top=True, custom_text=('Oops!'), button_color=('white', 'red'))
else:
for path in out_list:
for files in os.listdir(path):
if '<SPECIFIC FILE>' in files.lower():
break
else:
error_list.append(path)
if error_list:
error_list_string = '\n'.join(error_list)
sg.popup(f'The Following Path(s) Do NOT Contain <SPECIFIC FILE>...\nPlease ONLY Add Full Paths:\n\n{error_list_string}', title='NO <SPECIFIC PATH> FOUND', keep_on_top=True, custom_text=('Sorry!'), button_color=('white', 'red'))
else:
print(random_string_gen() + '.' + user)
break
if '-REMOVEPATH' in event:
##Remove Line from window. values Dict cannot be altered, so need to generate a new list with the values of the data held in the value dict: -PATHx- and -BROWSEPATHx-
##Where x is the unique iterator number used to ensure unique keys. The Event also uses the same unique iterator key: -REMOVEPATHx- so replacing -REMOVEPATH with -PATH and -BROWSEPATH
##generates the keys we need. call the hide_row() function to remove row from window, and append both -PATHx- and -BROWSEPATHx-.
folder_path=str(event).replace("-REMOVEPATH", "-PATH")
browse_path=str(event).replace("-REMOVEPATH", "-BROWSEPATH")
num_rows -= 1
if num_rows == 0:
program_window[event].hide_row()
program_window.extend_layout(program_window['-FRAME1-'], [[sg.Text('PATH:'), sg.Input(key=f'-PATH{i}-', right_click_menu=right_click_menu), sg.FolderBrowse(initial_folder="<ROOT PATH>", key=f'-BROWSEPATH{i}-' ), sg.Button('Remove Path', key=f'-REMOVEPATH{i}-')]])
i += 1
num_rows = 1
else:
program_window[event].hide_row()
REMOVE_LIST.append(values[folder_path])
REMOVE_LIST.append(values[browse_path])
program_window.close()
if __name__ == "__main__":
main()
解决方案
推荐阅读
- javascript - 即使在fabricjs中未选择图像,如何默认显示自定义控件图标
- c# - 如何在 Visual Studio 中修复此错误?
- python - TensorFlow Keras 输出风格
- php - 如何在 Laravel 中查看我上传的 pdf 文件?
- c++ - 获取二维数组c ++中的所有数字对
- php - Wordpress - 如何使用散列密码验证用户输入密码
- spring - 使用 Elastic Search 和 MongoDB 创建 spring-boot 应用程序时出现 UnsatisfiedDependencyException,使用 Jhipster 生成
- android - 从 kotlin 中的干净架构定义用例的惯用方式
- c++ - 特征稀疏向量:找到最大系数
- reporting-services - 在 SSRS 预先定义时间的日期