Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 24, 2021 14:57:08

serversss
Зарегистрирован: 2021-04-24
Сообщения: 1
Репутация: +  0  -
Профиль   Отправить e-mail  

Гистограмма с отображением максимального значения

Здравствуйте. подскажите пожалуйста, возможно ли сделать в pyqtgraph гистограмму с отображением максимального значения.
т.е у меня гистограмма показывает в реальном времени изменение 4-х переменных, они постоянно прыгаю и хотелось бы чтобы на графике отображался ее фиксированный максимальный пик ( в виде точки либо второго графика за основной диаграммой).


код отображения гистограммы

 # Plot widget for histogram
        self.pbar = pg.PlotWidget(background = (13 , 13, 13, 255))
        self.pbar.showGrid(x = True, y = True, alpha = 0.7)            
        self.pb1 = pg.BarGraphItem(x=np.linspace(1, 2, num=1), height=np.linspace(1, 2, num=1), width=0.3, pen = QtGui.QColor(153,0,0), brush=QtGui.QColor(153,0,0))
        self.pb2 = pg.BarGraphItem(x=np.linspace(2, 3, num=1), height=np.linspace(2, 3, num=1), width=0.3, pen=QtGui.QColor(229, 104, 19), brush=QtGui.QColor(229, 104, 19))
        self.pb3 = pg.BarGraphItem(x=np.linspace(3, 4, num=1), height=np.linspace(3, 4, num=1), width=0.3, pen=QtGui.QColor(221, 180, 10), brush=QtGui.QColor(221, 180, 10))
        self.pb4 = pg.BarGraphItem(x=np.linspace(4, 5, num=1), height=np.linspace(4, 5, num=1), width=0.3, pen=QtGui.QColor(30, 180, 30), brush=QtGui.QColor(30, 180, 30))
        self.pbar.addItem(self.pb1)  
        self.pbar.addItem(self.pb2)
        self.pbar.addItem(self.pb3)
        self.pbar.addItem(self.pb4)


 self.pb1.setOpts(height=self.DataMovingAverage[0][self.l-1])
                self.pb2.setOpts(height=self.DataMovingAverage[1][self.l-1])
                self.pb3.setOpts(height=self.DataMovingAverage[2][self.l-1])
                self.pb4.setOpts(height=self.DataMovingAverage[3][self.l-1])


основной код

 from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import Qt 
