【问题标题】:WxPython Layout with Graph and Grid带有图形和网格的 WxPython 布局
【发布时间】:2019-07-02 13:31:45
【问题描述】:

布局无法正常工作。我希望屏幕分成相等的部分。中间最左边的按钮是 mathplotlib 图,右边是网格。有两个问题 mathplotlib 图没有出现居中,网格不在最右边。

我已尝试更改尺寸器并向它们添加一些标志。

import wx
import wx.grid as grid
from sympy import Symbol, sympify
from matplotlib.pyplot import plot, show, title, xlabel, ylabel
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np

h = float()
xi = float()
yi = float()
fx = Symbol('fx')
xistr = np.array([])
yistr = np.array([])
istr = np.array([])
hstr = np.array([])
state = float()


class MyPanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        ###########
        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
        left_sizer = wx.BoxSizer(wx.VERTICAL)
        center_sizer = wx.BoxSizer(wx.VERTICAL)
        right_sizer = wx.BoxSizer(wx.VERTICAL)
        main_sizer.Add(left_sizer, 1, wx.EXPAND)
        main_sizer.Add(center_sizer, 1, wx.EXPAND)
        main_sizer.Add(right_sizer, 1, wx.EXPAND)
        ###########
        self.runbn = wx.Button(self, label="Run", size=(60, 30))
        self.Bind(wx.EVT_BUTTON, self.Run, self.runbn)
        ############
        self.functionin = wx.TextCtrl(self, size=(150, 30), style=wx.TE_CENTER)
        self.STRfxbn = wx.Button(self, -1, label="STR", size=(60, 30))
        self.Bind(wx.EVT_BUTTON, self.STRfc, self.STRfxbn)
        ############
        self.yiin = wx.TextCtrl(self, size=(150, 30), style=wx.TE_CENTER)
        self.STRyibn = wx.Button(self, -1, label="STR", size=(60, 30))
        self.Bind(wx.EVT_BUTTON, self.STRyi, self.STRyibn)
        ############
        self.xiin = wx.TextCtrl(self, size=(150, 30), style=wx.TE_CENTER)
        self.STRxibn = wx.Button(self, -1, label="STR", size=(60, 30))
        self.Bind(wx.EVT_BUTTON, self.STRxi, self.STRxibn)
        ############
        self.hiin = wx.TextCtrl(self, size=(150, 30), style=wx.TE_CENTER)
        self.STRhibn = wx.Button(self, -1, label="STR", size=(60, 30))
        self.Bind(wx.EVT_BUTTON, self.STRhi, self.STRhibn)
        ###########
        self.resultbn = wx.Button(self, label="Results", size=(60, 30))
        self.Bind(wx.EVT_BUTTON, self.showresults, self.resultbn)
        ############

        left_sizer.Add(wx.StaticText(self, -1, "f(x) for ODE"))
        left_sizer.Add(self.functionin, 0)
        left_sizer.Add(self.STRfxbn, 0)

        left_sizer.Add(wx.StaticText(self, -1, "Initial y value"))
        left_sizer.Add(self.yiin, 0)
        left_sizer.Add(self.STRyibn, 0)

        left_sizer.Add(wx.StaticText(self, -1, "Initial x value"))
        left_sizer.Add(self.xiin)
        left_sizer.Add(self.STRxibn)

        left_sizer.Add(wx.StaticText(self, -1, "Initial step h"))
        left_sizer.Add(self.hiin)
        left_sizer.Add(self.STRhibn)

        left_sizer.Add(self.runbn, 0)
        left_sizer.Add(self.resultbn, 0)
        self.SetSizer(main_sizer)

    def showresults(self, event):
        global istr
        global xistr
        global yistr
        global hstr
        resultgr = grid.Grid(self)
        resultgr.CreateGrid(30, 4)
        resultgr.SetColLabelValue(0, "Iteration")
        resultgr.SetColLabelValue(1, "X Value")
        resultgr.SetColLabelValue(2, "Y Value")
        resultgr.SetColLabelValue(3, "Step Size")
        r = 0
        i = 0
        for i in range(30):
            resultgr.SetCellValue(r, 0, str(round(istr[r], 4)))
            r = r + 1
            i = i + 1
        r = 0
        i = 0
        for i in range(30):
            resultgr.SetCellValue(r, 1, str(round(xistr[r], 4)))
            r = r + 1
            i = i + 1
        r = 0
        i = 0
        for i in range(30):
            resultgr.SetCellValue(r, 2, str(round(yistr[r], 4)))
            r = r + 1
            i = i + 1
        r = 0
        i = 0
        for i in range(30):
            resultgr.SetCellValue(r, 3, str(round(hstr[r], 4)))
            r = r + 1
            i = i + 1
        self.figure = Figure(figsize=(5, 4), dpi=100)
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.axes.set_xlabel("x values")
        self.axes.set_ylabel("y values")
        self.axes.set_title("Prince-Dormand")
        self.axes.plot(xistr, yistr)
        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
        left_sizer = wx.BoxSizer(wx.VERTICAL)
        center_sizer = wx.BoxSizer(wx.VERTICAL)
        right_sizer = wx.BoxSizer(wx.VERTICAL)
        main_sizer.Add(left_sizer, 2, wx.EXPAND)
        main_sizer.Add(center_sizer, 1, wx.EXPAND)
        main_sizer.Add(right_sizer, 1, wx.EXPAND)
        center_sizer.Add(self.canvas, 0, wx.LEFT, 200)
        right_sizer.Add(resultgr, 0, wx.RIGHT, 0)
        self.SetSizer(main_sizer)
        self.Fit()

