# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ---------------------------------------------------------------------------- import wx from wx.lib.newevent import NewCommandEvent from .textctrl import TextCtrl numberfield_cmd_event, EVT_NUMBERFIELD = NewCommandEvent() numberfield_change_cmd_event, EVT_NUMBERFIELD_CHANGE = NewCommandEvent() def GetTextExtent(text): tdc = wx.WindowDC(wx.GetApp().GetTopWindow()) w, h = tdc.GetTextExtent(text) return w, h class NumberField(wx.Control): def __init__(self, parent, _id=wx.ID_ANY, label="", default_value=0,
""" Defines a small number of custom events, which are useful for the GUI. """ import wx from wx.lib.newevent import NewCommandEvent ID_COMPASS_OPEN = wx.NewId() class CompassOpenEvent(wx.PyCommandEvent): """ Event posted when a request has been made to "open" a object in the container. The source should always be ID_COMPASS_OPEN. The type of event is EVT_MENU, because wxPython doesn't like it if we use anything else. When binding handlers, make sure to explicitly specify the source ID (or check it in the callback) to avoid catching these events by mistake. """ def __init__(self, newnode, **kwds): """ Request that *newnode* be displayed by the GUI """ wx.PyCommandEvent.__init__(self, wx.EVT_MENU.typeId, ID_COMPASS_OPEN) self.node = newnode self.kwds = kwds # Hints that the selected item in the view may have changed. # Interested parties should inspect the view to figure out the new selection. ContainerSelectionEvent, EVT_CONTAINER_SELECTION = NewCommandEvent()
import time import wx from wx.lib.newevent import NewCommandEvent import pytweening as ptw from aic import ActiveImageControl from aic.util import make_padding rs_cmd_event, EVT_RS_CHANGE = NewCommandEvent() class RangeSlider(ActiveImageControl): def __init__(self, parent, bitmaps, is_vertical=False, is_inverted=False, max_pos=None, *args, **kwargs): """ An Image Control for presenting a range slider style It behaves as a double point native control slider; handle values are expressed as percentages :param bitmaps: wx.BitMap objects - iterable (bmp,bmp,[bmp]) (first bitmap will be the static background) (the second will be the handle/s (pointers), preferably smaller than the static bitmap) (if a third bitmap is passed, it will apply to the 'high' handle only) If the handle is large, you may need to compensate by adding padding to the slider :param is_vertical: Boolean - does the slider operate in a vertical orientation :param is_inverted: Boolean - does the slider operate contra to the co-ordinate system
# you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ---------------------------------------------------------------------------- import wx from wx.lib.newevent import NewCommandEvent button_cmd_event, EVT_BUTTON = NewCommandEvent() class Button(wx.Control): def __init__(self, parent, id=wx.ID_ANY, label="", bmp=None, center=True, flat=False, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.NO_BORDER, *args, **kwargs):
from wx.lib.newevent import NewCommandEvent import nuxhash.settings from nuxhash.devices.nvidia import enumerate_devices as nvidia_devices from nuxhash.download.downloads import make_miners from nuxhash.gui.about import AboutScreen from nuxhash.gui.benchmarks import BenchmarksScreen from nuxhash.gui.mining import MiningScreen from nuxhash.gui.settings import SettingsScreen PADDING_PX = 10 CONFIG_DIR = nuxhash.settings.DEFAULT_CONFIGDIR ICON_PATH = Path(os.path.dirname(__file__))/'icons'/'nuxhash.svg' PubSubSendEvent, EVT_PUBSUB = NewCommandEvent() class MainWindow(wx.Frame): def __init__(self, parent, *args, **kwargs): wx.Frame.__init__(self, parent, *args, **kwargs) self.SetIcon(wx.Icon(wx.IconLocation(str(ICON_PATH)))) self.SetSizeHints(minW=500, minH=500) self._Devices = self._ProbeDevices() self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(EVT_PUBSUB, self.OnPubSend) # Create notebook and its pages. notebook = wx.Notebook(self) notebook.AddPage(
import wx import wx.dataview from wx.lib.newevent import NewCommandEvent from wx.lib.pubsub import pub from wx.lib.scrolledpanel import ScrolledPanel from nuxhash import utils from nuxhash.devices.nvidia import NvidiaDevice from nuxhash.gui import main from nuxhash.miners import all_miners from nuxhash.settings import DEFAULT_SETTINGS BENCHMARK_SECS = 60 InputSpeedsEvent, EVT_SPEEDS = NewCommandEvent() class BenchmarksScreen(wx.Panel): def __init__(self, parent, *args, devices=[], **kwargs): wx.Panel.__init__(self, parent, *args, **kwargs) self._Devices = devices self._Settings = self._Benchmarks = None self._Miners = [miner(main.CONFIG_DIR) for miner in all_miners] # dict of (device, algorithm) -> Item self._Items = {} self._Thread = None pub.subscribe(self._OnSettings, 'data.settings') pub.subscribe(self._OnBenchmarks, 'data.benchmarks')
import wx import wx.grid from wx.lib.newevent import NewCommandEvent import os import logging log = logging.getLogger(__name__) from ..frame import NodeFrame from .plot import LinePlotFrame, ContourPlotFrame # Indicates that the slicing selection may have changed. # These events are emitted by the SlicerPanel. ArraySlicedEvent, EVT_ARRAY_SLICED = NewCommandEvent() # Menu and button IDs ID_VIS_MENU_PLOT = wx.NewId() class GeoSurfaceFrame(NodeFrame): """ Top-level frame displaying objects of type compass_model.Array. From top to bottom, has: 1. Toolbar (see ArrayFrame.init_toolbar) 2. SlicerPanel, with controls for changing what's displayed. 3. An ArrayGrid, which displays the data in a spreadsheet-like view. """
class RolePanel(wx.Panel): AddRoleEvent, EVT_ADD_ROLE = NewCommandEvent() RemoveRoleEvent, EVT_REMOVE_ROLE = NewCommandEvent() def __init__(self, *args, **kwargs): super(RolePanel, self).__init__(*args, **kwargs) sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(sizer) roles_label = wx.StaticText(self, label="User Roles") font = roles_label.GetFont() font.MakeBold() roles_label.SetFont(font) self.given_name_label = wx.StaticText(self, label="") sizer.AddSpacer(8, -1) label_sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(label_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8) label_sizer.Add(roles_label) label_sizer.AddStretchSpacer(1) label_sizer.Add(self.given_name_label) self.role_list = wx.ListBox(self, size=(300, -1), style=wx.LB_SINGLE) self.role_list.Bind(wx.EVT_LISTBOX, self.on_listbox_role_list) self.role_combo = wx.ComboBox(self) self.role_combo.Bind(wx.EVT_COMBOBOX, self.on_role_combo) self.set_roles_list(role_combo_list) self.add_btn = wx.Button(self, -1, "Add") self.add_btn.Bind(wx.EVT_UPDATE_UI, self.on_update_add_btn) self.add_btn.Bind(wx.EVT_BUTTON, self.on_add) self.remove_btn = wx.Button(self, -1, "Remove") self.remove_btn.Bind(wx.EVT_UPDATE_UI, self.on_update_remove_btn) self.remove_btn.Bind(wx.EVT_BUTTON, self.on_remove) sizer.AddSpacer(8, -1) sizer.Add(self.role_list, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 8) sizer.AddSpacer(8, -1) hsizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(hsizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8) combo_sizer = wx.BoxSizer(wx.VERTICAL) hsizer.Add(combo_sizer, 1, wx.EXPAND) combo_sizer.Add(self.role_combo, 0, wx.EXPAND) hsizer.Add(self.add_btn, 0, wx.LEFT, 8) hsizer.Add(self.remove_btn, 0, wx.LEFT, 8) sizer.AddSpacer(8, -1) self.Layout() self.user = None self.user_roles = None self.role_selected = ROLE_NONE_SELECTED self.Bind(wx.EVT_UPDATE_UI, self.on_update_panel, self) def on_update_panel(self, event): event.Enable(isinstance(self.user_roles, UserRoleVo)) def on_update_add_btn(self, event): event.Enable(self.role_combo.GetSelection()) def on_update_remove_btn(self, event): event.Enable(self.role_list.GetSelection() > -1) def on_role_combo(self, event): self.role_selected = event.ClientData self.role_list.SetSelection(-1) def on_listbox_role_list(self, event): self.role_selected = event.ClientData self.role_combo.SetSelection(0) def on_add(self, event): evt = self.AddRoleEvent(self.Id) wx.PostEvent(self, evt) self.role_combo.SetSelection(0) event.Skip() def on_remove(self, event): evt = self.RemoveRoleEvent(self.Id) wx.PostEvent(self, evt) self.role_list.SetSelection(-1) event.Skip() def set_user(self, user_vo=None): if user_vo: self.user = user_vo self.populate_from_user() else: self.user = UserVo() self.populate_from_user() self.user = None def populate_from_user(self): self.given_name_label.SetLabel(self.user.given_name) self.Layout() def set_user_roles(self, user_roles_vo=None): if user_roles_vo: self.user_roles = user_roles_vo.get_copy() self.populate_from_user_roles() else: self.user_roles = UserRoleVo() self.populate_from_user_roles() self.user_roles = None def populate_from_user_roles(self): self.role_list.Clear() for role in self.user_roles.roles: self.role_list.Append(role.value, role) def set_roles_list(self, role_list_enum): self.role_combo.Clear() for role in role_list_enum: self.role_combo.Append(role.value, role) self.role_combo.SetSelection(0)
import time import wx from wx.lib.newevent import NewCommandEvent import pytweening as ptw from aic import ActiveImageControl from aic.util import make_padding sss_cmd_event, EVT_SSS_CHANGE = NewCommandEvent() class SimpleSlideSwitch(ActiveImageControl): def __init__(self, parent, bitmaps, is_vertical=False, max_pos=None, switch_ticks=2, *args, **kwargs): """ An Image Control for presenting a simple multi-position slide switch It behaves similarly to native radio buttons, in that only one value is selected at any one time (obj) :param bitmaps: wx.BitMap objects - iterable (bmp,bmp) (first bitmap will be the static background) (the second will be the handle (pointer), preferably smaller than the static bitmap If the handle is larger, you may need to compensate by adding padding to the slider :param is_vertical: Boolean - does the slider operate in a vertical orientation :param max_pos: Int - maximum limit of handle movement, pixel position relative to the zero position
# -*- coding: utf-8 -*- ## \package dbr.event # # Custom event types & binders # MIT licensing # See: docs/LICENSE.txt from wx.lib.newevent import NewCommandEvent ## Event to post when wiz.wizard.Wizard.ShowPage is called ChangePageEvent = NewCommandEvent() EVT_CHANGE_PAGE = ChangePageEvent[1] ChangePageEvent = ChangePageEvent[0] ## Event to post when dbr.timer.DebreateTimer.Stop is called TimerStopEvent = NewCommandEvent() EVT_TIMER_STOP = TimerStopEvent[1] TimerStopEvent = TimerStopEvent[0] ## Event to post when dbr.log.LogWindow.PollLogFile is called RefreshLogEvent = NewCommandEvent() EVT_REFRESH_LOG = RefreshLogEvent[1] RefreshLogEvent = RefreshLogEvent[0]
#------------------------------------------------------------------------------ # Copyright (c) 2013, Nucleic Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING.txt, distributed with this software. #------------------------------------------------------------------------------ from wx.lib.newevent import NewCommandEvent #: A custom command event that can be posted to request a layout #: when a widget's geometry has changed. On Qt, this type of event #: is posted and handled automatically. This fills that gap. wxEvtLayoutRequested, EVT_COMMAND_LAYOUT_REQUESTED = NewCommandEvent()
class UserList(wx.Panel): SelectEvent, EVT_SELECT = NewCommandEvent() NewEvent, EVT_NEW = NewCommandEvent() DeleteEvent, EVT_DELETE = NewCommandEvent() def __init__(self, *args, **kwargs): super(UserList, self).__init__(*args, **kwargs) sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(sizer) sizer.AddSpacer(8, -1) label_sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(label_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8) users_label = wx.StaticText(self, label="Users") font = users_label.GetFont() font.MakeBold() users_label.SetFont(font) label_sizer.Add(users_label) label_sizer.AddStretchSpacer(1) self.users_qty_label = wx.StaticText(self, label="0") label_sizer.Add(self.users_qty_label) sizer.AddSpacer(8, -1) self.user_list = OLVList(self, size=(435, 150), style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_HRULES | wx.LC_VRULES) self.user_list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_selection) self.user_list.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.on_selection) sizer.Add(self.user_list, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8) self.user_list.SetColumns(columns) self.user_list.AutoSizeColumns() sizer.AddSpacer(8, -1) hsizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(hsizer, 0, wx.ALIGN_RIGHT, 8) self.delete_btn = wx.Button(self, wx.ID_DELETE) self.delete_btn.Bind(wx.EVT_BUTTON, self.on_delete) self.delete_btn.Bind(wx.EVT_UPDATE_UI, self.on_update_delete) hsizer.Add(self.delete_btn, 0, wx.RIGHT, 8) self.new_btn = wx.Button(self, wx.ID_NEW) self.new_btn.Bind(wx.EVT_BUTTON, self.on_new) hsizer.Add(self.new_btn, 0, wx.RIGHT, 8) sizer.AddSpacer(8, -1) self.Layout() self.users = [] self.selected_user = None def on_update_delete(self, event): event_ob = event.EventObject has_selection = bool(self.selected_user) if event_ob.Enabled != has_selection: event.Enable(not event_ob.Enabled) def on_selection(self, event): self.selected_user = self.user_list.GetSelectedObject() evt = self.SelectEvent(self.Id) wx.PostEvent(self, evt) event.Skip() def on_new(self, event): self.user_list.DeselectAll() evt = self.NewEvent(self.Id) wx.PostEvent(self, evt) event.Skip() def on_delete(self, event): dlg = wx.MessageDialog(self, "Are you sure", "Confirm delete", wx.YES_NO) answer = dlg.ShowModal() dlg.Destroy() if answer == wx.ID_NO: return selected_obj = self.user_list.GetSelectedObject() self.user_list.DeselectAll() evt = self.DeleteEvent(self.Id, selected_obj=selected_obj) wx.PostEvent(self, evt) event.Skip() def update_user_list(self, value): self.user_list.SetObjects(value) users_amount = len(value) self.users_qty_label.SetLabel(str(users_amount))
# -*- coding=utf-8 -*- import wx from wx.lib.newevent import NewCommandEvent from wx.lib.scrolledpanel import ScrolledPanel from stickybuttonthemed import StickyButtonThemed SwitchEvent, EVT_SWITCH = NewCommandEvent() class SwitchThemed(ScrolledPanel): def __init__(self, parent, theme=None): super(SwitchThemed, self).__init__(parent) self._theme = theme self._buttonsHeight = 40 self._buttons = [] self._mainSizer = wx.FlexGridSizer(cols=1) self._mainSizer.AddGrowableCol(0) self.SetSizer(self._mainSizer) self.SetupScrolling() def _onButtonClick(self, event): current_button = event.GetEventObject() current_button.SetToggle(True) index = None for n, button in enumerate(self._buttons): if button != current_button:
class UserForm(wx.Panel): AddEvent, EVT_ADD = NewCommandEvent() UpdateEvent, EVT_UPDATE = NewCommandEvent() CancelEvent, EVT_CANCEL = NewCommandEvent() MODE_ADD = "modeAdd" MODE_EDIT = "modeEdit" def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(sizer) sizer.AddSpacer(8, -1) label_sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(label_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8) profile_label = wx.StaticText(self, label="User Profile") font = profile_label.GetFont() font.MakeBold() profile_label.SetFont(font) label_sizer.Add(profile_label) self.username_label = wx.StaticText(self, label="") label_sizer.AddStretchSpacer(1) label_sizer.Add(self.username_label) self.flex_gridsizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=8) sizer.AddSpacer(8, -1) sizer.Add(self.flex_gridsizer, 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER, 8) sizer.AddSpacer(8, -1) ctrl_size = (200, -1) self.first_name_input = wx.TextCtrl(self, size=ctrl_size) self.first_name_input.Bind(wx.EVT_TEXT, partial(self.on_input, "first_name")) self.create_field("First name", self.first_name_input) self.last_name_input = wx.TextCtrl(self, size=ctrl_size) self.last_name_input.Bind(wx.EVT_TEXT, partial(self.on_input, "last_name")) self.create_field("Last name", self.last_name_input) self.email_input = wx.TextCtrl(self, size=ctrl_size) self.email_input.Bind(wx.EVT_TEXT, partial(self.on_input, "email")) self.create_field("Email", self.email_input) self.username_input = wx.TextCtrl(self, size=ctrl_size) self.username_input.Bind(wx.EVT_TEXT, partial(self.on_input, "user_name")) self.username_input.Bind(wx.EVT_UPDATE_UI, self.on_update_username_input) self.create_field("Username*", self.username_input) self.password_input = wx.TextCtrl(self, size=ctrl_size, style=wx.TE_PASSWORD) self.password_input.Bind(wx.EVT_TEXT, partial(self.on_input, "password")) self.create_field("Password*", self.password_input) self.confirm_input = wx.TextCtrl(self, size=ctrl_size, style=wx.TE_PASSWORD) self.create_field("Confirm Password*", self.confirm_input) self.department_combo = wx.ComboBox(self, size=ctrl_size) self.department_combo.Bind(wx.EVT_TEXT, partial(self.on_combo, "department")) self.create_field("Department*", self.department_combo) self.set_department_list(dept_combo_list) hsizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(hsizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8) self.submit_btn = wx.Button(self, -1, "Add User", size=(100, -1)) self.submit_btn.Bind(wx.EVT_BUTTON, self.on_submit) self.submit_btn.Bind(wx.EVT_UPDATE_UI, self.on_update_submit) hsizer.AddStretchSpacer(1) hsizer.Add(self.submit_btn, 0, wx.RIGHT, 8) self.cancelBtn = wx.Button(self, wx.ID_CANCEL) self.cancelBtn.Bind(wx.EVT_BUTTON, self.on_cancel) hsizer.Add(self.cancelBtn, 0, wx.RIGHT) sizer.AddSpacer(8, -1) self.Layout() self.user = None self.mode = UserForm.MODE_ADD self.Bind(wx.EVT_UPDATE_UI, self.on_update_panel, self) def create_field(self, field_name, ctrl): label = wx.StaticText(self, label=field_name) self.flex_gridsizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT) self.flex_gridsizer.Add(ctrl, flag=wx.ALIGN_CENTER) def on_update_panel(self, event): event.Enable(isinstance(self.user, UserVo)) def on_update_submit(self, event): if isinstance(self.user, UserVo): event_ob = event.EventObject if self.mode == self.MODE_ADD: event_ob.SetLabel("Add User") else: event_ob.SetLabel("Update Profile") is_valid = all([ self.user.is_valid, self.confirm_input.GetValue() == self.password_input.GetValue() ]) event.Enable(is_valid) else: event.Skip() def on_update_username_input(self, event): if isinstance(self.user, UserVo): event.Enable(self.mode == UserForm.MODE_ADD) else: event.Skip() def on_input(self, user_field, event): setattr(self.user, user_field, event.String) def on_combo(self, user_field, event): setattr(self.user, user_field, event.ClientData) def on_submit(self, event): if self.mode == self.MODE_ADD: evt = self.AddEvent(self.Id) else: evt = self.UpdateEvent(self.Id) wx.PostEvent(self, evt) event.Skip() def on_cancel(self, event): event.Skip() evt = self.CancelEvent(self.Id) wx.PostEvent(self, evt) def set_department_list(self, dept_list_enum): self.department_combo.Clear() for dept_enum_item in dept_list_enum: self.department_combo.Append(dept_enum_item.value, dept_enum_item) self.department_combo.SetSelection(0) def set_selected_department(self, department): for index in range(self.department_combo.GetCount()): if self.department_combo.GetClientData(index) == department: self.department_combo.SetSelection(index) def set_user(self, user_vo=None, mode=None): self.mode = mode or self.MODE_ADD if user_vo: self.user = user_vo.get_copy() self.populate_from_user() else: self.reset() def populate_from_user(self): self.first_name_input.ChangeValue("%s" % self.user.first_name) self.last_name_input.ChangeValue("%s" % self.user.last_name) self.email_input.ChangeValue("%s" % self.user.email) self.username_input.ChangeValue("%s" % self.user.user_name) self.username_label.SetLabel("%s" % self.user.user_name) self.password_input.ChangeValue("%s" % self.user.password) self.confirm_input.ChangeValue("%s" % self.user.password) self.set_selected_department(self.user.department) self.Layout() self.first_name_input.SetFocus() self.first_name_input.SetInsertionPointEnd() def reset(self): self.user = UserVo() self.populate_from_user() self.user = None
import time from math import atan2, pi, degrees, radians import wx from wx.lib.newevent import NewCommandEvent import pytweening as ptw from aic import ActiveImageControl rd_cmd_event, EVT_RD_CHANGE = NewCommandEvent() class RotaryDial(ActiveImageControl): def __init__(self, parent, bitmaps, *args, **kwargs): """ An Image Control for presenting a rotary dial style, (eg a knob or dial type control) It behaves similarly to a native control slider, except value is expressed as degrees (float) :param bitmaps: wx.BitMap objects - iterable (bmp,bmp) (first bitmap will be the static background) (the second will be the dynamic pointer - an bitmap suitable for rotation - eg a knob pointer) NB: The dynamic bitmap MUST BE A SQUARE (w=h); Even pixel dimensions will rotate slightly better (eg 50x50 not 51x51) The rotating bitmap must be smaller than the base bitmap It might be possible to do a partially exposed knob using a mask??? EVT_RD_CHANGE: returns .value: float -> the degrees difference from the 'zero' point of the dial Positive values only, in clockwise rotation For example: if the zero point is at 9 0'clock and the handle is at 6 0'clock, .value will return: 270 (degrees)
#!/usr/bin/env python # -*- coding: utf-8 -*- ########################################################################### ## Python code generated with wxFormBuilder (version Jun 17 2015) ## http://www.wxformbuilder.org/ ## ## PLEASE DO "NOT" EDIT THIS FILE! ########################################################################### import wx import wx.xrc from wx.lib.newevent import NewCommandEvent TimerChangeEvent, EVT_TIMER_CHANGE = NewCommandEvent() DisplayUpdate, EVT_DISP_UPDATE = wx.lib.newevent.NewEvent() import numpy as np import matplotlib from matplotlib import dates from datetime import datetime, timedelta import time # matplotlib采用WXAgg为后台,将matplotlib嵌入wxPython中 matplotlib.use("WXAgg") from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar from matplotlib.ticker import MultipleLocator, FuncFormatter