停用 wxpython FilePickerCtrl

Deactivate wxpython FilePickerCtrl

有没有办法 activate/deactivate wxpython 小部件尤其是 FilePickerCtrl 小部件的可编辑性?

就我而言,我正在创建一个桌面应用程序,用户可以从中启动和停止服务器。在启动服务器之前,用户可以通过 FilePickerCtrl 小部件指定一个变量,该变量将从服务器使用。我想让 FilePickerCtrl 在服务器停止时可编辑,在服务器 运行ning 时不可编辑。

到目前为止,我已经尝试了 wxpython Validators 但没有成功。一些可重现的代码:

configuration.py(需要编辑excel路径)

global SERVER_CONF
SERVER_CONF = {
    'XE_EXCEL_PATH': '/absolute/path/to/excel.xlsx'
}

gui_main.py

import wx
from server_tab import Server


class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="")

        # Create a panel and notebook (tabs holder)
        p = wx.Panel(self)
        nb = wx.Notebook(p)

        # Create the tab windows
        tab1 = Server(nb)

        # Add the windows to tabs and name them.
        nb.AddPage(tab1, tab1.name)

        # Set noteboook in a sizer to create the layout
        sizer = wx.BoxSizer()
        sizer.Add(nb, 1, wx.EXPAND)
        p.SetSizer(sizer)


if __name__ == "__main__":
    app = wx.App()
    MainFrame().Show()
    app.MainLoop()

server.py

from flask import request
from flask import Flask

from configuration import SERVER_CONF



app = Flask(__name__)


@app.route('/', methods=['POST'])
def read_html_source():
    global SERVER_CONF
    print('HEREEE',SERVER_CONF['XE_EXCEL_PATH'])
    return ('', 200)


@app.route("/shutdown", methods=['GET'])
def shutdown():
    shutdown_func = request.environ.get('werkzeug.server.shutdown')
    if shutdown_func is None:
        raise RuntimeError('Not running werkzeug')
    shutdown_func()
    return ("Shutting down...", 200)


def main():
    app.run(debug=False, port=5001)

if __name__ == "__main__":
    main()

server_tab.py

import os
import requests
import threading
import wx

import server

from configuration import SERVER_CONF


# Define the tab content as classes:
class Server(wx.Panel):

    name = "Server"

    def __init__(self, parent):
        global SERVER_CONF
        self.is_server_active = False
        wx.Panel.__init__(self, parent)

        generic_sizer = wx.BoxSizer(wx.VERTICAL)

        title = wx.StaticText(self, 0, "The APE API server")
        generic_sizer.Add(title, 0, wx.ALL | wx.EXPAND, 5)
        
        file_sizer = wx.BoxSizer(wx.HORIZONTAL)
        excel_label = wx.StaticText(self, 0, "Excel ")
        file_sizer.Add(excel_label, 0, wx.ALL | wx.EXPAND, 5)
        self. excel_browser = wx.FilePickerCtrl(
            self,
            wildcard='*.xlsx',
            path=SERVER_CONF['XE_EXCEL_PATH'],
            validator=ServerValidator(self.is_server_active) 
        )
        file_sizer.Add(self.excel_browser, 0, wx.ALL , 5)
        generic_sizer.Add(file_sizer, 0, wx.ALL , 5)

        server_btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
        start_server_btn = wx.Button(self, label='Run Server')
        start_server_btn.Bind(wx.EVT_BUTTON, self.start_server)
        server_btn_sizer.Add(start_server_btn, 0, wx.ALL | wx.EXPAND, 5)
        stop_server_btn = wx.Button(self, label='Stop Server')
        stop_server_btn.Bind(wx.EVT_BUTTON, self.stop_server)
        server_btn_sizer.Add(stop_server_btn, 0, wx.ALL | wx.EXPAND, 5)

        generic_sizer.Add(server_btn_sizer, 0, wx.ALL | wx.EXPAND, 5)

        parent.SetSizer(generic_sizer)

    def start_server(self, entry):
        SERVER_CONF['XE_EXCEL_PATH'] = self.excel_browser.GetPath()
        self.is_server_active = True
        self.thread = threading.Thread(target=server.main)
        self.thread.start()

    def stop_server(self, entry):
        resp = requests.get('http://localhost:5001/shutdown')
        self.thread.join()
        print('Server was stoped')


