I am writing my IDE, and according to my plan, it should be possible to work directly with Stack Overflow (in the future) and open files of various formats (including videos). Here is the code of the three scripts in which all the work takes place: main.py: import sys import os from PyQt5.QtWidgets import ( QApplication, QMainWindow, QTextEdit, QVBoxLayout, QWidget, QAction, QFileDialog, QPushButton, QStackedWidget, QListWidget, QHBoxLayout, QTabWidget, QToolButton, QTabBar, QSplitter ) from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtCore import Qt, QUrl from PyQt5.QtGui import QFont, QIcon import subprocess import json import file_filters from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent from PyQt5.QtMultimediaWidgets import QVideoWidget class VideoTab(QWidget): def __init__(self, name, folder): super().__init__() self.name = name self.folder = folder self.path = os.path.join(folder, name) self.check_path = folder + '/' + name self.vLayout = QVBoxLayout(self) self.video_widget = QVideoWidget() self.pause_but = QPushButton("Play") self.pause_but.clicked.connect(self.pause_but_acc) self.vLayout.addWidget(self.video_widget, stretch=1) self.vLayout.addWidget(self.pause_but, alignment=Qt.AlignCenter) self.isPlaying = False self.player = QMediaPlayer() self.player.setVolume(100) self.player.setVideoOutput(self.video_widget) self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.path))) self.video_widget.show() def pause_but_acc(self): if not self.isPlaying: self.player.play() self.isPlaying = True self.pause_but.setText("Pause") else: self.player.pause() self.isPlaying = False self.pause_but.setText('Play') def close_tab(self): try: self.player.pause() except: pass self.player.setVideoOutput(None) self.vLayout.removeWidget(self.video_widget) self.video_widget.setParent(None) self.video_widget.deleteLater() self.video_widget = None class PythonIDE(QMainWindow): def __init__(self): super().__init__() self.so_engine = QWebEngineView() self.so_engine.setUrl(QUrl("https://stackoverflow.com")) self.last_tab = None self.save_time = 10000 self.current_file = None self.new_file_status = False self.initUI() def initUI(self): self.setWindowTitle("SIDE") self.setGeometry(100, 100, 800, 600) self.mainWin = QStackedWidget() self.editor_container = QWidget() self.splited_editor_container = QSplitter() self.editor_widget = QSplitter(Qt.Vertical) self.editor_underwidget = QTabWidget() self.editor_underwidget.setMovable(True) self.folder_group = QWidget() self.folder_layout = QVBoxLayout() self.folder_but_layout = QHBoxLayout() self.folder_widget = QListWidget() self.setFolder_but = QPushButton("F") self.setFolder_but.clicked.connect(self.openFolder) self.setFolder_but.setFixedSize(30, 30) self.newFile_folder_but = QPushButton("+") self.newFile_folder_but.setFixedSize(30, 30) self.folder_but_layout.addWidget(self.setFolder_but, alignment = Qt.AlignLeft) self.folder_but_layout.addWidget(self.newFile_folder_but, alignment = Qt.AlignRight) self.folder_layout.addLayout(self.folder_but_layout) self.folder_layout.addWidget(self.folder_widget) self.folder_group.setLayout(self.folder_layout) self.editor_widget.addWidget(self.editor_underwidget) self.splited_editor_container.addWidget(self.folder_group) self.splited_editor_container.addWidget(self.editor_widget) layout = QVBoxLayout() layout.addWidget(self.splited_editor_container) self.editor_container.setLayout(layout) self.so_container = QWidget() self.so_layout = QVBoxLayout() self.so_layout.addWidget(self.so_engine) self.so_container.setLayout(self.so_layout) self.mainWin.addWidget(self.editor_container) self.mainWin.addWidget(self.so_container) self.setCentralWidget(self.mainWin) self.mainWin.setCurrentWidget(self.editor_container) self.create_menu() def create_menu(self): self.menubar = self.menuBar() # menu "Tools" self.tools_menu = self.menubar.addMenu("Tools") self.editor_menu = QAction("Editor", self) self.editor_menu.triggered.connect(self.switch_to_editor) self.tools_menu.addAction(self.editor_menu) self.questions_menu = QAction('StackOverflow', self) self.questions_menu.triggered.connect(self.switch_to_questions) self.tools_menu.addAction(self.questions_menu) def switch_to_editor(self): self.mainWin.setCurrentWidget(self.editor_container) import gc gc.collect() def switch_to_questions(self): self.mainWin.setCurrentWidget(self.so_container) self.so_layout.addWidget(self.so_engine) def openFolder(self): self.new_file_status = False self.current_folder = QFileDialog.getExistingDirectory() self.setFolder_widget() def setFolder_widget(self): try: self.working_files = os.listdir(self.current_folder) self.folder_widget.clear() self.folder_widget.addItems(self.working_files) self.folder_widget.itemClicked.connect(self.process_item) except: pass def process_item(self, item): file_filters.process_file(item.text(), self.current_folder, self.editor_underwidget) extensions = {"text": {"text": [".txt", ".json"], "scripts": [".py", ".pyw", ".pyi", ".c", ".h", ".cs", ".cpp"," .cxx", ".hpp", ".java", ".class", ".js", ".html"]},"image": [".png", ".jpg", "jpeg"],"audio": [".mp3", ".wav", ".aac", ".ogg"],"video": [".mp4", ".avi"],"anims": [".gif", ".mng"]} def process_file(name, folder, widget): current_file = str(folder + "/" + name) is_FileIn_widget = False wid = False for ind in range(widget.count()): tab = widget.widget(ind) if hasattr(tab, 'check_path'): if tab.check_path == current_file: is_FileIn_widget = True widget.setCurrentIndex(ind) break else: print('skip') if is_FileIn_widget: print('!') else: print('*') if not is_FileIn_widget: if not wid: for ext in extensions["video"]: if name.endswith(ext): wid = VideoTab(name, folder) try: index = widget.addTab(wid, name) close_button = QToolButton() close_button.setIcon(QIcon("close_icon.png")) close_button.setFixedSize(16, 16) close_button.clicked.connect(lambda: close_tab(widget, widget.tabText(index), name, index)) widget.tabBar().setTabButton(index, QTabBar.RightSide, close_button) widget.setCurrentIndex(index) except Exception as e: print('troubles:', e) def close_tab(tab_widget, text, name, indx): print(f'close button closed with name {name} and index {indx}') for ind in range(tab_widget.count()): if tab_widget.tabText(ind) == name: tab = tab_widget.widget(ind) if hasattr(tab, 'close_tab'): save_close = getattr(tab, 'close_tab') save_close() else: print('error: close function did not found') tab.setParent(None) tab.deleteLater() tab_widget.removeTab(ind) break if __name__ == "__main__": app = QApplication(sys.argv) ide = PythonIDE() ide.showMaximized() sys.exit(app.exec_()) but when I open the videotab, and then go to the stack overflow tab, the application starts to freeze wildly and glitch - the widgets fit on top of each other, the work slows down, the fps drops. However, these problems do not disappear even after closing the videotab, only after restarting the application. Also, by the way, there is a very unpleasant visual bug that appears even when QWebEngineView is not configured - this is the list of tabs on top of QTabWidget, when creating a videotab, it slides off the screen for one millisecond. I somehow tried to add a dynamic loading and unloading system, in which, after switching tabs, the contents of inactive ones are deleted and then restored (this is not here, since I have not completed this system yet, but I doubt it will help). As a result, the bug disappears only if you do not use one of the elements - a video tab or a window with a website. I say right away that I will not delete either, because that, in my opinion, is the advantage of my program. Therefore, if they are somehow incompatible, please say so. I also specifically left the process-file function because it causes the aforementioned small visual bug, and also makes the main bug worse by about ~5-10% My PC: I have Windows 10 Pro, Ryzen 3 3200G with Vega 8 onboard, and 32 GB ddr4 RAM Upd. I switched to PyQt6 and everything worked. The issue can be considered resolved. Continue reading...