类中设置了两个方法,用于绘图和更新数据,第一次按下按钮触发Draw函数时使用正常,但是关闭窗口后再次点击按钮,弹出的窗口不再更新,需要通过缩放窗口才可以正常显示调整后的界面,update()、repaint()、showNormal()、adjustSize()等方法均无效(不排除使用方法错误),第二次调用时是直接使用之前创建的窗口,但是在关闭时删除画布和布局后并不能重新生成画布和布局,问题出现在用字典存放的重复利用的窗口与新的布局画布的位置,线程更新正常。
class Ui_MainWindow(object):
def __init__(self):
self.plots = {}
self.timers = {}# 多个线程
self.widgets = {}
for name in ['B1', 'B2', 'B3', 'B4', 'B5', 'B6']:
self.widgets[name] = QWidget()
self.widgets[name].setWindowTitle(name)
def Draw(self, name, index, ylabel):
if name in self.plots:
fig, ax = self.plots[name]
else:
fig, ax = matplotlib.pyplot.subplots()
self.plots[name] = (fig, ax)
canvas = FigureCanvasQTAgg(fig)
layout = QVBoxLayout(self.widgets[name])
layout.addWidget(canvas)
self.widgets[name].show()
def CloseEvent(event, layout, canvas):
try:
print("Widget is closed")
self.timers[name] = False # 将对应的标志位设置为False,关闭线程
timer.timeout.disconnect(update) # 断开与主时间对象的连接
self.widgets[name].close()
except Exception as e:
print(str(e))
self.widgets[name].closeEvent = lambda event: CloseEvent(event, layout, canvas)
self.timers[name] = True # 将对应的标志位设置为True
def update():#根据name运行updata启动数据更新线程
if self.timers[name]:
self.UpdatePlot(ax, name, index, ylabel)
timer.timeout.connect(update)#通过主线程连接update进而选择线程
def UpdatePlot(self, ax, name, index, ylabel):
print(name + "updata")
global table#存放数据的表格
if not table:
return
data = [row[index] for row in table]
t = [row[0] for row in table]
time = []
for item in t:
hours, minutes, seconds = item.split(":")
second = int(hours) * 3600 + int(minutes) * 60 + int(seconds)
time.append(second)
ax.clear() # 清除当前图像
ax.plot(time, data)
ax.set_xlabel('time/s')
ax.set_ylabel(ylabel)
ax.set_title(name)
fig = self.plots[name][0]
fig.canvas.draw()
你的问题可能出现在关闭窗口并不真正销毁窗口对象,而是隐藏了它。因此,当你再次打开窗口时,你正在重新打开隐藏的旧窗口,而非新建一个窗口。在这个旧窗口中,你的图像和布局可能不再有效或正确。
在关闭窗口时,尝试完全删除和销毁旧的布局和画布,然后在打开窗口时,每次都创建新的布局和画布。尝试更新你的Draw
函数,让它每次都创建新的图像和布局,像这样:
def Draw(self, name, index, ylabel):
fig, ax = matplotlib.pyplot.subplots()
self.plots[name] = (fig, ax)
canvas = FigureCanvasQTAgg(fig)
# 每次都创建新的布局
layout = QVBoxLayout(self.widgets[name])
self.widgets[name].setLayout(layout)
# 在添加新的画布前,清除布局中的所有元素
while layout.count():
child = layout.takeAt(0)
if child.widget():
child.widget().deleteLater()
layout.addWidget(canvas)
self.widgets[name].show()
同时,请注意,当你使用self.widgets[name].setLayout(layout)
设置新布局时,Qt会自动删除并销毁旧布局。因此,确保你已保存所有需要保存的数据,因为在设置新布局后,旧布局和它包含的所有小部件都将被删除。