python-qt5 icon indicating copy to clipboard operation
python-qt5 copied to clipboard

PyQt5 shows white border while displaying image in full screen

Open ammar3010 opened this issue 5 days ago • 0 comments

I'm using PyQt5 to build a UI for my computer vision app. The app has six pages, and on the fourth page, I receive video frames from a backend thread that runs when the app reaches this page. However, I'm having trouble getting the QLabel on the fourth page to resize correctly and display the video frames in full screen.

Here is the code snippet that sends frames to the frontend:

qImg = QImage(combined_frame2.data, combined_frame2.shape[1], combined_frame2.shape[0], QImage.Format_RGB888)
self.update_video_frame.emit(qImg.rgbSwapped())

Here is the class for the fourth page:

class FourthPage(QWidget):
    recording_finished = pyqtSignal()
    switch_to_fifth_page = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.initUI()

    def initUI(self):
        self.setContentsMargins(0, 0, 0, 0)

        # Set up the video label to take up the entire space
        self.video_label = QLabel(self)
        self.video_label.setAlignment(Qt.AlignCenter)
        self.video_label.setStyleSheet("background-color: transparent;")  # Optional: Set transparent background

        # Set video_label to cover the entire widget
        self.video_label.setGeometry(0, 0, self.width(), self.height())

        self.click_player = QMediaPlayer()

        # Install event filter to detect clicks on the video label
        self.video_label.installEventFilter(self)

    def resizeEvent(self, event):
        # Ensure video_label resizes with the widget
        self.video_label.setGeometry(0, 0, self.width(), self.height())

    def stopRecording(self):
        self.recording_finished.emit()

    def playClickSound(self):
        self.click_player.setMedia(QMediaContent(QUrl.fromLocalFile("/path/to/Click.mp3")))
        self.click_player.setVolume(100)
        self.click_player.play()
    
    def handleMouseClick(self):
        self.stopRecording()
        self.playClickSound()
        QTimer.singleShot(500, self.switch_to_fifth_page.emit)

    def eventFilter(self, source, event):
        if event.type() == QEvent.MouseButtonPress and source == self.video_label:
            self.handleMouseClick()
            return True
        return super().eventFilter(source, event)

Here is the main class that controls the flow of the app:

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.stack = QStackedWidget(self)
        self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
        self.setGeometry(0, 0, 800, 600)
        self.showFullScreen()
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout(self)
        self.introPage = IntroPage()
        self.firstPage = FirstPage()
        self.secondPage = SecondPage()
        self.thirdPage = ThirdPage()
        self.fourthPage = FourthPage()
        self.startRecordingPage = StartRecordingPage()
        self.fifthPage = FifthPage()
        self.sixthPage = SixthPage()
        self.stack.addWidget(self.introPage)
        self.stack.addWidget(self.firstPage)
        self.stack.addWidget(self.secondPage)
        self.stack.addWidget(self.thirdPage)
        self.stack.addWidget(self.startRecordingPage)
        self.stack.addWidget(self.fourthPage)
        self.stack.addWidget(self.fifthPage)
        self.stack.addWidget(self.sixthPage)
        layout.addWidget(self.stack)
        self.setLayout(layout)

        self.introPage.switch_to_first_page.connect(self.showFirstPage)
        self.firstPage.switch_to_second_page.connect(self.showSecondPage)
        self.secondPage.switch_to_third_page.connect(self.showThirdPage)
        self.thirdPage.switch_to_recording_page.connect(self.showStartRecordingPage)
        self.startRecordingPage.switch_to_fourth_page.connect(self.showFourthPage)
        self.fourthPage.switch_to_fifth_page.connect(self.showFifthPage)
        self.fourthPage.recording_finished.connect(self.stopRecording)
        self.sixthPage.restart_requested.connect(self.restartApp)
        self.sixthPage.exit_requested.connect(self.exitApp)

        self.backend_thread = BackendThread()
        self.backend_thread.update_video_frame.connect(self.update_video_frame)
        self.backend_thread.finished.connect(self.showSixthPage)
        self.showFullScreen()

    def stopRecording(self):
        self.backend_thread.stop_recording = True

    def showFirstPage(self):
        self.stack.setCurrentWidget(self.firstPage)

    def showSecondPage(self):
        self.stack.setCurrentWidget(self.secondPage)

    def showThirdPage(self):
        self.stack.setCurrentWidget(self.thirdPage)

    def showStartRecordingPage(self):
        self.stack.setCurrentWidget(self.startRecordingPage)

    def showFourthPage(self):
        self.stack.setCurrentWidget(self.fourthPage)
        self.backend_thread.start()

    def showFifthPage(self):
        self.stack.setCurrentWidget(self.fifthPage)
        QTimer.singleShot(100, self.run_processing)  # Delay the processing to allow the UI to update

    def showSixthPage(self):
        self.stack.setCurrentWidget(self.sixthPage)
        self.display_results()

    def run_processing(self):
        self.backend_thread.run_processing()

    def update_video_frame(self, qImg):
        self.fourthPage.video_label.setPixmap(QPixmap.fromImage(qImg))

    def display_results(self):
        font = self.sixthPage.results_label.font()
        font.setPointSize(14)
        self.sixthPage.results_label.setFont(font)
        self.sixthPage.results_label.setWordWrap(True)
        self.sixthPage.results_label.setFixedWidth(self.width() - 20)
        self.sixthPage.results_label.setText(
            f"Frame count: {self.backend_thread.frame_count}\n"
            f"FPS: {self.backend_thread.fps}\n"
            f"Transcript: {self.backend_thread.transcript}\n"
            f"Objects List: {self.backend_thread.objects_list}\n"
            f"Phrase Timestamps: {self.backend_thread.phrase_timestamps}\n"
        )

    def restartApp(self):
        self.stack.setCurrentWidget(self.introPage)

    def exitApp(self):
        QApplication.instance().quit()

Problem: The QLabel on the fourth page does not resize correctly to display the video frames in full screen. I've tried different spacing and margin options, but none of them work. It gives white borders on left, right and top

Question: How can I ensure that the QLabel resizes correctly and displays the video frames in full screen on the fourth page?

Any help or suggestions would be greatly appreciated!

ammar3010 avatar Jul 03 '24 12:07 ammar3010