... Following are button functions and main function which calculates values that go into graph and grid

class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title='Prince-Dormand Method', size=(1300, 600))
        panel = MyPanel(self)
        self.Show()


if __name__ == '__main__':
    app = wx.App(False)
    resultgr = grid.Grid()
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

应该发生的情况是每个元素都在屏幕的相应部分中。

【问题讨论】:

  • 就目前而言,您的代码无法运行。为了改善您的问题,请固定所有值,固定绘图。将代码归结为最基本的内容。还要检查您的 for i in range 代码,您不必增加 i 和 r,使用 i 这就是 range 函数的作用。一个好问题的关键是让某人尽可能容易地提供帮助。基本布局应该足够简单,但没有人愿意通过一行行无法运行的代码。
  • 会添加完整的代码帮助吗?(可运行)
  • 以下提供关于mcvestackoverflow.com/help/minimal-reproducible-example的建议,目的是让您的问题易于回答and经常在创建它的过程中,您可能会回答您自己的问题,因为必须以不同的方式思考问题或简化问题,可以为您提供以前没有的洞察力。

标签: python-3.x matplotlib wxpython


【解决方案1】:

您可以在下面找到具有所需小部件分布的工作示例。 下面的代码应该是您添加应用所需的所有其他小部件和方法的良好起点。

import wx
import wx.grid as grid
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure

class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title='Prince-Dormand Method', size=(800, 600))

        ####---- Widgets
        self.panel = wx.Panel(self)
        # Left Sizer Widgets here
        self.runbn = wx.Button(self.panel, label="Run", size=(60, 30))
        # Matplotlib plot here
        self.figure = Figure(figsize=(5, 4), dpi=100)
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self.panel, -1, self.figure)
        self.axes.set_xlabel("x values")
        self.axes.set_ylabel("y values")
        self.axes.set_title("Prince-Dormand")
        # Grid here
        self.resultgr = grid.Grid(self)
        self.resultgr.CreateGrid(30, 4)
        self.resultgr.SetColLabelValue(0, "Iteration")
        self.resultgr.SetColLabelValue(1, "X Value")
        self.resultgr.SetColLabelValue(2, "Y Value")
        self.resultgr.SetColLabelValue(3, "Step Size")
        ####---- Sizers
        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
        left_sizer = wx.BoxSizer(wx.VERTICAL)
        center_sizer = wx.BoxSizer(wx.VERTICAL)
        right_sizer = wx.BoxSizer(wx.VERTICAL)

        left_sizer.Add(self.runbn, 1, wx.ALIGN_CENTER)
        center_sizer.Add(self.canvas, 1, wx.EXPAND)
        right_sizer.Add(self.resultgr, 1, wx.EXPAND)

        main_sizer.Add(left_sizer, 1, wx.EXPAND)
        main_sizer.Add(center_sizer, 1, wx.EXPAND)
        main_sizer.Add(right_sizer, 1, wx.EXPAND)

        self.panel.SetSizer(main_sizer)
        main_sizer.Fit(self.panel)
    #---
#---

if __name__ == '__main__':
    app = wx.App(False)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

【讨论】:

  • 非常感谢。然而,我有两个问题。为什么由sizer创建的所有框的大小都不一样?如何防止网格的一部分在窗口之外?
  • 原则上,由于您使用 wx.BoxSizer 作为 main_sizer,它们的大小应该完全相同。网格的问题是图形比网格宽。由于 main_sizer 为 center_sizer 和 right_sizer 提供了相同的宽度,因此网格中的底部白色面板变得更宽并超出了单元格。将图形的大小更改为 4,4 以查看差异。您真的需要所有部分的宽度相同吗?使用 wx.FlexGridSizer 作为 main_sizer 可能会更好。
猜你喜欢
  • 1970-01-01
  • 2014-06-02
  • 2013-08-01
  • 1970-01-01
  • 2012-03-01
  • 1970-01-01
  • 2018-07-28
  • 2020-10-18
  • 1970-01-01
相关资源
最近更新 更多