class ServerValidator(wx.PyValidator):

    def __init__(self, is_server_active):
        wx.Validator.__init__(self)
        self.is_server_active = is_server_active

    def Clone(self):
        '''Required Validator method'''
        return ServerValidator(self.is_server_active)

    def Validate(self, win):
        window = self.GetWindow()
        print("Is running?", self.is_server_active)
        return not self.is_server_active

运行 使用 python gui_main.py 并使用 curl http://localhost:5001 -d POST 进行测试。如果您忘记从 GUI 停止服务器 运行 curl http://localhost:5001/shutdown

最简单的方法是启用禁用 控件。这通常适用于 wx 控件

import wx

class MainFrame(wx.Frame):
    """Create MainFrame class."""
    def __init__(self, *args, **kwargs):
        super().__init__(None, *args, **kwargs)
        self.size = (400, 1000)
        self.title_text = 'Wx App'

        self.panel = MainPanel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panel)
        self.SetSizer(sizer)
        self.Size = (600, 200)
        self.Center()
        self.Show()

    def on_disable(self, event):
    self.panel.excel_browser.Disable()

    def on_enable(self, event):
    self.panel.excel_browser.Enable()


class MainPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        self.excel_browser = wx.FilePickerCtrl(self)
        btn_disable = wx.Button(self, id=wx.ID_CANCEL)
        btn_disable.Bind(wx.EVT_BUTTON, parent.on_disable)
        btn_enable = wx.Button(self, id=wx.ID_OK)
        btn_enable.Bind(wx.EVT_BUTTON, parent.on_enable)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.excel_browser)
        sizer.Add(btn_disable)
        sizer.Add(btn_enable)
        self.SetSizer(sizer)

if __name__ == '__main__':
    wx_app = wx.App()
    MainFrame()
    wx_app.MainLoop()

只是为了证明 Psionman 关于启用和禁用 wx 小部件的观点,并且您还可以测试小部件是否IsEnabled,这可能是一个有用的工具,特别是对于切换控件。
这里,FilePickerCtrlLock 按钮在启用和禁用之间切换,按钮标签根据选择器是否 Enabled 切换。

import wx

class MainWindow(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title='Lockable File Selector', size=(400, 200))
        self.panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)

        self.s_box = wx.StaticBox(self.panel, -1, 'Please select the input file')
        s_sizer = wx.StaticBoxSizer(self.s_box, wx.VERTICAL)
        fp_box = wx.BoxSizer(wx.HORIZONTAL)

        self.fp_ctrl = wx.FilePickerCtrl(self.panel, wx.ID_ANY, message="Choose a file")
        self.fp_lock = wx.Button(self.panel, wx.ID_ANY, label="Lock")

        fp_box.Add(self.fp_ctrl, 1, wx.ALL | wx.CENTER | wx.EXPAND, 5)
        fp_box.Add(self.fp_lock, 0, wx.ALL | wx.CENTER, 5)
        s_sizer.Add(fp_box, 1, wx.ALL | wx.CENTER | wx.EXPAND, 10)
        vbox.Add(s_sizer, 0, wx.ALL | wx.CENTER | wx.EXPAND, 5)
        self.panel.SetSizer(vbox)

        self.fp_ctrl.Bind(wx.EVT_FILEPICKER_CHANGED, self.on_open_file)
        self.fp_lock.Bind(wx.EVT_BUTTON, self.on_lock)

        self.panel.Fit()
        self.fp_lock.Enable(False)
        self.Show()

    def on_open_file(self, event):
        path = self.fp_ctrl.GetPath()
        use_path, x = path.rsplit('/', 1)
        self.s_box.SetLabel(use_path)
        if path:
            self.fp_lock.Enable(True)

    def on_lock(self, event):
        if self.fp_ctrl.IsEnabled():
            self.fp_ctrl.Enable(False)
            self.fp_lock.SetLabel('Unlock')
        else:        
            self.fp_ctrl.Enable(True)
            self.fp_lock.SetLabel('Lock')        

if __name__ == '__main__':
    app = wx.App()
    frame = MainWindow()
    app.MainLoop()