Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QFrame with layout and comboBoxes insight => setStylesSheet calls index method of QAbstractItemModel of connected comboBoxes



  • Hello,
    I have several QFrames with each a vertical layout containing some QComboBoxes. The comboBoxes get the data from a QAbstractItem Model. I use the enterEvent method to change the styleSheet of the QFrame for highlighting the Frame, that is currently used (Where the mouse pointer is in) and the leaveEvent for reverting back the styleSheet to the standard one.

    I just change the border width and color.

    Now I have the following issue. When setting the styleSheet, the index method of the QAbstractItemModels (that are linked) to the comboBox are is called, and not only once, it occurs all the time and slows down the application significantly. I used a profiling tool to figure out, that the index method is called about 800,000 times during 15 secs moving the mouse pointer over the frames. Without changing the stylesheet, the index method is called only about 50,000 times, which is still quite a lot but compared to 800k it is not much.

    I had already the idea that it is the result of changing the width of the frame. But also when I keep the width always the same, the result is still the same.

    So, what is an appropriate way to achieve what I want: Changing the frame style when entering without such a huge performance decrease. I am happy about every hint.

    Thanks
    Daniel


  • Lifetime Qt Champion

    Hi,

    Can you provide a minimal compilable example that shows that behaviour ?



  • Creating an example is rather time intensive, thus I do not want to do it now. My question was more about the general understanding, when the index and data method of QAbstractItemModels are called. I expected that this will happen only when you interact directly with the corresponding ComboBox/Listview. But obviously, this happens on much more situations. How to figure out what signals or evants will interact with the model.

    By the way, I am working with PyQt.

    Does this help a bit more?
    Daniel


  • Lifetime Qt Champion

    AFAIK, PyQt should have no impact on that.

    The high number of calls are indeed pretty surprising. What might happen is that there are several changes of sizes due to the change of style sheet. Not knowing how many combo boxes you have and what your GUI looks like, it's pretty much impossible to guess what is happening.



  • Hey, sorry for my late reply.
    I also thought already that it might be because of the size change. So I tried already to keep the border width constant at 3px. However, just setting border-color in the style sheet does not have an effect (see last code snippet). I have to use the border property where I have to set the width, style and color. So I always have to set a new width and maybe even if I always keep 3px, it resets the with and recalculates the size of the content inside the frame.

    on enter event I use (CardInnerFrame is the name of the class I use. It is a subclass of QFrame)

    self.setStyleSheet("CardInnerFrame {"
                               "border: 3px solid rgb(85,142,213);}")
    

    on leave I use:

    self.setStyleSheet("CardInnerFrame {"
                               "border: 3px solid rgb(160,160,160);}")
    

    I would prefer to use to set only the color:

    self.setStyleSheet("CardInnerFrame {"
                               "border-color: rgb(160,160,160);}")
    

    But that one has no effect.

    Thanks for your help.
    Daniel



  • Ah ja, forgot to mention about the GUI. It is simply a frame with varying number of comboBoxes. But you realize a significant performance loss with let's say more than 5 comboBoxes in the the frame. Please find attached a screenshot of the frame.

    0_1535525613199_Frame.PNG


  • Lifetime Qt Champion

    Hi
    If you suspect its due to stylesheet usage, you see this performance drop, why
    not just paint the effect yourself in paintEvent since u already subclassed the frame.
    it is very little code

      QStyleOptionFrame opt;
        initStyleOption(&opt);
        style()->drawControl(QStyle::CE_ShapedFrame, &opt, p, this);
    

    https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qframe.cpp.html#_ZN6QFrame9drawFrameEP8QPainter



  • @mrjj Sorry that I did not answer for so long. Was totally busy with other important stuff that I could not further focus on this. But now I am back on this topic. I like the idea to simply paint it on my own. But actually I am a little bit over-strained with it. I never painted something on my own before, but I would really like to learn it.

    So, here is what I want to achieve. When I enter the frame, the grey frame should get blue plus I want to change the line width of the frame.

    What I have: A Class that subclasses the Qframe class where I reimplemented the enterEvent method, to catch the the events, when the mouse pointer enters the frame. What to do now? Creating a painter from QtGui.QPainter? The few lines you added did not help so much.

    I am using Qt for python, but I guess it will be more or less the same as in normal Qt, right? I appreciate your help.

    Daniel


  • Lifetime Qt Champion

    @Dagginio
    Hi
    Using python should be exactly the same.
    So in enterEvent you set a variable to know mouse has enter and clear
    it on the leave event.
    Then you override paintEvent
    and there you make a QPainter and draw the frames the way you want.

    (example) disclaimer. not a pyt user :)

     def paintEvent(self, event):
            painter = QPainter(self)
            painter.drawLine(0, 10, 10, 10)
    


  • @mrjj thanks. That is what I was thinking of. However, when set a variable that the mouse entered, it will not trigger the painting itself. Is a event function callable? Can I call the paintEvent method from the enterEvent method? And assuming I painted already a blue frame. Do I have to remove that blue frame before I paint a grey one?

    Daniel


  • Lifetime Qt Champion

    @Dagginio
    Hi
    just call update() to have it refresh when "status" changes.

    -Do I have to remove that blue frame before I paint a grey one?
    depends if you have autofillbackground on widget on.
    in that case it will be cleared default.
    else u might have to. try without and see