import sys
import serial
import pyqtgraph as pg
import numpy as np
import time
from scipy.signal import butter, lfilter
import serial.tools.list_ports
from datetime import datetime
from scipy.fftpack import fft
# Main window
class GUI(QtWidgets.QMainWindow):
    # Initialize constructor
    def __init__(self):
          super(GUI, self).__init__()
          self.initUI()
    # Custom constructor
    def initUI(self): 
        # Values
        COM = '' #Example: COM='COM6'
        baudRate = 115200 #Serial frequency
        self.f = open(datetime.now().strftime("%Y_%m_%d_%H_%M_%S") + ".txt", "w")
        self.f.write(datetime.now().strftime("Date: %Y.%m.%d\rTime: %H:%M:%S") + "\r\n")
        self.f.write("File format: \r\nseconds | data1 | data2 | data3 | data4 | data5 | data6 | data7| data8 | data9 \r\n")
        self.l = 0 #Current point
        self.dt = 0.00125 #Updating time s
        self.fs = 1 / self.dt #Updating frequency in Hz
        self.passLowFrec = 10.0 #Low frequency for passband filter
        self.passHighFrec = 200.0 #Low frequency for passband filter
        self.dataWidth = 10000 #Maximum count of data points
        self.xH = [0]*10
        self.Time = [0]*self.dataWidth #Tine array
        self.timeWidth = 10 #Time width of plot
        self.Data = np.zeros((9, self.dataWidth))
        self.DataMovingAverage = np.zeros((4, self.dataWidth))
        self.MA = np.zeros((9, 3))
        self.MA_alpha = 0.95
        self.Y0 = np.zeros(9)
        self.X0 = np.zeros(9)
        self.FFT = 0
        self.msg_end = np.array([0])
        self.setWindowTitle("MYOstack GUI v1.0.1 | ELEMYO" + "    ( COM Port not found )")
        self.setWindowIcon(QtGui.QIcon('img/icon.png'))
        # Menu panel
        startAction = QtGui.QAction(QtGui.QIcon('img/start.png'), 'Start (Enter)', self)
        startAction.setShortcut('Return')
        startAction.triggered.connect(self.start)
        stopAction = QtGui.QAction(QtGui.QIcon('img/pause.png'), 'Stop (Space)', self)
        stopAction.setShortcut('Space')
        stopAction.triggered.connect(self.stop)
        refreshAction = QtGui.QAction(QtGui.QIcon('img/refresh.png'), 'Refresh (R)', self)
        refreshAction.setShortcut('r')
        refreshAction.triggered.connect(self.refresh)
        exitAction = QtGui.QAction(QtGui.QIcon('img/out.png'), 'Exit (Esc)', self)
        exitAction.setShortcut('Esc')
        exitAction.triggered.connect(self.close)
        # Toolbar
        toolbar = self.addToolBar('Tool')
        toolbar.addAction(startAction)
        toolbar.addAction(stopAction)
        toolbar.addAction(refreshAction)
        toolbar.addAction(exitAction)
        
        # Plot widget for 1st sensor
        self.pw1 = pg.PlotWidget(background = (21 , 21, 21, 255))
        self.pw1.showGrid(x = True, y = True, alpha = 0.7) 
        self.p1 = self.pw1.plot()
        self.p1.setPen(color=(100,255,255), width=1)
        # Plot widget for 2nd sensor
        self.pw2 = pg.PlotWidget(background = (13 , 13, 13, 255))
        self.pw2.showGrid(x = True, y = True, alpha = 0.7) 
        self.p2 = self.pw2.plot()
        self.p2.setPen(color=(100,255,255), width=1)
        # Plot widget for 3rd sensor
        self.pw3 = pg.PlotWidget(background = (21 , 21, 21, 255))
        self.pw3.showGrid(x = True, y = True, alpha = 0.7) 
        self.p3 = self.pw3.plot()
        self.p3.setPen(color=(100,255,255), width=1)
        # Plot widget for 4th sensor
        self.pw4 = pg.PlotWidget(background = (13 , 13, 13, 255))
        self.pw4.showGrid(x = True, y = True, alpha = 0.7) 
        self.p4 = self.pw4.plot()
        self.p4.setPen(color=(100,255,255), width=1)
        # Plot widget for 5th sensor
        self.pw5 = pg.PlotWidget(background = (21 , 21, 21, 255))
        self.pw5.showGrid(x = True, y = True, alpha = 0.7) 
        self.p5 = self.pw5.plot()
        self.p5.setPen(color=(100,255,255), width=1)
        # Plot widget for 6th sensor
        self.pw6 = pg.PlotWidget(background = (13 , 13, 13, 255))
        self.pw6.showGrid(x = True, y = True, alpha = 0.7) 
        self.p6 = self.pw6.plot()
        self.p6.setPen(color=(100,255,255), width=1)
        # Plot widget for 7th sensor
        self.pw7 = pg.PlotWidget(background = (21 , 21, 21, 255))
        self.pw7.showGrid(x = True, y = True, alpha = 0.7) 
        self.p7 = self.pw7.plot()
        self.p7.setPen(color=(100,255,255), width=1)
        # Plot widget for 8th sensor
        self.pw8 = pg.PlotWidget(background = (13 , 13, 13, 255))
        self.pw8.showGrid(x = True, y = True, alpha = 0.7) 
        self.p8 = self.pw8.plot()
        self.p8.setPen(color=(100,255,255), width=1)
        # Plot widget for 9th sensor
        self.pw9 = pg.PlotWidget(background = (21 , 21, 21, 255))
        self.pw9.showGrid(x = True, y = True, alpha = 0.7) 
        self.p9 = self.pw9.plot()
        self.p9.setPen(color=(100,255,255), width=1)
        
        # Plot widget for spectral Plot
        self.pw10 = pg.PlotWidget(background = (13 , 13, 13, 255))
        self.pw10.showGrid(x = True, y = True, alpha = 0.7) 
        self.p10 = self.pw10.plot()
        self.p10.setPen(color=(100,255,255), width=1)
        self.pw10.setLabel('bottom', 'Frequency', 'Hz')
        
        # Plot widget for histogram
        self.pbar = pg.PlotWidget(background = (13 , 13, 13, 255))
        self.pbar.showGrid(x = True, y = True, alpha = 0.7)            
        self.pb1 = pg.BarGraphItem(x=np.linspace(1, 2, num=1), height=np.linspace(1, 2, num=1), width=0.3, pen = QtGui.QColor(153,0,0), brush=QtGui.QColor(153,0,0))
        self.pb2 = pg.BarGraphItem(x=np.linspace(2, 3, num=1), height=np.linspace(2, 3, num=1), width=0.3, pen=QtGui.QColor(229, 104, 19), brush=QtGui.QColor(229, 104, 19))
        self.pb3 = pg.BarGraphItem(x=np.linspace(3, 4, num=1), height=np.linspace(3, 4, num=1), width=0.3, pen=QtGui.QColor(221, 180, 10), brush=QtGui.QColor(221, 180, 10))
        self.pb4 = pg.BarGraphItem(x=np.linspace(4, 5, num=1), height=np.linspace(4, 5, num=1), width=0.3, pen=QtGui.QColor(30, 180, 30), brush=QtGui.QColor(30, 180, 30))
        self.pbar.addItem(self.pb1)  
        self.pbar.addItem(self.pb2)
        self.pbar.addItem(self.pb3)
        self.pbar.addItem(self.pb4)
        
        self.pbar.setLabel('bottom', 'Sensor number')
        
        # Styles
        centralStyle = "color: rgb(255, 255, 255); background-color: rgb(13, 13, 13);"
        editStyle = "border-style: solid; border-width: 1px;"
        
        # Settings zone
        filtersText = QtWidgets.QLabel("FILTERS:")
        self.passLowFreq = QtWidgets.QLineEdit(str(self.passLowFrec), self)
        self.passLowFreq.setMaximumWidth(100)
        self.passLowFreq.setStyleSheet(editStyle)
        self.passHighFreq = QtWidgets.QLineEdit(str(self.passHighFrec), self)
        self.passHighFreq.setMaximumWidth(100)
        self.passHighFreq.setStyleSheet(editStyle)
        self.bandpass = QtWidgets.QCheckBox("BANDPASS FILTER:")
        self.bandstop50 = QtWidgets.QCheckBox("NOTCH 50 Hz")
        self.bandstop60 = QtWidgets.QCheckBox("NOTCH 60 Hz")
        self.MovingAverage = QtWidgets.QCheckBox("Signal envelope")
        
        fft1 = QtWidgets.QRadioButton('1')
        fft1.setChecked(True)
        fft1.Value = 1
        fft2 = QtWidgets.QRadioButton('2')
        fft2.Value = 2
        fft3 = QtWidgets.QRadioButton('3')
        fft3.Value = 3
        fft4 = QtWidgets.QRadioButton('4')
        fft4.Value = 4
        fft5 = QtWidgets.QRadioButton('5')
        fft5.Value = 5
        fft6 = QtWidgets.QRadioButton('6')
        fft6.Value = 6
        fft7 = QtWidgets.QRadioButton('7')
        fft7.Value = 7
        fft8 = QtWidgets.QRadioButton('8')
        fft8.Value = 8
        fft9 = QtWidgets.QRadioButton('9')
        fft9.Value = 9
        self.button_group = QtWidgets.QButtonGroup()
        
        
        self.button_group.buttonClicked.connect(self._on_radio_button_clicked)
        
        self.l11 = QtWidgets.QLabel("")
        self.l11.setStyleSheet("font-size: 25px; background-color: rgb(21,21,21);")
        self.l13 = QtWidgets.QLabel("")
        self.l13.setStyleSheet("font-size: 25px; background-color: rgb(21,21,21);")
        self.l15 = QtWidgets.QLabel("")
        self.l15.setStyleSheet("font-size: 25px; background-color: rgb(21,21,21);")
        self.l17 = QtWidgets.QLabel("")
        self.l17.setStyleSheet("font-size: 25px; background-color: rgb(21,21,21);")
        self.l19 = QtWidgets.QLabel("")
        self.l19.setStyleSheet("font-size: 25px; background-color: rgb(21,21,21);")
        self.l1 = QtWidgets.QLabel(" 1 ")
        self.l1.setStyleSheet("font-size: 25px; background-color: rgb(153,0,0); border-radius: 14px;")
        self.l2 = QtWidgets.QLabel(" 2")
        self.l2.setStyleSheet("font-size: 25px; background-color: rgb(229, 104, 19); border-radius: 14px;") 
        self.l3 = QtWidgets.QLabel(" 3 ")
        self.l3.setStyleSheet("font-size: 25px; background-color: rgb(221, 180, 10); border-radius: 14px;")
        self.l4 = QtWidgets.QLabel(" 4 ")
        self.l4.setStyleSheet("font-size: 25px; background-color: rgb(30, 180, 30); border-radius: 14px;")
        self.l5 = QtWidgets.QLabel(" 5 ")
        self.l5.setStyleSheet("font-size: 25px; background-color: rgb(11, 50, 51); border-radius: 14px;")
        self.l6 = QtWidgets.QLabel(" 6 ")
        self.l6.setStyleSheet("font-size: 25px; background-color: rgb(29, 160, 191); border-radius: 14px;")
        self.l7 = QtWidgets.QLabel(" 7 ")
        self.l7.setStyleSheet("font-size: 25px; background-color: rgb(30, 30, 188); border-radius: 14px;")
        self.l8 = QtWidgets.QLabel(" 8 ")
        self.l8.setStyleSheet("font-size: 25px; background-color: rgb(75, 13, 98); border-radius: 14px;")
        self.l9 = QtWidgets.QLabel(" 9 ")
        self.l9.setStyleSheet("font-size: 25px; background-color: rgb(139, 0, 55); border-radius: 14px;")
        # Main widget
        centralWidget = QtWidgets.QWidget()
        centralWidget.setStyleSheet(centralStyle)
        # Layout
        vbox = QtWidgets.QVBoxLayout()
        
        layout = QtWidgets.QGridLayout()
        
        layout.addWidget(self.l1, 0, 1, Qt.AlignVCenter)
        layout.addWidget(self.l2, 0, 4, Qt.AlignVCenter)
        
        layout.addWidget(self.l3, 1, 1, Qt.AlignVCenter)
        layout.addWidget(self.l4, 1, 4, Qt.AlignVCenter)
        
        
        
        
        layout.addWidget(self.pw1, 0, 2)
        layout.addWidget(self.pw2, 0, 3)
        layout.addWidget(self.pw3, 1, 2)
        layout.addWidget(self.pw4, 1, 3)
        
        layout.addWidget(self.pbar, 2, 2)
        
        
        
       
            
        
        vbox.addWidget(self.bandpass) 
          
        
        vbox.addLayout(layout)
        centralWidget.setLayout(vbox)
        self.setCentralWidget(centralWidget)  
        self.showMaximized()
        self.show()
        # Serial monitor
        self.monitor = SerialMonitor(COM, baudRate)
        self.monitor.bufferUpdated.connect(self.updateListening, QtCore.Qt.QueuedConnection)
    # Start working
    def start(self):
        self.monitor.running = True
        self.monitor.start()
    # Pause
    def stop(self):
        self.monitor.running = False    
    # Refresh
    def refresh(self):
        self.l = 0 #Current point
        self.Time = [0]*self.dataWidth #Tine array
        self.Data = np.zeros((9, self.dataWidth))
        self.DataMovingAverage = np.zeros((9, self.dataWidth))
        self.Time = [0]*self.dataWidth
        self.msg_end = 0        
    # Update
    def updateListening(self, msg):
        # Update variables
        self.setWindowTitle("MYOstack GUI v1.0.1 | ELEMYO " + 
                            "    ( " + self.monitor.COM + " , " + str(self.monitor.baudRate) + " baud )")
        s = self.passLowFreq.text()
        if s.isdigit():
            self.passLowFrec = float(s)
        s = self.passHighFreq.text()
        if s.isdigit():
            self.passHighFrec = float(self.passHighFreq.text())
        # Parsing data from serial buffer
        msg = msg.decode(errors='ignore')
        if len(msg) >= 2:
            msg_end_n = msg.rfind("\r", 1)
            msg_begin = self.msg_end
            self.msg_end = msg[msg_end_n:len(msg)]
            if(self.l > 2):
                msg = msg_begin + msg[0:msg_end_n]
            for st in msg.split('\r\n'):
                s = st.split(' ')
                if (len(s) == 4) :
                    if ( self.l == self.dataWidth):
                        self.l = 0
                    for i in range(4):
                        self.Data[i][self.l] = int(s[i])/1.024*3.3
                        self.DataMovingAverage[i][self.l] = self.movingAverage(i, self.Data[i][self.l], self.MA_alpha)
                        
                    self.Time[self.l] = self.Time[self.l - 1] + self.dt
                    self.f.write(str(round(self.Time[self.l], 3)) + " " + str(self.Data[0][self.l]) + " " + str(self.Data[1][self.l]) + " "
                                 + str(self.Data[2][self.l]) + " " + str(self.Data[3][self.l]) + " "
                                 + str(self.Data[4][self.l]) + "\r\n")
                    
                    self.l = self.l + 1
                
        # Filtering
        Data = np.zeros((9, self.dataWidth))
        for i in range(9):
            Data[i] = np.concatenate((self.Data[i][self.l: self.dataWidth], self.Data[i][0: self.l]))
        
        Time = self.Time[self.l + 1: self.dataWidth-1]+(self.Time[0: self.l])
        
        if (self.bandpass.isChecked() == 1 and self.passLowFrec < self.passHighFrec 
            and self.passLowFrec > 0 and self.fs > 2*self.passHighFrec):
            for i in range(9):
                Data[i] = self.butter_bandpass_filter(Data[i], self.passLowFrec, self.passHighFrec, self.fs)
        if self.bandstop50.isChecked() == 1:
            if self.fs > 110: 
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 48, 52, self.fs)
            if self.fs > 210: 
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 98, 102, self.fs)
            if self.fs > 310: 
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 148, 152, self.fs)
            if self.fs > 410:
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 198, 202, self.fs)
        if self.bandstop60.isChecked() == 1:
            if self.fs > 130:
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 58, 62, self.fs)
            if self.fs > 230:
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 118, 122, self.fs)
            if self.fs > 330:
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 158, 162, self.fs)
            if self.fs > 430:
                for i in range(9): Data[i] = self.butter_bandstop_filter(Data[i], 218, 222, self.fs)
        # Shift the boundaries of the graph
        timeCount = self.Time[self.l - 1] // self.timeWidth
        # Update plot
        if (self.l > 3):
            # Main signal graphic
            self.pw1.setXRange(self.timeWidth * timeCount, self.timeWidth * ( timeCount + 1))
            self.pw2.setXRange(self.timeWidth * timeCount, self.timeWidth * ( timeCount + 1))
            self.pw3.setXRange(self.timeWidth * timeCount, self.timeWidth * ( timeCount + 1))
            self.pw4.setXRange(self.timeWidth * timeCount, self.timeWidth * ( timeCount + 1))
            self.pw5.setXRange(self.timeWidth * timeCount, self.timeWidth * ( timeCount + 1))
            
            
            if self.MovingAverage.isChecked() == 1:
                for i in range(9):
                    Data[i] = np.concatenate((self.DataMovingAverage[i][self.l: self.dataWidth], self.DataMovingAverage[i][0: self.l]))
            
            self.p1.setData(y=Data[0][0: self.dataWidth-2], x = Time[0: self.dataWidth-1])
            self.p2.setData(y=Data[1][0: self.dataWidth-2], x = Time[0: self.dataWidth-1])
            self.p3.setData(y=Data[2][0: self.dataWidth-2], x = Time[0: self.dataWidth-1])
            self.p4.setData(y=Data[3][0: self.dataWidth-2], x = Time[0: self.dataWidth-1])
            
            if (self.l > 100):
                self.pb1.setOpts(height=self.DataMovingAverage[0][self.l-1])
                self.pb2.setOpts(height=self.DataMovingAverage[1][self.l-1])
                self.pb3.setOpts(height=self.DataMovingAverage[2][self.l-1])
                self.pb4.setOpts(height=self.DataMovingAverage[3][self.l-1])
               
            
            
            # FFT graphic
            if self.l > 1000:
                Y = abs(fft(self.Data[self.button_group.checkedId()-1][self.l-1000: self.l-2])) / 998
                X = 1/self.dt*np.linspace(0, 1, 998)
                self.FFT = (1-0.85)*Y + 0.85*self.FFT
                self.p10.setData(y=self.FFT[2: int(len(self.FFT)/2)], x=X[2:int(len(X)/2)]) 
                    
    # Values for butterworth bandpass filter
    def butter_bandpass(self, lowcut, highcut, fs, order = 4):
        nyq = 0.5 * fs
        low = lowcut / nyq
        high = highcut / nyq
        b, a = butter(order, [low, high], btype = 'bandpass')
        return b, a
    # Butterworth bandpass filter
    def butter_bandpass_filter(self, data, lowcut, highcut, fs, order = 4):
        b, a = self.butter_bandpass(lowcut, highcut, fs, order=order)
        y = lfilter(b, a, data)
        return y
    # Values for butterworth bandstop filter
    def butter_bandstop(self, lowcut, highcut, fs, order = 2):
        nyq = 0.5 * fs
        low = lowcut / nyq
        high = highcut / nyq
        b, a = butter(order, [low, high], btype = 'bandstop')
        return b, a
    # Butterworth bandstop filter
    def butter_bandstop_filter(self, data, lowcut, highcut, fs, order = 4):
        b, a = self.butter_bandstop(lowcut, highcut, fs, order = order)
        y = lfilter(b, a, data)
        return y
    def movingAverage(self, i, data, alpha):
        wa = 2.0*self.fs*np.tan(3.1416*1/self.fs)
        HPF = (2*self.fs*(data - self.X0[i]) - (wa-2*self.fs)*self.Y0[i])/(2*self.fs+wa)
        self.Y0[i] = HPF
        self.X0[i] = data
        data = HPF
        if data < 0:
            data = -data
        self.MA[i][0] = (1 - alpha)*data + alpha*self.MA[i][0];
        self.MA[i][1] = (1 - alpha)*(self.MA[i][0]) + alpha*self.MA[i][1];
        self.MA[i][2] = (1 - alpha)*(self.MA[i][1]) + alpha*self.MA[i][2];
        return self.MA[i][2]*4
    # Change gain
    def _on_radio_button_clicked(self, button):
        if self.monitor.COM != '':
            self.monitor.ser.write(bytearray([button.Value]))
    # Exit event
    def closeEvent(self, event):
        self.f.close()
        self.monitor.ser.close()
        event.accept()
