[Python] Conflict between QWebEngineView and QVideoWidget PyQt5? [closed]

Discussão em 'Python' iniciado por Stack, Abril 18, 2025.

  1. Stack

    Stack Membro Participativo

    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...

Compartilhe esta Página