python-3.x - AddSpacer 有奇怪的颜色
问题描述
我是使用 Python 构建 GUI 的新手。我正在构建一个从 COM 端口接收数据并将其显示在图表上的应用程序。一切都快完成了,我想在图表和滑块之间留出更多空间,但是当我使用 AddSpacer 时,它们有不同的颜色并且看起来很尴尬。像这样
以下是带有随机数据的程序代码,您可以在自己的计算机上尝试。任何帮助都非常感谢,谢谢!
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# simple.py
import wx
import serial
import time
import os
import numpy as np
import matplotlib
matplotlib.use('WXAgg')
from collections import deque
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
from matplotlib.figure import Figure
########################################################################
class SerialCom():
def __init__(self,port,b_rate):
self.port = port
self.b_rate = b_rate
global ser
ser = serial.Serial()
def connect(self): #Start connect
try:
ser.port = self.port
ser.baudrate = self.b_rate
ser.timeout=1
ser.write_timeout = 1
ser.open()
return('Connecting...')
except serial.SerialException:
return("No serial port found")
time.sleep(1) #Waiting for connection to initialize
def status(self):
x=os.path.exists(self.port)
if x==1:
return 'Connected'
else:
return 'Disconnected'
def disconnect(self):
return('Disconnecting')
ser.close()
class DataGen(object):
""" A silly class that generates pseudo-random data for
display in the plot.
"""
def __init__(self, init=50):
self.data = self.init = init
def next(self):
self._recalc_data()
return self.data
def _recalc_data(self):
delta = random.uniform(-0.5, 0.5)
r = random.random()
if r > 0.9:
self.data += delta * 15
elif r > 0.8:
# attraction to the initial value
delta += (0.5 if self.init > self.data else -0.5)
self.data += delta
else:
self.data += delta
########################################################################
class TopPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.datagen = DataGen()
self.data = [DataGen().next()]
self.paused = False
self.InitGraph()
self.redraw_timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)
self.redraw_timer.Start(50)
def InitGraph(self):
# init graph
self.figure = Figure(dpi = 100)
self.ax = self.figure.add_subplot(111)
#set bg, x, y color
self.ax.set_title('Very important random data', size=14)
self.ax.grid(True, color='gray')
self.ax.tick_params(labelsize=8)
self.canvas = FigureCanvas(self, -1, self.figure)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
#self.sizer.AddSpacer(10)
self.SetSizer(self.sizer)
#self.vals = deque()
self.plot_data, = self.ax.plot([], [])
self.Fit()
def update_graph(self):
xmax = len(self.data) if len(self.data) > 50 else 50
xmin = xmax - 50
ymin = round(min(self.data), 0) - 1
ymax = round(max(self.data), 0) + 1
self.ax.set_xbound(lower=xmin, upper=xmax)
self.ax.set_ybound(lower=ymin, upper=ymax)
self.ax.grid(True, color='gray')
self.plot_data.set_data(np.arange(len(self.data)),np.array(self.data))
self.canvas.draw()
def on_redraw_timer(self, e):
#data = float(random.randint(1, 50))
#self.vals.append(data)
# update plot data
#length = len(self.vals)
self.data.append(self.datagen.next())
self.update_graph()
########################################################################
class BottomPanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent = parent)
self.InitUI()
def InitUI(self):
sizer = wx.GridBagSizer(5, 6)
self.timer = wx.Timer(self, 1)
self.timer.Start(1000)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
#Create Sliders
self.Psld = wx.Slider(self, value=200, minValue=150, maxValue=500, style=wx.SL_HORIZONTAL)
self.Isld = wx.Slider(self, value=200, minValue=150, maxValue=500, style=wx.SL_HORIZONTAL)
self.Dsld = wx.Slider(self, value=200, minValue=150, maxValue=500, style=wx.SL_HORIZONTAL)
sizer.Add(self.Psld, pos=(0, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND, border=10)
sizer.Add(self.Isld, pos=(1, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND, border=10)
sizer.Add(self.Dsld, pos=(2, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND, border=10)
#SliderLabels
Ptxt = wx.StaticText(self, label="P Term")
Itxt = wx.StaticText(self, label="I Term")
Dtxt = wx.StaticText(self, label="D Term")
sizer.Add(Ptxt, pos=(0, 0), flag=wx.LEFT|wx.TOP|wx.RIGHT, border=10)
sizer.Add(Itxt, pos=(1, 0), flag=wx.LEFT|wx.TOP|wx.RIGHT, border=10)
sizer.Add(Dtxt, pos=(2, 0), flag=wx.LEFT|wx.TOP|wx.RIGHT, border=10)
#Slider Value
self.Pval = wx.StaticText(self, label='200')
self.Ival = wx.StaticText(self, label='200')
self.Dval = wx.StaticText(self, label='200')
sizer.Add(self.Pval, pos=(0, 4), flag=wx.TOP|wx.RIGHT, border=10)
sizer.Add(self.Ival, pos=(1, 4), flag=wx.TOP|wx.RIGHT, border=10)
sizer.Add(self.Dval, pos=(2, 4), flag=wx.TOP|wx.RIGHT, border=10)
#Slider Event
self.Psld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
self.Isld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
self.Dsld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
st1 = wx.StaticText(self, label='COM port: ')
self.text_ctrl = wx.TextCtrl(self)
connect_btn = wx.Button(self, label='Enter')
sizer.Add(st1, pos=(0, 5), flag=wx.TOP|wx.RIGHT, border=12)
sizer.Add(self.text_ctrl, pos=(1, 5), flag=wx.TOP|wx.RIGHT, border=5)
sizer.Add(connect_btn, pos=(2, 5), flag=wx.TOP|wx.RIGHT|wx.ALIGN_LEFT, border=5)
connect_btn.Bind(wx.EVT_BUTTON, self.OnPress)
sizer.AddGrowableCol(1)
self.SetSizer(sizer)
def OnSliderScroll(self, e):
valP = self.Psld.GetValue()
valI = self.Isld.GetValue()
valD = self.Dsld.GetValue()
self.Pval.SetLabel(str(valP))
self.Ival.SetLabel(str(valI))
self.Dval.SetLabel(str(valD))
def OnPress(self,e):
global Ser
global statusbar
com = self.text_ctrl.GetValue()
if not com:
statusbar.SetStatusText("Please enter port!")
else:
Ser = SerialCom(com,115200)
statusbar.SetStatusText(Ser.connect())
statusbar.SetStatusText(com, 1)
time.sleep(1)
def OnTimer(self, event):
if Ser != None:
statusbar.SetStatusText(Ser.status())
########################################################################
class GuiFrame(wx.Frame):
def __init__(self,parent,title):
super().__init__(parent, title = title, size = (750,550))
top = TopPanel(self)
bottom = BottomPanel(self)
self.SetIcon(wx.Icon("icon2.png"))
global statusbar
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(top, 1, wx.EXPAND)
main_sizer.AddSpacer(5)
main_sizer.Add(bottom,0, wx.EXPAND)
main_sizer.AddSpacer(5)
self.SetSizer(main_sizer)
statusbar = self.CreateStatusBar(2)
statusbar.SetStatusText('Disconnected')
########################################################################
statusbar = None
Ser = None
if __name__ == "__main__":
app = wx.App()
frame = GuiFrame(None, title='PID Tuner')
frame.Show()
app.MainLoop()
解决方案
原来我需要在顶部和机器人面板顶部添加一个主面板。
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour('black')
top = TopPanel(self.panel)
bottom = BottomPanel(self.panel)
self.SetIcon(wx.Icon("icon2.png"))
global statusbar
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(top, 1, wx.EXPAND|wx.ALL, 5)
sizer.AddSpacer(40)
sizer.Add(bottom, 0, wx.EXPAND|wx.ALL, 5)
self.panel.SetSizer(sizer)
statusbar = self.CreateStatusBar(2)
statusbar.SetStatusText('Disconnected')
推荐阅读
- sap - 获取访问令牌失败:通过 OAuth2Bearer 访问 S4HANA 时未找到有效的 JWT 承载
- php - 用户在上传后注销 [PHP]
- javascript - 我们应该在表单状态中存储原始值还是解析值
- cassandra - 两个 Cassandra 节点,复制因子为 2,但使用的存储大小不同
- javascript - 在 React Native 中,如何从 json 数组中动态获取 flatlist 中的键
- php - 使用include替换iframe php错误
- java - Hibernate 初始化一个组/实体集合
- symfony - sylius 中的重写 Order 类引发异常“sylius_order”已存在
- django - 运行 django auth 迁移不会在 db 中创建表
- mysql - MySQL - 仅当成员不在另一个列表中时才返回成员列表