# Serial monitor class
class SerialMonitor(QtCore.QThread):
    bufferUpdated = QtCore.pyqtSignal(bytes)
    # Custom constructor
    def __init__(self, COM, baudRate):
        QtCore.QThread.__init__(self)
        self.running = False
        self.filter = False
        self.COM = COM
        self.baudRate = baudRate
        self.baudRate = baudRate
        self.checkPort = 1
    # Listening port
    def run(self):
        while self.running is True:
            while self.COM == '': 
                ports = serial.tools.list_ports.comports(include_links=False)
                for port in ports :
                    self.COM = port.device
                if self.COM != '':
                    time.sleep(0.5)
                    self.ser = serial.Serial(self.COM, self.baudRate)
                    self.checkPort = 0
            while self.checkPort:
                ports = serial.tools.list_ports.comports(include_links=False)
                for port in ports :
                    if self.COM == port.device:
                        time.sleep(0.5)
                        self.ser = serial.Serial(self.COM, self.baudRate)
                        self.checkPort = 0
                   
            # Waiting for data
            while (self.ser.inWaiting() == 0):
                pass
            # Reading data
            msg = self.ser.read( self.ser.inWaiting() )
            if msg:
                #Parsing data
                self.bufferUpdated.emit(msg)
                time.sleep(0.1)
                
# Starting program       
if __name__ == '__main__':
    app = QtCore.QCoreApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    window = GUI()
    window.show()
    window.start()
    sys.exit(app.exec_())

Отредактировано serversss (Апрель 24, 2021 15:00:15)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version