admin
2024-05-07 582b3f0e67e5bf2f5806b70600faaa89f44215a6
gui_wx.py
@@ -1486,6 +1486,335 @@
        return t1
class TickCompareFrame(wx.Frame):
    mark_lines = {}
    def __init__(self):
        '''构造函数'''
        wx.Frame.__init__(self, None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE,
                          size=(800, 1000))
        self.SetBackgroundColour(wx.Colour(0, 0, 0))
        self.Center()
        # 拉取数据线程
        self.cost_price_threads = {}
        # 以下代码处理图标
        # if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
        #     exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
        #     icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
        # else:
        #     icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
        # self.SetIcon(icon)
        # 定义窗口关闭
        self.Bind(wx.EVT_CLOSE, self.OnExit)
        self.Bind(wx.EVT_SIZE, self.OnResize)
        self.panels = []
        self.scroll = None
        self.col = 1
        self.ratio = 0.55
        self.__re_draw()
        self.timer = wx.Timer(self)  # 创建定时器
        self.Bind(wx.EVT_TIMER, self.post_redraw, self.timer)  # 绑定一个定时器事件
        self.last_size = (self.Size[0], self.Size[1])
        # 初始化
        #  self.scroll = wx.ScrolledWindow(self, -1, size=(800, 1000))
        self.boxsier = wx.BoxSizer(wx.VERTICAL)
        boxSizer1 = wx.BoxSizer(wx.HORIZONTAL)
        self.edit_code1 = wx.TextCtrl(self, size=(100, 30))
        self.edit_code2 = wx.TextCtrl(self, size=(100, 30))
        self.btn_load_data = wx.Button(self, label="加载数据", size=(100, 30))
        boxSizer1.Add(self.edit_code1)
        boxSizer1.Add(self.edit_code2)
        boxSizer1.Add(self.btn_load_data, 1, wx.LEFT|wx.TOP, 2)
        self.boxsier.Add(boxSizer1)
        # self.scroll.EnableScrolling(False, True)
        # self.boxsier.Add(wx.FlexGridSizer(rows, self.col, space, space))
        # self.scroll.SetSizer(self.boxsier)
        # self.scroll.Layout()
        # self.boxsier.Fit(self.scroll)
        # boxsier.Add(mainBoxsier, 1, wx.EXPAND | wx.ALL, 5)
        # self.SetSizer(boxsier)
        # mainBoxsier.Fit(self)
        if setting.is_stay_on_top():
            self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.STAY_ON_TOP
    def __re_draw(self):
        return
        codes_name = juejin_core.GPCodeManager().get_codes_with_names()
        rows = len(codes_name)
        if rows % self.col == 0:
            rows = rows / self.col
        else:
            rows = rows / self.col + 1
        space = 0
        if not self.scroll:
            return
        if self.panels:
            for p in self.panels:
                p.Destroy()
        self.boxsier.Clear()
        pannel_height = round((self.Size[0] - (self.col - 1) * space) / self.col * self.ratio)
        self.scroll.SetScrollbars(1, 1, 0, pannel_height * rows)
        self.scroll.SetScrollRate(0, pannel_height)
        global drawManager
        axes_list = []
        self.panels = []
        for i in range(0, len(codes_name)):
            # pos=(0, i * pannel_height)
            pannel = wx.Panel(self.scroll, size=(-1, pannel_height))
            pannel.BackgroundColour = wx.Colour(0, 0, 0)
            self.panels.append(pannel)
            self.boxsier.Add(pannel)
            code = codes_name[i][0]
            axes = self.__create_canvas(pannel, code, "{}({})".format(codes_name[i][0], codes_name[i][1]),
                                        codes_name[i][1],
                                        codes_name[i][2])
            if code not in self.cost_price_threads:
                t1 = self.run_get_cost_price(codes_name[i][0])
                self.cost_price_threads[code] = t1
            axes_list.append(axes)
        self.scroll.Layout()
        # self.boxsier.Fit(self.scroll)
        #
        # 初始化数据
        drawManager = DrawManager(axes_list, codes_name)
        t1 = threading.Thread(target=lambda: drawManager.init_code_datas())
        # 后台运行
        t1.setDaemon(True)
        t1.start()
    @classmethod
    def set_mouse_data(cls, xdata, ydata, code, axes2):
        try:
            if code not in cls.mark_lines:
                cls.mark_lines[code] = {}
            if "mouse" not in cls.mark_lines[code]:
                line_h = axes2.axhline(ydata, linestyle='-', color='white', lw=0.5, zorder=3)
                line_v = axes2.axvline(xdata, linestyle='-', color='white', lw=0.5, zorder=3)
                text_h = axes2.text(axes2.get_xlim()[1], ydata, r'', fontsize=10, color='white',
                                    verticalalignment="center", bbox=dict(facecolor='white', alpha=0.9), zorder=3)
                text_v = axes2.text(xdata, axes2.get_ylim()[0], r'', fontsize=10, color='red',
                                    verticalalignment='top', horizontalalignment='center',
                                    bbox=dict(facecolor='white', alpha=0.9), zorder=3)
                cls.mark_lines[code]["mouse"] = (line_h, line_v, text_h, text_v)
            line = cls.mark_lines.get(code).get("mouse")
            x = round(xdata)
            y = round(ydata, 2)
            line[0].set_ydata(ydata)
            line[1].set_xdata(xdata)
            line[2].set_text(f"{y}%")
            line[3].set_text(f"{tool.trade_time_add_second('09:30:00', x)}")
            line[2].set_x(axes2.get_xlim()[1] * (1 + 0.005))
            line[2].set_y(y)
            line[3].set_x(x)
            line[3].set_y(axes2.get_ylim()[0] * (1 + 0.02))
            if y >= 0:
                line[2].set_color('red')
            else:
                line[2].set_color('green')
            axes2.figure.canvas.draw()
        except Exception as e:
            pass
    def __create_canvas(self, pannel, code, title, name, price, close_callback=None):
        TickDataProcess.clear(code)
        def show_mouse_line(event):
            # 删除之前的线
            self.set_mouse_data(event.xdata, event.ydata, code, axes)
        def clear_mouse_line(event):
            print("clear_mouse_line")
            if code in self.mark_lines:
                if self.mark_lines.get(code):
                    line = self.mark_lines.get(code).get("mouse")
                    if line is not None:
                        for l in line:
                            l.remove()
                        self.mark_lines.get(code).pop("mouse")
                        axes.figure.canvas.draw()
        def close_canvas(event):
            print("关闭", title)
            close_callback(title)
        dpi = 100
        width_dpi = self.Size[0] / (dpi * self.col)
        figure_score = Figure(figsize=(width_dpi, round(width_dpi * (self.ratio), 2)), dpi=dpi)
        # 设置外边距
        right_padding_px = 85
        right = round((self.Size[0] - right_padding_px) / self.Size[0], 4)
        figure_score.subplots_adjust(left=0.01, bottom=0.15, top=0.92,
                                     right=right)
        # 设置字体颜色
        plt.rcParams["text.color"] = "red"
        plt.rcParams["axes.labelcolor"] = "red"
        # 设置坐标轴数字颜色
        plt.rcParams["xtick.color"] = "white"
        plt.rcParams["ytick.color"] = "white"
        # 设置坐标轴颜色
        plt.rcParams["axes.edgecolor"] = "firebrick"
        # 解决中文乱码问题
        plt.rcParams["font.sans-serif"] = ["SimHei"]  # 设置字体
        plt.rcParams["font.serif"] = ["SimHei"]
        plt.rcParams["axes.unicode_minus"] = False  # 该语句解决图像中的“-”负号的乱码问题
        # 测试
        buttonaxe = plt.axes([0.94, 0.5, 0.1, 0.1])
        button1 = Button(buttonaxe, '关闭', color='white', hovercolor='yellow')
        axes = figure_score.add_subplot(1, 1, 1)
        axes.autoscale(True)
        # axes_score.plot(t_score, s_score, 'ro', t_score, s_score, 'k')
        axes.set_title(title)
        axes.grid(False)
        axes.set_xlabel(f'时间({name})')
        axes.dist = 0
        # axes.set_ylabel(u'价格')
        # 获取平开价
        extra = 0  # (tool.get_limit_up_price(price)-decimal.Decimal(price))*decimal.Decimal(0.02)
        axes.patch.set_facecolor('black')
        figure_score.patch.set_facecolor('black')
        # 设置横坐标9:25-15:00
        xs_str = ["09:25", "09:30", "10:30", "11:30", "14:00", "15:00"]
        xs_int = [DrawManager.get_x_time_as_seconds(f"0000-00-00 {x}:00") for x in xs_str]
        axes.set_xticks(xs_int[1:])
        axes.set_xticklabels(xs_str[1:])
        axes.set_xlim([xs_int[0], xs_int[-1]])
        axes2 = axes.twinx()
        # axes2.grid(color='firebrick', ls='-', lw=0.5)
        axes2.grid(color='firebrick', ls='-', lw=0.5)
        # 鼠标在画布移动
        # axes2.figure.canvas.mpl_connect('motion_notify_event', show_mouse_line)
        # # 鼠标离开画布
        # axes2.figure.canvas.mpl_connect('axes_leave_event', clear_mouse_line)
        # 设置纵坐标轴
        limit_up_price = float(tool.get_limit_up_price(price))
        max_rate = round((limit_up_price - price) / price, 4) * 100
        print("涨停最大比例", max_rate)
        # 设置纵坐标信息
        # max_rate = 2
        DrawManager.set_y_info(code, max_rate, axes, axes2, price)
        line = axes2.plot([], [], color='white', linewidth=1)
        average_line = axes2.plot([], [], color='yellow', linewidth=1, linestyle='-')
        average_line_1m = axes2.plot([], [], color='yellow', linewidth=1, linestyle='-')
        # axes2.legend(loc='upper left')
        cannvas = FigureCanvas(pannel, -1, figure_score)
        axes2.text(1, 11.5, r'', fontsize=15, color='red')
        axes2.text(-1, -11.5, r'', fontsize=15, color='red')
        axes2.spines['top'].set_visible(False)
        axes.spines['top'].set_visible(False)
        axes2.spines['bottom'].set_visible(True)
        axes.spines['bottom'].set_visible(False)
        # 中轴线加粗
        hline = axes2.axhline(0, linestyle='-', color='firebrick', lw=2, zorder=1)
        # 设置坐标轴标记点为黑色
        axes.tick_params(axis='x', colors='firebrick')
        axes.tick_params(axis='y', colors='black')
        axes2.tick_params(axis='x', colors='firebrick')
        axes2.tick_params(axis='y', colors='black')
        def update_data(i):
            print("更新数据:", i)
        return axes2, line, average_line_1m, average_line, axes
    def __show_top(self, event):
        if event.Selection:
            setting.set_stay_on_top(1)
            self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.STAY_ON_TOP
        else:
            setting.set_stay_on_top(0)
            self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN
    def OnExit(self, e):
        try:
            setting.set_tick_window_info((self.Position[0], self.Position[1], self.Size[0], self.Size[1]))
        except Exception as e:
            print("")
        self.Hide()
    def post_redraw(self, evt):
        if abs(self.last_size[0] - self.Size[0]) > 20:
            print("--------post_redraw--------")
            self.last_size = (self.Size[0], self.Size[1])
            self.__re_draw()
    def OnResize(self, e):
        print("变化后的尺寸", e.Size)
        # 留出滚动条,留出上边距
        if self.scroll:
            self.scroll.Size = (e.Size[0] - 15, e.Size[1] - 60)
            for p in self.panels:
                p_height = round(e.Size[0] * (450 / 800))
                p.Size = (e.Size[0], p_height)
        self.timer.Stop()
        self.timer.StartOnce(1000)
        # 降低重绘频率
        # self.__re_draw()
    def set_codes_success(self):
        print("设置代码成功回调")
        p2.send("resub")
        self.__re_draw()
        self.timer.Stop()
        self.timer.StartOnce(1000)
        self.Size = wx.Size(self.Size[0], self.Size[1] + 10)
        time.sleep(0.1)
        self.Size = wx.Size(self.Size[0], self.Size[1] - 10)
    def run_get_cost_price(self, code):
        def request(code):
            while True:
                try:
                    price = SocketApiUtil.get_cost_price(code)
                    pre_price = juejin_core.GPCodeManager().get_pre_prices(code)
                    rate = round((price - pre_price) * 100 / pre_price, 2)
                    DrawManager.set_cost_rate(code, rate)
                    # wx.CallAfter(lambda :)
                except Exception as e:
                    DrawManager.set_cost_rate(code, None)
                    # wx.CallAfter(lambda: str(e))
                except:
                    pass
                finally:
                    time.sleep(3)
        t1 = threading.Thread(target=lambda: request(code), daemon=True)
        t1.start()
        return t1
# 绘图管理器
class DrawManager:
    X_RANGE_MINIUTES = 335
@@ -1894,7 +2223,7 @@
    def OnInit(self):
        self.SetAppName(APP_TITLE)
        self.__init_data()
        self.frame = TickFrame()
        self.frame = TickCompareFrame()
        # self.floatFrame = FloatFrame()
        global_datas["tickFrame"] = self.frame
        # global_datas["floatFrame"] = self.floatFrame