Tuesday, March 19, 2024

Building a Step-by-Step Progress Window with PyQt6

 Have you ever needed to guide users through a series of steps within an application? Creating a step-by-step progress window can be an effective way to accomplish this. In this tutorial, we'll learn how to build a simple yet powerful step-by-step progress window using PyQt6, a popular Python framework for creating desktop applications with graphical user interfaces.


Introduction to the Program

We'll create a PyQt6 application with the following features:

  1. A main progress bar indicating overall progress.
  2. A secondary progress bar that appears during specific steps.
  3. Buttons for navigation (Back, Next, Skip, Cancel).
  4. Dynamic labels indicating the current step and instructions.

Setting Up the Environment

First, let's ensure you have PyQt6 installed. If not, you can install it using pip:

pip install PyQt6

Now, let's dive into the code!

Step 1: Importing Necessary Libraries

We start by importing the required libraries for our application. These include PyQt6 widgets, QPushButton, QProgressBar, QLabel, and QTimer.

Step 2: Creating the MainWindow Class

We define a class MainWindow that inherits from QWidget, which is the base class for all user interface objects in PyQt6.

Step 3: Initializing the Window and Widgets

We set up the window title, geometry, and various widgets such as progress bars, buttons, and labels within the __init__ method.

Step 4: Implementing Navigation Functions

We define functions for navigation: next_step, previous_step, skip_step, and cancel. These functions handle the logic for advancing to the next step, going back to the previous step, skipping a step, and canceling the process, respectively.

Step 5: Updating Step Labels

We create a function update_step_label to update the step labels dynamically based on the current step.

Step 6: Updating Task Labels

Another function update_task_label updates the task labels, which display information about the current task being performed.

Step 7: Updating Secondary Progress

We use a QTimer to update the secondary progress bar dynamically during specific steps. This progress bar appears and disappears as needed.

Step 8: Executing the Application

Finally, we instantiate the QApplication, create an instance of the MainWindow class, and show the window using window.show(). We then run the application's event loop using app.exec().

Conclusion

In this tutorial, we've created a step-by-step progress window using PyQt6. This application can be useful for guiding users through a series of tasks or operations, providing clear instructions and visual feedback along the way. You can further customize this application by adding more steps, integrating additional features, or enhancing the user interface to fit your specific requirements.

Feel free to explore and extend the functionality of this application to suit your needs. Happy coding!

Here is the complete program listing:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QProgressBar, QLabel
from PyQt6.QtCore import QTimer


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Progress Window")
        self.setGeometry(100, 100, 800, 480)

        self.progress_bar_main = QProgressBar(self)
        self.progress_bar_main.setGeometry(100, 80, 600, 40)
        self.progress_bar_main.setMinimum(0)
        self.progress_bar_main.setMaximum(100)
        self.progress_bar_main.setValue(0)

        self.label_task = QLabel("", self)
        self.label_task.setGeometry(100, 330, 600, 20)

        self.progress_bar_secondary = QProgressBar(self)
        self.progress_bar_secondary.setGeometry(100, 360, 600, 20)
        self.progress_bar_secondary.setMinimum(0)
        self.progress_bar_secondary.setMaximum(5)
        self.progress_bar_secondary.setValue(0)
        self.progress_bar_secondary.setVisible(False)

        self.back_button = QPushButton("Back", self)
        self.back_button.setGeometry(350, 420, 100, 30)

        self.next_button = QPushButton("Next", self)
        self.next_button.setGeometry(460, 420, 100, 30)
        self.next_button.setEnabled(True)

        self.skip_button = QPushButton("Skip", self)
        self.skip_button.setGeometry(570, 420, 100, 30)
        self.skip_button.setEnabled(False)

        self.cancel_button = QPushButton("Cancel", self)
        self.cancel_button.setGeometry(680, 420, 100, 30)

        self.next_button.clicked.connect(self.next_step)
        self.back_button.clicked.connect(self.previous_step)
        self.skip_button.clicked.connect(self.skip_step)
        self.cancel_button.clicked.connect(self.cancel)

        self.step = 0

        self.label_step = QLabel("Step 1: Select file", self)
        self.label_step.setGeometry(100, 130, 600, 40)
        self.label_step.setStyleSheet("font-size: 24pt; font-family: Helvetica;")

        self.label_instruction = QLabel("Instructions: Select a file to proceed", self)
        self.label_instruction.setGeometry(100, 170, 600, 20)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_secondary_progress)

    def next_step(self):
        self.step += 1
        if self.step > 5:
            self.close()  # Finish the program when all steps are completed
        else:
            self.progress_bar_main.setValue((self.step + 1) * 20)

            if self.step == 5:
                self.next_button.setText("Finish")
                self.skip_button.setEnabled(False)
            else:
                self.next_button.setEnabled(True)
                self.back_button.setEnabled(True)
                self.skip_button.setEnabled(True)

            #self.update_step_label()
            self.update_task_label()
            self.label_task.setVisible(True)
            self.progress_bar_secondary.setVisible(True)
            self.progress_bar_secondary.setValue(0)
            self.next_button.setEnabled(False)
            self.back_button.setEnabled(False)
            self.timer.start(1000)

    def update_secondary_progress(self):
        value = self.progress_bar_secondary.value()
        if value < 5:
            self.progress_bar_secondary.setValue(value + 1)
        else:
            self.timer.stop()
            self.next_button.setEnabled(True)
            self.back_button.setEnabled(True)
            self.progress_bar_secondary.setVisible(False)
            self.label_task.setVisible(False)
            
            self.update_step_label()  # Update labels after the second progress bar finishes

    def previous_step(self):
        self.step -= 1
        if self.step < 0:
            self.step = 0
        self.progress_bar_main.setValue((self.step + 1) * 20)

        if self.step == 0:
            self.back_button.setEnabled(False)
        else:
            self.back_button.setEnabled(True)
            self.next_button.setEnabled(True)
            self.skip_button.setEnabled(True)

        self.update_step_label()

    def skip_step(self):
        self.step += 1
        if self.step > 5:
            self.step = 5
        self.progress_bar_main.setValue((self.step + 1) * 20)

        if self.step == 5:
            self.next_button.setText("Finish")
            self.skip_button.setEnabled(False)
        else:
            self.next_button.setEnabled(True)
            self.back_button.setEnabled(True)
            self.skip_button.setEnabled(True)

        self.update_step_label()

    def cancel(self):
        self.close()

    def update_step_label(self):
        self.instructions = [
            "Select file",
            "Check compatibility",
            "Confirm",
            "Apply filters",
            "Save data","Finish!"
        ]
        self.label_step.setText(f"Step {self.step + 1}: {self.instructions[self.step]}")
        self.label_instruction.setText(f"Instructions: {self.instructions[self.step]}")

    def update_task_label(self):
        self.tasks = [
            "Checking file...",
            "Checking compatibility...",
            "Confirming...",
            "Applying filters...",
            "Saving data..."
        ]
        if self.step < 5:
            self.label_task.setText(f"{self.tasks[self.step]}")
        


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

No comments:

Post a Comment