Charty
Charty

Reputation: 11

Issue with PySide6 QtCharts with multiple QHorizontalBarSeries using the same x-axis

Adding several QHorizontalBarSeries to my QChart using the same x-axis (QValueAxis) did not add the bars relative to the values on the x-axis. Instead, all Series I've added have their biggest value fill the entire x-axis.

Example data:

BLOCKED:    {'Category 1': 146, 'Category 2': 31,   'Category 3': 0,   'Category 4': 3,  'Category 5': 14,  'Category 6': 0}
FAIL:       {'Category 1': 100, 'Category 2': 52,   'Category 3': 6,   'Category 4': 0,  'Category 5': 26,  'Category 6': 3}
PASS:       {'Category 1': 981, 'Category 2': 1176, 'Category 3': 462, 'Category 4': 81, 'Category 5': 240, 'Category 6': 129}
UNEXECUTED: {'Category 1': 3,   'Category 2': 39,   'Category 3': 0,   'Category 4': 0,  'Category 5': 0,   'Category 6': 0}
WIP:        {'Category 1': 1,   'Category 2': 1,    'Category 3': 0,   'Category 4': 0,  'Category 5': 0,   'Category 6': 0}

In this example I create one series for each status (BLOCKED, FAIL, PASS, UNEXECUTED, WIP).

The highest value is in PASS - Category 2. Therefore the x-axis should show every bar in relation to these values.

My result looks like this:

Example Bar Chart

I have tried attaching the x-axis to each series as well as the chart, and the axis at least shows the scale I want, but still all but one series ignore the scale I want to achieve.

So far my code for chart generation looks something like this

        # Extract unique ExecutionStatus values
        unique_statuses = sorted(self.testexecutions["ExecutionStatus"].unique())
        unique_components = sorted(self.testexecutions["Components"].unique(), reverse=True)

        self.__chart.setTitle("ExecutionStatus By Component")

        # Create a category axis for the y-axis (Components)
        y_axis = QtCharts.QBarCategoryAxis()
        y_axis.setCategories(unique_components)
        self.__chart.addAxis(y_axis, Qt.AlignLeft)

        # Create a value axis for the x-axis (Number of TestExecutions)
        x_axis = QtCharts.QValueAxis()

        # Group by both 'ExecutionStatus' and 'Components' columns and count occurrences
        grouped_data = self.testexecutions.groupby(["ExecutionStatus", "Components"]).size().reset_index(name="Count")

        # Convert the grouped data to a dictionary
        status_component_amount_dict = {}

        for status in unique_statuses:
            status_data = grouped_data[grouped_data["ExecutionStatus"] == status]
            status_component_amount_dict[status] = dict(zip(status_data["Components"], status_data["Count"]))

        max_bar_value = self.__get_maximum_bar(status_component_amount_dict)
        print(f"max_bar_value: {max_bar_value}")

        x_axis.setRange(0, max_bar_value)
        x_axis.setLabelFormat("%i")

        self.__chart.addAxis(x_axis, Qt.AlignBottom)

        for status in sorted(status_component_amount_dict.keys()):
            print(f"{status}: {status_component_amount_dict[status]}")
            series = QtCharts.QHorizontalBarSeries()

            bar_set = QtCharts.QBarSet(status)
            for component in unique_components:
                bar_set.append(status_component_amount_dict[status].get(component, 0))

            series.append(bar_set)

            series.attachAxis(x_axis)
            series.attachAxis(y_axis)

            self.__chart.addSeries(series)

        # Create a legend
        legend = self.__chart.legend()
        legend.setAlignment(Qt.AlignTop)
        self.chart_view.setChart(self.__chart)

I still don't know why for example the bars for the status 'WIP' in 'Category 1' fill the entire x-axis, although their value is 1 and the x-axis has the range from 0 to 1176.

Upvotes: 1

Views: 168

Answers (0)

Related Questions