Я работаю над графическим интерфейсом, используя wxPython. Этот графический интерфейс должен динамически запрашивать у пользователя несколько наборов входов в одном окне, обновляя окно с помощью нового набора входов после нажатия кнопки «ok».wxPython: приостановить основной скрипт и ждать нажатия кнопки
Для этого у меня есть цикл for, который вызывает функцию, которая запрашивает элементы управления ввода в окне. Я попытался использовать класс threading.Event
, позволяя сценарию дождаться нажатия кнопки, но сбой python.
Здесь ниже представлена интересующая часть кода.
# Iterate through parameters
self.cv = threading.Event()
for key in parameters:
self.input_sizer = [None]*len(parameters[key])
self.cv.clear()
self.make_widgets(key, parameters[key])
self.cv.wait()
# Panel final settings
self.panel.SetSizer(self.main_sizer)
self.main_sizer.SetSizeHints(self)
def make_widgets(self, request, parameters):
# Function for widget prompting on the panel
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.controls = {"request": wx.StaticText(self.panel, label="Please type the new alias' " + request),
"txt": [None]*len(parameters),
"tc": [None]*len(parameters)}
self.main_sizer.Add(self.controls["request"], 1, wx.ALL, 10)
for i in range(len(parameters)):
self.input_sizer[i] = wx.BoxSizer(wx.HORIZONTAL)
self.main_sizer.Add(self.input_sizer[i], 1, wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10)
# Text
self.controls['txt'][i] = wx.StaticText(self.panel, label=parameters[i])
self.input_sizer[i].Add(self.controls["txt"][i], 0, wx.ALIGN_CENTER | wx.LEFT, 10)
# Input
self.controls['tc'][i] = wx.TextCtrl(self.panel)
self.input_sizer[i].Add(self.controls["tc"][i], 0, wx.ALIGN_CENTER)
# Ok button
self.button_ok = wx.Button(self.panel, label="Ok")
self.main_sizer.Add(self.button_ok, 1, wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10)
self.button_ok.Bind(wx.EVT_BUTTON, self.carry_on)
def carry_on(self, event):
self.cv.set()
У кого-нибудь есть идеи?
Спасибо, здесь ниже приведен полный код.
import wx
from collections import OrderedDict
import threading
############################################################################
class AddMainName(wx.Frame):
# Class definition for main Name addition
def __init__(self, parent, title):
# Constructor
super().__init__(parent, title=title)
# Run the name addition
self.set_alias_name()
self.Centre()
self.Show()
def set_alias_name(self):
# Function for definition of alias name
# Panel
self.panel = wx.Panel(self)
# Lists of parameters to be typed
parameters = OrderedDict([("name parts", [
"Prefix", "Measurement", "Direction", "Item", "Location", "Descriptor", "Frame", "RTorigin"
]),
("SI units", [
"A", "cd", "K", "kg", "m", "mol", "Offset", "rad", "s", "ScaleFactor"
]),
("normal display unit", [
"A", "cd", "K", "kg", "m", "mol", "Offset", "rad", "s", "ScaleFactor"
]),
("other parameters", [
"Meaning", "Orientation Convention", "Contact Person", "Note",
])])
# Iterate through parameters
self.cv = threading.Event()
for key in parameters:
self.input_sizer = [None]*len(parameters[key])
self.cv.clear()
self.make_widgets(key, parameters[key])
self.cv.wait()
# Panel final settings
self.panel.SetSizer(self.main_sizer)
self.main_sizer.SetSizeHints(self)
def make_widgets(self, request, parameters):
# Function for widget prompting on the panel
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.controls = {"request": wx.StaticText(self.panel, label="Please type the new alias' " + request),
"txt": [None]*len(parameters),
"tc": [None]*len(parameters)}
self.main_sizer.Add(self.controls["request"], 1, wx.ALL, 10)
for i in range(len(parameters)):
self.input_sizer[i] = wx.BoxSizer(wx.HORIZONTAL)
self.main_sizer.Add(self.input_sizer[i], 1, wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10)
# Text
self.controls['txt'][i] = wx.StaticText(self.panel, label=parameters[i])
self.input_sizer[i].Add(self.controls["txt"][i], 0, wx.ALIGN_CENTER | wx.LEFT, 10)
# Input
self.controls['tc'][i] = wx.TextCtrl(self.panel)
self.input_sizer[i].Add(self.controls["tc"][i], 0, wx.ALIGN_CENTER)
# Ok button
self.button_ok = wx.Button(self.panel, label="Ok")
self.main_sizer.Add(self.button_ok, 1, wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10)
self.button_ok.Bind(wx.EVT_BUTTON, self.carry_on)
def carry_on(self, event):
self.cv.set()
############################################################################
class AddCommonName(wx.Frame):
# Class definition for common name addition
def __init__(self, parent, title):
# Constructor
super().__init__(parent, title=title,
size=(400, 150))
# Run the name addition
self.set_alias()
self.Centre()
self.Show()
def set_alias(self):
panel = wx.Panel(self)
sizer = wx.GridBagSizer(5, 5)
text1 = wx.StaticText(panel, label="Please type the new alias name.")
sizer.Add(text1, pos=(0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM,
border=15)
panel.SetSizer(sizer)
############################################################################
class AliasGUI(wx.Frame):
def __init__(self, parent, title):
# Constructor
super().__init__(parent, title=title)
# Run first dialog of the GUI
self.begin()
self.Centre()
self.Show()
def begin(self):
# Panel initial settings
panel_start = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
# Alias type selection
text_start = wx.StaticText(panel_start, label="Please select the type of the new alias.")
main_sizer.Add(text_start, 1, wx.ALL, 10)
# Buttons
buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(buttons_sizer, 1, wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10)
# Main name button
button_main_name = wx.Button(panel_start, label="Main Name")
buttons_sizer.Add(button_main_name, 0, wx.ALIGN_CENTER | wx.RIGHT, 10)
button_main_name.Bind(wx.EVT_BUTTON, self.main_name)
# Common name button
button_common_name = wx.Button(panel_start, label="Common Name")
buttons_sizer.Add(button_common_name, 0, wx.ALIGN_CENTER)
button_common_name.Bind(wx.EVT_BUTTON, self.common_name)
# Panel final settings
panel_start.SetSizer(main_sizer)
main_sizer.SetSizeHints(self)
@staticmethod
def main_name(event):
# Function for main name addition
frame = AddMainName(None, title="New Main Name")
frame.Centre()
frame.Show()
@staticmethod
def common_name(event):
# Function for common name addition
frame = AddCommonName(None, title="New Common Name")
frame.Centre()
frame.Show()
# GUI execution
if __name__ == '__main__':
app = wx.App()
AliasGUI(None, title="Aliases Management GUI")
app.MainLoop()
спасибо за ответ и прошу прощения за мой бедный язык. На самом деле сценарий ждет неопределенно долго и в определенный момент не отвечает, но он не падает. То, что я хочу, это разные окна, которые появляются один за другим, после нажатия кнопки «ok» (и текущее окно также должно закрываться). Я не знал, что настройка фрейма не запускается до тех пор, пока моя функция '__init__' не будет выполнена. Теперь я переместил цикл for в функцию 'main_name', чтобы создать новый кадр для каждого набора входов. Полагая также «ждать», сценарий все еще ждет бесконечно. – Francesco
Лично я бы использовал Modal Dialog, чтобы спросить у пользователя информацию, а не фрейм. Остальная часть скрипта ждет автоматически до тех пор, пока диалог не будет выполнен, и вы сможете получить информацию, которую вы хотите оттуда. – Lokla
Спасибо за ваше предложение. Дело в том, что я хотел бы использовать wxPython, так как набор запросов, запрошенных пользователю, весьма разнообразен. Сначала у меня должны быть окна с запросом на некоторые тексты, а затем на другие окна с списком прокрутки и другим текстом. Мне не удается найти решение для рекурсивного всплытия фреймов и их закрытия. Проблема заключается в том, что это делается внутри цикла 'for'. Таким образом, выполняется основной скрипт, который одновременно создает все кадры.В противном случае, если я буду использовать 'wait' в любой момент, я всегда ожидаю неограниченное время. – Francesco